Javascript-форум (https://javascript.ru/forum/)
-   jQuery (https://javascript.ru/forum/jquery/)
-   -   Универсальный GrayScale с плавной работой (затухание и проявление), принцип работы? (https://javascript.ru/forum/jquery/35765-universalnyjj-grayscale-s-plavnojj-rabotojj-zatukhanie-i-proyavlenie-princip-raboty.html)

master_alf 21.02.2013 15:02

Универсальный GrayScale с плавной работой (затухание и проявление), принцип работы?
 
Приветствую.
Появилась задача сделать скрипт. который бы делал картинки на сайте серыми по-умолчанию (т.е. после загрузи страницы) и цветными при наведении мышкой. Универсального рецепта, который одинаково бы работал во всех браузерах (читай в IE тоже) - не нашел. Если кто-то знает такой скриптег - прошу подсказать. Но это лишь быстрый способ решения проблемы...

Отрыв один такой скрипт, который работает не особо универсально, я заглянул внутрь и понял, что большой проблемы его поправить - нет. Но понимания джаваскрипта у меня полного нет. И проблема в том, что не понимаю какого рода информацию мне нужно искать... а вопрос вот в чем.

Я могу сделать черно-белую картинку по наведению/загрузке страницы - не проблема. Но не понимаю как сделать плавный переход от черно-белого состояния к цветному. Каким образом осуществляются подобные плавные переходы? Наложить невидимую цветную картинку поверх серой, и просто плавно проявлять? Т.е. через opacity? Или есть более адекватные и красивые методы?

Если предложенный мною вариант адекватен, то подскажите, пожалуйста, как в Jquery работать с таймерами? Ибо эту часть понимаю плохо :(

Спасибо.

ksa 21.02.2013 15:31

Цитата:

Сообщение от master_alf
предложенный мною вариант адекватен

Вполне... :yes:

Цитата:

Сообщение от master_alf
как в Jquery работать с таймерами?

Там есть эффекты, например
http://jquery-docs.ru/Effects/animat...easingcallback

master_alf 22.02.2013 14:46

Почти написал, судя по всему... но прошу помощи. Не получается собрать всё воедино. здесь выложил результат работы, вопросы следующие:
  1. Гугл Хром выдает багу, если я создание черно-белых копий вешаю на document.ready(). гугл показал, что ему не нравится что картинки не догрузились. Как победить - не понял, потому пока перевесил всё на кнопку.
  2. Не могу понять как правильно в функции прицепленные на hover передать указатель на ту картинку, на которую будет наведена мышь...
Как это всё победить? :(

ksa 22.02.2013 15:02

Цитата:

Сообщение от master_alf
Как это всё победить?

С помощью простых тестовых примеров, которые выкладывай прямо тут...

master_alf 22.02.2013 15:15

Как раз проблема в том, что по-отдельности у меня все работало :(
<script type="text/javascript">
        $(document).ready(function() { 
               $('.gray').hover(hoverIn(this), hoverOut());});
       });
    </script>

Не могу понять как правильно передать указатель на картинку для функции hover, если я передаю this - то передается ссылка на файл (на локальном компе ссылка передается именно на файл html. Вида file:///d:/garbage/.../file.html
Если не передаю ничего, а просто в функции вызываемой hover-ом используют $(this).animate() - то скрипт падает с ошибками. Вывод alert(this) показывает object window.
Как передать внутрь функции вызывающей анимацию ссылку на конкретную картинку? Ибо селектором получить нужный элемент - нереально. На сайте картинок для которых пишется скрипт будет много, и взять конкретную по селектору - невозможно.

master_alf 22.02.2013 15:40

Вопрос снят - нашел косяк. И в целом сделал иначе - перевесил привязку hoverа на момент создания элемента. Плюс, как оказалось, нужно делать не
$('.gray').hover(hoverIn(), hoverOut());
а
$('.gray').hover(hoverIn, hoverOut);


Теперь разбираюсь с вызовом функции в правильный момент...

ksa 22.02.2013 21:28

Цитата:

Сообщение от master_alf
как оказалось, нужно делать не
$('.gray').hover(hoverIn(), hoverOut());
а
$('.gray').hover(hoverIn, hoverOut);

Можно и так

$('.gray').hover(function (){
   hoverIn();
}, function (){
   hoverOut();
});

danik.js 23.02.2013 12:04

Цитата:

Сообщение от ksa
Можно и так

$('.gray').hover(function (){
   hoverIn();
}, function (){
   hoverOut();
});


А еще можно так:

$('.gray').hover(function (){
   (function(){ hoverIn() })();
}, function (){
   (function(){ hoverOut() })();
});

Но.. только зачем?

ksa 23.02.2013 13:17

Цитата:

Сообщение от danik.js
только зачем?

В моём случае в те функции можно передать параметры.

danik.js 23.02.2013 13:35

Цитата:

Сообщение от ksa
В моём случае в те функции можно передать параметры.

$('.gray').hover(
    $.proxy(hoverIn, this, arg1, arg2)),
    $.proxy(hoverOut, this, arg1, arg2))
);

ES5:
$('.gray').hover(
    hoverIn.bind(this, arg1, arg2),
    hoverOut.bind(this, arg1, arg2)
);

Но да, анонимные функции тож довольно удобно.

master_alf 25.02.2013 11:02

Учебный вариант заработал во всех нужных браузерах IE 7+ (6го нет что бы проверить, но и там должно работать), FF, Opera, Chrome, Safari. Посмотреть можно здесь, а скачать здесь (не нашел как файл к сообщению прикрепить).

Господа спецы, прошу, по-возможности, глянуть как оно работает. Если есть какие-то кривости в коде, опасные места - подскажите, пожалуйста. Если можно - с общими советами как это исправить (работать вместо меня не прошу, но полезные советы - это хорошо).
Я бы хотел выложить данный плагин для свободного использования, но для этого его нужно довести до совершенства. А в JS я весьма слаб... потому рассчитываю на вашу помощь :)

danik.js 25.02.2013 12:01

Давай сюды код тогда.

master_alf 25.02.2013 12:35

Вызов плагина, параметром передается селектор, для которого нужно применить grayScale.
$(document).ready(function() {
            makeGray('body div img');
        });


Подключаемый файл, где собственно описана вся логика работы.
var grayTryCount = 0;
var timerID = false;
function makeGray(selector) {
    if (grayTryCount <= 3) {
        grayTryCount +=1;
        $(selector).each(function(){
            if ((this.complete) && (!$(this).hasClass('makeGrayDone')) && (!$(this).hasClass('gray'))){
                makeCopy(this);
            } else {
                if (!timerID) {
                    timerID = setTimeout(function() {makeGray('body div img')}, 1000);
                }
            }
        });
    }
}
        
        function makeCopy(img) {
            var canvas2DSupported = !!window.CanvasRenderingContext2D;
            if (canvas2DSupported) {
                var newImg = makeCanvasCopy(img);
            } else { 
                var newImg = makeIMGCopy(img); 
            }
            var offset = $(img).offset();
            $(img).parent().append(newImg);
            $(img).addClass('makeGrayDone');
            $(newImg).offset(offset);
            $(newImg).hover(hoverIn, hoverOut);
        }
        
        function makeIMGCopy(imgObj) {
                var newImg = document.createElement('img');
                newImg.src = $(imgObj).attr('src');
                $(newImg).attr('class', 'gray');
                newImg.style.filter ='progid:DXImageTransform.Microsoft.BasicImage(grayScale=1)';
                
                return newImg;
        }
        
        function makeCanvasCopy(imgObj) {
            var newImg = document.createElement('img');

            var canvas = document.createElement('canvas');
            var canvasContext = canvas.getContext('2d');
            var imgW = imgObj.width;
            var imgH = imgObj.height;
            canvas.width = imgW;
            canvas.height = imgH;
            canvasContext.drawImage(imgObj, 0, 0);
            var imgPixels = canvasContext.getImageData(0, 0, imgW, imgH);
            
            for(var y = 0; y < imgPixels.height; y++){
                for(var x = 0; x < imgPixels.width; x++){
                    var i = (y * 4) * imgPixels.width + x * 4;
                    var avg = (imgPixels.data[i] + imgPixels.data[i + 1] + imgPixels.data[i + 2]) / 3;
                    imgPixels.data[i] = avg;
                    imgPixels.data[i + 1] = avg;
                    imgPixels.data[i + 2] = avg;
                }
            }

            canvasContext.putImageData(imgPixels, 0, 0, 0, 0, imgPixels.width, imgPixels.height);
            newImg.src = canvas.toDataURL();
            
            $(newImg).attr('class', 'gray');
            return newImg;
        }

        function createCanvas(imgObj) {
            var canvas = document.createElement('canvas');
            var canvasContext = canvas.getContext('2d');

            var imgW = imgObj.width;
            var imgH = imgObj.height;
            canvas.width = imgW;
            canvas.height = imgH;

            canvasContext.drawImage(imgObj, 0, 0);
            var imgPixels = canvasContext.getImageData(0, 0, imgW, imgH);

            for(var y = 0; y < imgPixels.height; y++){
                for(var x = 0; x < imgPixels.width; x++){
                    var i = (y * 4) * imgPixels.width + x * 4;
                    var avg = (imgPixels.data[i] + imgPixels.data[i + 1] + imgPixels.data[i + 2]) / 3;
                    imgPixels.data[i] = avg;
                    imgPixels.data[i + 1] = avg;
                    imgPixels.data[i + 2] = avg;
                }
            }

            canvasContext.putImageData(imgPixels, 0, 0, 0, 0, imgPixels.width, imgPixels.height);
            imgObj.src = canvas.toDataURL();
            //return canvas.toDataURL();
        }
        
        function hoverIn(obj) {
         $(this).animate({
                opacity: 0
                }, 
                {duration: 500, step: function(now, fx) {
                    // Every step of the opacity animation we'll get the current 
                    // opacity as the 'now' argument.
                    var opacity = Math.round(now * 100);
                    $(fx.elem).css('-ms-filter', 'progid:DXImageTransform.Microsoft.Alpha(Opacity=' + opacity + ')');
                    }
                  });
        }
        function hoverOut() {
            $(this).animate({
                opacity: 1
                }, 
                {duration: 500, step: function(now, fx) {
                    var opacity = Math.round(now * 100);
                    $(fx.elem).css('-ms-filter', 'progid:DXImageTransform.Microsoft.Alpha(Opacity=' + opacity + ')');
                    }
                  });
        }

Deff 25.02.2013 12:52

master_alf,
А картинка пока только с того же домена ?

master_alf 25.02.2013 12:57

Да, только с этого же домена.
Я, если честно, слабо представляю зачем нужно грузить картинки с других доменов и обрабатывать их подобным образом... но может это дело в слабой фантазии? :D
В принципе, если в готовом плагине лучше, что бы оно было - погуглю как делается. Встречал рецепты.

Deff 25.02.2013 12:59

master_alf,
На большинстве халявных сайтах и форумов, нет загрузки изо на текущий домен
Пример Укоз, mybb.ru

Deff 25.02.2013 13:01

Цитата:

Сообщение от master_alf
В принципе, если в готовом плагине лучше, что бы оно было - погуглю как делается. Встречал рецепты.

Лучше имхо отдельным расширением, связанным плагином
На хабре видал статейку, как реализуемо для свежих версий браузеров => http://habrahabr.ru/post/120917/

danik.js 25.02.2013 13:05

Цитата:

Сообщение от master_alf
makeGray('body div img');

1) body в селекторе ни к селу ни к городу. Бывают картинки вне body чтоли?
2) Раз jQuery, то и оформи как плагин к jQuery. Чтобы вызов был через $('div img').makeGray()

Цитата:

Сообщение от master_alf
var grayTryCount = 0;
var timerID = false;

Срём в глобал? Не канает для публичного плагина. Срочно обернуть в анонимную функцию.
Цитата:

Сообщение от master_alf
$(selector)

А что если у юзера был вызван jQuery.noConflict() ?
Передать в анонимную функцию - обертку ссылку на jQuery, а внутри уже использовать знак доллара. Смотри как это сделано в других плагинах. Вообще, раз ты делаешь плагин, хоть бы не поленился и изучил как их делают другие.

Цитата:

Сообщение от master_alf
setTimeout(

Это самый последний вариант решения, когда подругому - ну никак. В данном же случае можно просто навесить обработчик onload на картинки и ждать их загрузки.
Цитата:

Сообщение от master_alf
$(imgObj).attr('src');

Может просто imgObj.src ?
Цитата:

Сообщение от master_alf
$(newImg).attr('class', 'gray');

Цитата:

Сообщение от master_alf
$(img).addClass('makeGrayDone');

Как будто два разных человека писали код. addClass предпочтительней.

Где используется функция createCanvas ?

Цитата:

Сообщение от master_alf
$(fx.elem).css('-ms-filter', 'progid:DXImageTransform.Microsoft.Alpha(Opacity=' + opacity + ')');

Зачем это? jQuery сама фиксит opacity в старых ишаках.

Перед .animate() нужно делать .stop() чтоб не образовывалось очереди.

danik.js 25.02.2013 13:09

В WebKit и вроде 10м ишаке (не уверен) есть поддержка css mask, нужно проверять поддержку и по возможности использовать. Это в тыщу раз быстрее чем работа с пикселями.

$(newImg).attr('class', 'gray')

Слишком общий css-класс. Он может быть определен у юзера. Вообще, зачем тут css-классы назначать?

master_alf 25.02.2013 13:58

Цитата:

Сообщение от danik.js (Сообщение 236989)
1) body в селекторе ни к селу ни к городу. Бывают картинки вне body чтоли?

Согласен, fail.
Цитата:

Сообщение от danik.js (Сообщение 236989)
2) Раз jQuery, то и оформи как плагин к jQuery. Чтобы вызов был через $('div img').makeGray()

Погляжу как такое делается.
Цитата:

Сообщение от danik.js (Сообщение 236989)
Срём в глобал? Не канает для публичного плагина. Срочно обернуть в анонимную функцию.

Как только прочту, что такое анонимная функция - поправлю как рекомендвано. с JS сталкиваюсь постольку-поскольку...
Цитата:

Сообщение от danik.js (Сообщение 236989)
А что если у юзера был вызван jQuery.noConflict() ?
Передать в анонимную функцию - обертку ссылку на jQuery, а внутри уже использовать знак доллара. Смотри как это сделано в других плагинах. Вообще, раз ты делаешь плагин, хоть бы не поленился и изучил как их делают другие.

Как сказал выше - в JS слаб, jQuery умею использовать, но не писать под него плагины... погляжу ну другие обязательно.

Цитата:

Сообщение от danik.js (Сообщение 236989)
Это самый последний вариант решения, когда подругому - ну никак. В данном же случае можно просто навесить обработчик onload на картинки и ждать их загрузки.

Согласен, такой вариант в голову не приходил. Перепишу.

Цитата:

Сообщение от danik.js (Сообщение 236989)
Как будто два разных человека писали код. addClass предпочтительней.

За исключением пересчета цвета для канваса - всё писал я. А разные методы т.к. по-разному думал в эти моменты. Что вспомнил, то и использовал...
Цитата:

Сообщение от danik.js (Сообщение 236989)
Где используется функция createCanvas ?

Fail :( осталась не вычещенной с момента сборки всего воедино.
Цитата:

Сообщение от danik.js (Сообщение 236989)
Зачем это? jQuery сама фиксит opacity в старых ишаках.

Это не фикс прозрачности, а её динамическое изменение. Этим и достигатся плавность перехода в IE.
Цитата:

Сообщение от danik.js (Сообщение 236989)
Перед .animate() нужно делать .stop() чтоб не образовывалось очереди.

Забыл :( добавлю.
Цитата:

Сообщение от Deff (Сообщение 236985)
На большинстве халявных сайтах и форумов, нет загрузки изо на текущий домен
Пример Укоз, mybb.ru

Не подумал - добавлю.
Цитата:

Сообщение от danik.js (Сообщение 236990)
В WebKit и вроде 10м ишаке (не уверен) есть поддержка css mask, нужно проверять поддержку и по возможности использовать.

Почитаю что такое css mask. Пока я не понял о чем ты сказал.
Цитата:

Сообщение от danik.js (Сообщение 236990)
$(newImg).attr('class', 'gray')

Слишком общий css-класс. Он может быть определен у юзера. Вообще, зачем тут css-классы назначать?

С названием класса согласен. Хотел изменить на уникальные... но, опять же, забыл. А классы назначал как признак того, что данное изображение - серое. Что бы с него не делать копий. Т.к. при моем способе вызова функции grayScale() - были возможны дубликаты и уже серых картинок. Но с img.onload - проблема уйдет.

master_alf 25.02.2013 14:01

Цитата:

Сообщение от Deff (Сообщение 236987)
Лучше имхо отдельным расширением, связанным плагином
На хабре видал статейку, как реализуемо для свежих версий браузеров => http://habrahabr.ru/post/120917/

Спасибо, погляжу.

Deff 25.02.2013 14:19

Цитата:

Сообщение от master_alf
Как сказал выше - в JS слаб, jQuery умею использовать, но не писать под него плагины... погляжу ну другие обязательно.

Простейший Вариант

<script type="text/javascript" src="http://yandex.st/jquery/1.8.1/jquery.min.js"></script>
<script type="text/javascript">

//Плагин выдачи списка img, отмеченных неким классом ( в данном случае передаём в вызове класс .imgGray
$.fn.makeGray = function() {

    var imgArray = this; //this - переданый объект из jQuery ( При ниже вызове плагина это $(".imgGray")
    var arrOut = [];
    imgArray.each(function() {
         arrOut.push(this.src)
    });
  alert(arrOut.join(",\n"))
}

$(document).ready(function(){
   $(".imgGray").makeGray (); //Вызов и запуск плагина
});
</script>

<img class="imgGray" src="s2.png" />
<img class="imgGray" src="s1.png" />

master_alf 25.02.2013 15:20

Deff,
Спасибо, но уже бессмысленно :) нашел объяснение на сайте jQuery :)
переделал.
Пока без кроссдоменных картинок. Просто навел порядок во всем, на что указали. Вот код.

(function( $ ){
    $.fn.grayScale = function() {
        $(this).each(function() {
            this.onload = function() makeCopy(this);
        });

        function makeCopy(img) {
            var canvas2DSupported = !!window.CanvasRenderingContext2D;
            if (canvas2DSupported) {
                var newImg = makeCanvasCopy(img);
            } else { 
                var newImg = makeIMGCopy(img); 
            }
            var offset = $(img).offset();
            $(img).parent().append(newImg);
            $(newImg).offset(offset);
            $(newImg).hover(hoverIn, hoverOut);
        }

        function makeIMGCopy(imgObj) {
                var newImg = document.createElement('img');
                newImg.src = imgObj.src
                $(newImg).addClass('grayScaleGray');
                newImg.style.filter ='progid:DXImageTransform.Microsoft.BasicImage(grayScale=1)';
                return newImg;
        }

        function makeCanvasCopy(imgObj) {
            var newImg = document.createElement('img');
            var canvas = document.createElement('canvas');
            var canvasContext = canvas.getContext('2d');
            var imgW = imgObj.width;
            var imgH = imgObj.height;
            canvas.width = imgW;
            canvas.height = imgH;
            canvasContext.drawImage(imgObj, 0, 0);
            var imgPixels = canvasContext.getImageData(0, 0, imgW, imgH);
            for(var y = 0; y < imgPixels.height; y++){
                for(var x = 0; x < imgPixels.width; x++){
                    var i = (y * 4) * imgPixels.width + x * 4;
                    var avg = (imgPixels.data[i] + imgPixels.data[i + 1] + imgPixels.data[i + 2]) / 3;
                    imgPixels.data[i] = avg;
                    imgPixels.data[i + 1] = avg;
                    imgPixels.data[i + 2] = avg;
                }
            }
            canvasContext.putImageData(imgPixels, 0, 0, 0, 0, imgPixels.width, imgPixels.height);
            newImg.src = canvas.toDataURL();
            $(newImg).addClass('grayScaleGray');
            return newImg;
        }

        function hoverIn(obj) {
         $(this).stop().animate({
                opacity: 0
                }, 
                {duration: 500, step: function(now, fx) {
                    // Every step of the opacity animation we'll get the current 
                    // opacity as the 'now' argument.
                    var opacity = Math.round(now * 100);
                    $(fx.elem).css('-ms-filter', 'progid:DXImageTransform.Microsoft.Alpha(Opacity=' + opacity + ')');
                    $(fx.elem).css('ms-filter', 'progid:DXImageTransform.Microsoft.Alpha(Opacity=' + opacity + ')');
                    }
                  });
        }
        function hoverOut() {
            $(this).stop().animate({
                opacity: 1
                }, 
                {duration: 500, step: function(now, fx) {
                    var opacity = Math.round(now * 100);
                    $(fx.elem).css('-ms-filter', 'progid:DXImageTransform.Microsoft.Alpha(Opacity=' + opacity + ')');
                    $(fx.elem).css('ms-filter', 'progid:DXImageTransform.Microsoft.Alpha(Opacity=' + opacity + ')');
                    }
                  });
        }
    };
})( jQuery );


Вот вызов.
<script type="text/javascript">
        $(document).ready(function() {
            $('div > img').grayScale();
        });
    </script>

Теперь работает как плагин 8)
Но снова появился баг в хроме.
Он ругается, что не может определить высоту для создаваемого canvasa, т.к. функция выполняется ДО полной загрузки картинки.
Как я понимаю, я где-то неправильно вызываю функцию. Как раз эти самые анонимные функции где-то и должны использоваться? Но смаху решения найти не смог. Объясните, пожалуйста, как правильно вызывать функции из событий (в моем случае image.onload), или же функцию из функции таким образом, что бы они исполнялись только в нужный момент, а не в момент загрузки?

master_alf 25.02.2013 15:21

$(this).each(function() {
            this.onload = function() makeCopy(this);
        });

Мне кажется, косяк где-то вот тут... но как правильно сделать - не пойму.

Deff 25.02.2013 15:49

Цитата:

Сообщение от master_alf
Он ругается, что не может определить высоту для создаваемого canvasa, т.к. функция выполняется ДО полной загрузки картинки

тут нужно ставить отслеживатель всех загрузок картинок,
1. Картинка после вызова

$(document).ready(function() {
           $('div > img').grayScale();


может уже быть загружена(и onload не будет вызываться, поэтому скорее всего вызов нужно делать без обертки в $(document).ready(function() {
а обернуть вызов и движение по функции до тега <body>
$(this).each(function() {
this.onload = function() makeCopy(this); //А тут уже можно парсить и не ждать DOM загрузки
});

master_alf 25.02.2013 15:55

Прежде чем переносить реализацию на img.onload = func() я потестировал работу данного метода.
Просто цепляя на кнопку регистрацию обработчика события.
Т.е.
$('a').click(function() {
    var img = document.getElementById('myImage');
    img.onload = alert('work!');
});

И такое работало... Судя по тому, что я вижу в хроме, там проблема именно в том, что функция пытается выполниться не после загрузки картинки, а перед этим. Я где-то натыкался на пояснение, что по-разному оформленный вызов функций по-разному отрабатывается. Т.е. что-то пытается отработать сразу, в момент инициализации, а что-то просто загружается, и не покажет багу до момента вызова... Мне кажется, что у меня косяк именно тут. Или я не прав, и говорю не том вообще?

Deff 25.02.2013 16:06

Нун гуглить , тут пару дней назад на этом форуме разбирали загрузку-подгрузку ожидание картинок

master_alf 25.02.2013 16:09

Deff,
Я понял о чем ты говоришь. Но это не работает. Проверил все варианты - убрал документ.реди(), переместил вызов в head. Все эти варианты не помогают. Да и не могут. Ведь проблема не в том, что onload Не срабатывает - он срабатывает даже когда всё давно загрузилось, о чем я и говорил своим примером с кликом по ссылке.
Дело как раз в том, что скрипт загружаясь До картинки, почему-то инициализируется на выполнение, и пытается получить данные о размерах еще не загруженного изображения. И только в Хроме и Сафари получается баг - т.к. скрипт срабатывает ДО загрузки изображения. Ишак, опера и ФФ - без проблем ожидают загрузки изображений.

master_alf 25.02.2013 16:45

Блин! Разобрался...
Хром, зараза... в общем, дело вот в чем.
Если вызов делать вида
this.onload = makeCopy(this);

Будет ошибка. А если вида
this.onload = function() {makeCopy(this)};

Всё нормально! НО! Хром, останавливаясь на ошибке, игнорирует изменения кода если страницу тупо перезапускать, не нажимая "продолжить отладку". Уж не знаю почему так... может это какой-то глюк конкретно моего хрома... в общем - я нашел способ правильной записи. Завтра добавлю поддержку картинок со сторонних сайтов, и, если у спецов замечаний по коду больше не будет - то плагин готов :)

Спасибо всем за помощь.

Deff 25.02.2013 16:53

master_alf,
Может делать иной алгоритм
1. Дожидаемся загрузки страницы,
2. далее создаём - перебираем массив всех картинок
3. Смотрим подгружена картинка или нет
Если нет, -вынимаем её из очереди обработки и вешаем onload

master_alf 25.02.2013 16:55

Потестирую с разными картинками текущее решение, если даст где-то сбой, перепишу как ты сказал. Пока же - наконец-то работает! %)

danik.js 25.02.2013 18:07

Уже конечно намного лучше )
Цитата:

Сообщение от master_alf
$(this).each

Добавь впереди ключевое слово return, чтобы вернуть объект для продолжениия цепочки. То есть чтобы могло работать так:
$('img').makeGray().css('border': '1px solid');

Цитата:

Сообщение от master_alf
function() makeCopy(this);

Тут вы конечно втупили оба ))
Можно просто this.onload = makeCopy;
При событии load будет вызывана makeCopy, в которой this укажет на картинку.
Однако что будет если картинка уже загрузилась? Я не уверен что обработчик сработает. Поэтому нужно проверять - загрузилась ли картинка (через img.complete кажется, может для ишака иначе).
Цитата:

Сообщение от master_alf
'ms-filter'

А это еще зачем? Нет такого свойство. Префиксные начинаются с дефиса.
И еще раз спрашиваю - разве без этого всего в ишаке не работает? Ведь jQuery внутри уже сама использует нужные для ишака свойства при анимировании opacity...

master_alf 25.02.2013 21:52

Цитата:

Сообщение от danik.js (Сообщение 237071)
Уже конечно намного лучше )
Добавь впереди ключевое слово return, чтобы вернуть объект для продолжениия цепочки. То есть чтобы могло работать так:
$('img').makeGray().css('border': '1px solid');

*апстену*
Вернуть целую функцию?.. что за безумный язык! Нет, я понимаю, что ваши советы по существу... но, блин... мои олдскульные устои человека, учившегося кодить на Паскале - ломаются окончательно :blink:
Цитата:

Сообщение от danik.js (Сообщение 237071)
Можно просто this.onload = makeCopy;
При событии load будет вызывана makeCopy, в которой this укажет на картинку.

Я правильно понимаю, что при подобной записи получается, что функция makeCopy вызывается как метод для this, т.е. в данном случае для объекта типа Image? Я это просто что б в голове уложить, откуда внутри появится this с указателем на объект... :blink:
Цитата:

Сообщение от danik.js (Сообщение 237071)
Однако что будет если картинка уже загрузилась? Я не уверен что обработчик сработает. Поэтому нужно проверять - загрузилась ли картинка (через img.complete кажется, может для ишака иначе).

Добавлю проверку на завершение загрузки, согласен, что очевидная проверка лучше, чем надежда что браузер сработает как надо. Для Ишака .complete прекрасно работает. По крайней мере 7-8. Шестой поставлю - проверю.
Цитата:

Сообщение от danik.js (Сообщение 237071)
А это еще зачем? Нет такого свойство. Префиксные начинаются с дефиса.

Под рукой ссылки нет, завтра из офиса скину - я читал, что фильтры вызываются без дефиса для 6-7 ишака, и с дефисом для 8+. А значит нужно две записи.
Цитата:

Сообщение от danik.js (Сообщение 237071)
И еще раз спрашиваю - разве без этого всего в ишаке не работает? Ведь jQuery внутри уже сама использует нужные для ишака свойства при анимировании opacity...

Анимирования не получается. Только резкий переход. Собственно из-за того, что найденные мною рецепты не делали анимирование в ишаках, я и затеял написать эту фигню сам... :)
Ну либо я находил кривые решения, и сам не смог добиться иным путём. Тут я не могу ничего сказать - совершенно нуб :)

P.S. Извиняюсь за, по сути, оффтоп, но, ребят, можете подсказать какую конкретно часть документации/учебника/справочника/самоучителя/пофиг_чего прочитать, что бы врубиться таки во все эти хитросплетения вызовов, колбэков и прочих тонкостей джаваскрипта? Ибо что и как в каких случаях следует вызывать - для меня просто... неочивидно.
Например function some() {some code here} где-то вызывать как some, без () - для меня... непонятно - как так-то, вообще?!.. а хотелось бы ориентироваться, что я делаю...

Deff 25.02.2013 22:16

master_alf,
Думаю нун не спеша для начала выспаться, Утро -вечера мудреннее!

danik.js 25.02.2013 22:23

Цитата:

Сообщение от master_alf
Вернуть целую функцию?

Всего лишь ссылку на текущую jQuery коллекцию (по сути - объект, похожий на массив). Язык тут не причем. Это такая плюшка jQuery - цепочки вызовов, chained calls вроде. На сайте jquery.com полюбому есть демонстрация цепочек.

Цитата:

Сообщение от master_alf
в голове уложить, откуда внутри появится this с указателем на объект

Все просто. Почитай про this в javascript. Вобще - тут все очень просто - мы определили метод someimage.onload. В некоторый момент он будет вызван браузером. Мы можем даже сами вызвать его - someimage.onload() - при таком вызове this будет указывать на someimage, верно?
Цитата:

Сообщение от master_alf
без дефиса для 6-7 ишака, и с дефисом для 8+

Не без дефиса, а без префикса. Префикс - это -ms-
Какие еще рецепты. Просто убери этот кусок кода, все должно работать без него. В крайнем случае запили тестовый пример прям тут - посмотрим.
По части документации - для начала можешь покурить Учебник

master_alf 26.02.2013 09:50

Цитата:

Сообщение от danik.js (Сообщение 237133)
Всего лишь ссылку на текущую jQuery коллекцию (по сути - объект, похожий на массив). Язык тут не причем. Это такая плюшка jQuery - цепочки вызовов, chained calls вроде. На сайте jquery.com полюбому есть демонстрация цепочек.

Понято, почитаю. Спасибо.

Цитата:

Сообщение от danik.js (Сообщение 237133)
Мы можем даже сами вызвать его - someimage.onload() - при таком вызове this будет указывать на someimage, верно?

Да. Пытался сформулировать в чем у меня был вопрос, но внятно описать не смог. Видимо просто надо перечитать про области видимости. Похожу я в этом где-то запутался. :)
Цитата:

Сообщение от danik.js (Сообщение 237133)
Не без дефиса, а без префикса. Префикс - это -ms-

Совершенно верно, глянул на ту ссылку - префикс это -ms- ... память подводит :(. Если интересно, то ссылка вот.
Цитата:

Сообщение от danik.js (Сообщение 237133)
Какие еще рецепты. Просто убери этот кусок кода, все должно работать без него. В крайнем случае запили тестовый пример прям тут - посмотрим.

И снова я был не прав. Убрал функцию step в animate() - плавность всё равно осталась. Всё работает. Я же был уверен в том, что работать не будет т.к. изначально пробовал в animate() поместить
newImg.style.filter ='progid:DXImageTransform.Microsoft.BasicImage(grayScale=1)';

Т.е. просто плавный переход в серый цвет. И не работало именно такое решение, а не с применением прозрачности.
Цитата:

Сообщение от danik.js (Сообщение 237133)
По части документации - для начала можешь покурить Учебник

Начал еще вчера, но там мноооого всего. Думал нужные куски найти побыстрее, но да это уже совершенно другой вопрос.

P.S. на сайте/форуме нет раздела в духе "вот мой плагин, пользуйтесь на здоровье"? Вижу на форуме место для обсуждения плагинов, но это немного не то. И так оффтопиков развёл. :(

P.P.S. прикручу реализацию кросдоменных картинок, и выложу окончательный вариант. Ну или раньше приду с вопросами :D

Deff 26.02.2013 10:44

Цитата:

Сообщение от master_alf
P.S. на сайте/форуме нет раздела в духе "вот мой плагин, пользуйтесь на здоровье"?

http://javascript.ru/forum/project/

master_alf 26.02.2013 10:51

Цитата:

Сообщение от Deff (Сообщение 236987)
Лучше имхо отдельным расширением, связанным плагином
На хабре видал статейку, как реализуемо для свежих версий браузеров => http://habrahabr.ru/post/120917/

Deff, я посмотрел этот пост... скажу честно - очень многое осталось непонятым совершенно. Судя по всему, ты рекомендовал мне использовать CORS? Но это не будет работать в ишаках 7-, а так же требует настройки сервера, дабы он возвращал
Код:

Header set Access-Control-Allow-Origin "*"
Это написано вот здесь.
Вопрос - я прав, и это действительно тот способ который ты посоветовал? Или я проглядел что-то более простое... Ибо если нужно перенастроить заголовки ответа сервера, с которого планируется получать свои картинки... То во многих случаях плагин работать не будет. Т.к. доступа к серверу нет, а вряд ли большинство хостеров/админов такие добрые, что станут настраивать такой заголовок "впрок, дабы людям было удобно".

Deff 26.02.2013 11:20

Цитата:

Сообщение от master_alf
Deff, я посмотрел этот пост... скажу честно - очень многое осталось непонятым совершенно. Судя по всему, ты рекомендовал мне использовать CORS? Но это не будет работать в ишаках 7-, а так же требует настройки сервера, дабы он возвращал

Да - скорее Всего - тут я не прав. Нун искать статьи: загрузка в канвас картинки с инодомена

master_alf 26.02.2013 11:30

Понято. Значит погуглю всевозможные варианты.


Часовой пояс GMT +3, время: 02:34.