Веб-дизайн и веб-разработка для компаний и частных лиц в Чешской Республике.
+420 608 713 199

Эффект черно-белого изображения из цветного (html5, css3, jquery)

Black and White CSS + jQuery

При разработке сайтов бывает необходимо сделать черно-белое изображение из существующего цветного. Раньше разработчики использовали для этой цели два заранее подготовленных изображения. Однако в современных условиях это может стать избыточной тратой времени. Дело в том, что html5 + jQuery уже позволяют сделать этот эффект динамически без использования дополнительного изображения. Как это сделать? Gianluca Guarini написал для этого простой jQuery плагин, который он разместил в отрытом доступе на github.

Как начать использовать этот плагин? Для этого достаточно просто подключить его в заголовке вашей страницы:

<script src="js/jquery.min.js"></script>
<script src="js/jQuery.BlackAndWhite.js"></script>

jQuery Black and White при этом добавит в jQuery собственный метод – BlackAndWhite(). Перед тем, как его использовать, вы должны подготовить структуру html и css, которая должна выглядеть примерно так:

<style>
    .bwWrapper { position:relative; display:block; }
</style>
<div class="bwWrapper">
    <img src="http://example.com/image.jpg" alt="" />
</div>

После чего вам достаточно вызвать $(‘.bwWrapper’).BlackAndWhite() на событие jQuery $(document).ready():

$(document).ready(function(){
    $('.bwWrapper').BlackAndWhite();
});

По умолчанию все ваши изображения будут отображены в черно-белом виде. Если вы хотите добавить эффект при наведении мыши, вызовите метод так:

$(document).ready(function(){
    $('.bwWrapper').BlackAndWhite({
        hoverEffect: true
    });
});

Возможно, вас заинтересовало, как устроен этот плагин. На самом деле он достаточно прост и, возможно, вам понадобится более сложное поведение, поэтому рассмотрим его внутренности подробнее.
Как уже говорилось, плагин расширяет jQuery одним дополнительным методом: BlackAndWhite. При инициализации плагин проверяет, поддерживает ли браузер canvas – новый тэг, введенный в HTML5.

var supportsCanvas = !!document.createElement('canvas').getContext;

Дополнительно плагин проверяет, не является ли браузер IE с версией, отличной от 9.0 (на самом деле, наверное, этот момент не вполне корректен, потому что IE10 тоже будет считаться браузером, не поддерживающим canvas). Если это так, то черно-белый эффект достигается с помощью проприетарного свойства css filter:

'filter': 'progid:DXImageTransform.Microsoft.BasicImage(grayscale=1)'

Справедливости ради, хотелось бы отметить, что если браузер не поддерживает canvas, то он все равно будет отправлен в ветку для устаревших IE, что тоже некорректно, поэтому если у вас появится желание подправить поведение плагина, вы можете отправить patch автору на github. Поскольку в куске для IE нет ничего особо интересного, продолжим рассматривать ветку для современных браузеров с поддержкой canvas. Для начала скрипт определяет ширину и высоту исходного изображения. Затем добавляет новый элемент canvas прямо перед img, попутно выставляя первому position: absolute с top и left равными 0, что позволит перекрыть с помощью canvas первоначальный рисунок.

Основная “магия” кроется в функции greyImages():

function greyImages(img,canvas,width,height) {
    var ctx = canvas.getContext('2d'),
        currImg = img,
        imageData, px, length, i = 0,
        grey;

    $(img).load(function(){
        ctx.drawImage(img, 0, 0);

        imageData = ctx.getImageData(0, 0, width, height);
        px = imageData.data;
        length = px.length;

        for ( ; i &lt; length; i+= 4 ) {
            grey = px[i] * .3 + px[i+1] * .59 + px[i+2] * .11;
            px[i] = px[i+1] = px[i+2] = grey;
        }

        ctx.putImageData(imageData, 0, 0);
    });
}

Эта функция и производит преобразование цветного исходника в черно-белый вариант. В данном случае на событие $(img).load() вызывается отрисовка в canvas. По сути алгоритм следующий:

  • получаем context ‘2d’ элемента canvas
  • отрисовываем в контексте исходное изображение с помощью метода drawImage()
  • получаем исходные данные об изображении из контекста с помощью метода getImageData()
  • с помощью математических преобразований убираем цветовую составляющую в цикле по известной формуле для RGB палитры: greyscale = 0.2989 * R + 0.5870 * G + 0.1140 * B (альфа-канал при этом не меняется)
  • после чего размещаем модифицированное изображение в контексте элемента canvas.

Как видно, это преобразование в плагине работает только по событию load(). Если вам нужно это сделать в произвольный момент, повторите логику плагина, изменив момент вызова самого преобразования.

P.S. В плагине присутствует заплатка для Оперы. Дело в том, что в бразуере Opera странным образом работает кэширование изображений, в результате чего, в canvas приходит пустой рисунок. Автор решил эту проблему так:

if (jQuery.browser.opera){
    var rand = Math.random();
    // fix opera bug decaching images
    $(pic).prop('src',src+'?'+ rand)
}

По сути это вынуждает оперу каждый раз заново загружать изображение. Не самое элегантное решение. Если вы знаете решение получше, не стесняйтесь отправить его автору.

Интересуют наши услуги?
Наймите нас