跨浏览器图像灰度(grayscale)解决方案

前端开发whqet,csdn,王海庆,whqet,前端开发专家

实现图像灰度(grayscale)最初有ie4推出的专属属性filter实现,后来在css3里w3c实现了标准的filter,不过不同浏览器的实现程度不一样,因此现阶段我们必须探索一种浏览器兼容的解决方案。

1.IE私有滤镜的方式

自IE4开始,IE引入了私有滤镜,可以实现透明度、模糊、阴影、发光等效果,当然也可以实现灰度图像效果。代码如下
img {  
    filter: gray; /* just for IE6-9 */  
}  
IE10开始抛弃了这种私有滤镜,但是还没有提供对标准CSSfilter的支持,所以说IE10以上版本的灰度图像,仍然是一个问题。

2.W3c CSS filter方式

CSS3中借鉴IE私有滤镜的方式提供了标准的CSS Filter方案,里面可以支持grayscale灰度、sepia褐色、saturate饱和度、hue-rotate色相旋转、invert反色、opacity透明度、brightness亮度、contrast对比度、blur模糊、drop-shadow阴影等十种效果。关于CSS3 Filter大家可以参照以下教程:大漠的《 CSS3 Filter的十种特效》和Adobe的《 CSS Filter Lab》。
实现grayscale灰度图像的代码是这样的
img{
 -webkit-filter: grayscale(100%);    /* webkit内核支持程度较好 */
    -moz-filter: grayscale(100%);    /* 其他内核现在并不支持,为了将来兼容性书写 */
     -ms-filter: grayscale(100%);
      -o-filter: grayscale(100%);
         filter: grayscale(100%);    /* 标准写法 */
}
其中grayscale()的取值为0%-100%,也可以用0-1取代,0%代表彩色图像,100%代表完全的灰度。
css filter的浏览器兼容情况如下,Chrome31+,Safari7+,Opera20+,ios Safari6+,Android Browser4.4+,Blackberry 10+均支持了-webkit-filter的方式,IE不支持,firefox不支持。
跨浏览器图像灰度(grayscale)解决方案_第1张图片
因此我们需要考虑IE和firefox的兼容方案,好在对于firefox来说支持SVG effects for HTML 方式,接下来我们予以介绍。

3.SVG effects for HTML方式

Firefox虽说不支持css filter,但是支持svg effects for html,html文件可以调用svg里面的效果,不仅仅是滤镜、还可以是mask、clip等,详细内容大家可以参照MDN上的一片文章《 Applying SVG effects to HTML content》。
svg effects for html的浏览器兼容情况如下图所示。
跨浏览器图像灰度(grayscale)解决方案_第2张图片
首先,你需要在一个svg里声明滤镜,该svg可以内嵌到html文件里,也可以单独保存。
<svg xmlns="http://www.w3.org/2000/svg">
 <filter id="grayscale">
  <feColorMatrix type="matrix" values="0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0"/>
 </filter>
</svg>
如果该文件保存成了单独的文件gray.svg,我们可以在html文件里加以引用。
img{
	filter:url('gray.svg#grayscale'); /*灰度滤镜放在gray.svg文件的id叫做grayscale的滤镜里*/
}
如果该文件内嵌入了html文件里,则是这样引用
img{
	filter:url('#grayscale'); /*svg滤镜内嵌入了html文件*/
}
当然,我们也可以直接把svg文件打包嵌入到css里,如果你没有代码洁癖的话
img {  
        filter: url('url("data:image/svg+xml;utf8,<svg%20xmlns='http://www.w3.org/2000/svg'><filter%20id='grayscale'><feColorMatrix%20type='matrix'%20values='0.3333%200.3333%200.3333%200%200%200.3333%200.3333%200.3333%200%200%200.3333%200.3333%200.3333%200%200%200%200%200%201%200'/></filter></svg>#grayscale");')  
} 
上面的方式,我们可以兼容大部分的浏览器(除了IE10、IE11),兼容的grayscale代码如下。
img{
	-webkit-filter: grayscale(100%);            /* CSS3 filter方式,webkit内核方式,firefox外的绝大部分的现代浏览器*/
       -moz-filter: grayscale(100%);            /* 目前没有实现 */
        -ms-filter: grayscale(100%);
         -o-filter: grayscale(100%);
            filter: grayscale(100%);            /* CSS3 filter方式,标准写法*/
            filter: url(filters.svg#grayscale); /* Firefox 4+ */
            filter: gray;                       /* IE 6-9 */
}
img:hover{
	-webkit-filter: grayscale(0%);
	   -moz-filter: grayscale(0%);
	    -ms-filter: grayscale(0%);
	     -o-filter: grayscale(0%);
	        filter: grayscale(0%);
	        filter: none; /* Firefox 4+, IE 6-9 */
}

4.js实现

对于IE10、11,我们怎么办呢?就得用js啦。
var imgObj = document.getElementById('imgToGray'); 

function gray(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);
    return canvas.toDataURL();
}
imgObj.src = gray(imgObj);
该解决方案主要参考ajaxblender的《 Convert Images to Grayscale》,大家可以继续阅读查阅详情。

5.跨浏览器解决方案

该方案主要参考《 Cross-Browser Grayscale image example using CSS3 + JS v2.0. With browser feature detection using Modernizr》实现,英语没问题的童鞋可以移步观赏。博主写了两篇关于使用js实现跨浏览器解决灰度图像问题的博客,第一篇自行实现浏览器检测,第二篇使用了Modernizr。
该解决方案使用了jQuery和Modernizr,所以需要引入,此处省略,不知道怎么引入的童鞋,请自觉撞南墙100次。
好吧,有点狠了,还是贴出来cdn的方式吧。
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/modernizr/2.7.1/modernizr.min.js"></script>
对于IE浏览器
// IE 10 only CSS properties
var ie10Styles = [
'msTouchAction',
'msWrapFlow'];

var ie11Styles = [
'msTextCombineHorizontal'];

/*
* Test all IE only CSS properties
*/

var d = document;
var b = d.body;
var s = b.style;
var brwoser = null;
var property;

// Tests IE10 properties
for (var i = 0; i < ie10Styles.length; i++) {
    property = ie10Styles[i];
    if (s[property] != undefined) {
        brwoser = "ie10";
    }
}

// Tests IE11 properties
for (var i = 0; i < ie11Styles.length; i++) {
    property = ie11Styles[i];
    if (s[property] != undefined) {
        brwoser = "ie11";
    }
}

 //Grayscale images only on browsers IE10+ since they removed support for CSS grayscale filter
 if(brwoser == "ie10" || brwoser == "ie11" ){
    $('body').addClass('ie11'); // Fixes marbin issue on IE10 and IE11 after canvas function on images
    $('.grayscale img').each(function(){
        var el = $(this);
        el.css({"position":"absolute"}).wrap("<div class='img_wrapper' style='display: inline-block'>").clone().addClass('img_grayscale ieImage').css({"position":"absolute","z-index":"5","opacity":"0"}).insertBefore(el).queue(function(){
            var el = $(this);
            el.parent().css({"width":this.width,"height":this.height});
            el.dequeue();
        });
        this.src = grayscaleIe(this.src);
    });

    // Quick animation on IE10+ 
    $('.grayscale img').hover(
        function () {
            $(this).parent().find('img:first').stop().animate({opacity:1}, 200);
        }, 
        function () {
            $('.img_grayscale').stop().animate({opacity:0}, 200);
        }
    );

    // Custom grayscale function for IE10 and IE11
    function grayscaleIe(src){
        var canvas = document.createElement('canvas');
        var ctx = canvas.getContext('2d');
        var imgObj = new Image();
        imgObj.src = src;
        canvas.width = imgObj.width;
        canvas.height = imgObj.height; 
        ctx.drawImage(imgObj, 0, 0); 
        var imgPixels = ctx.getImageData(0, 0, canvas.width, canvas.height);
        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;
            }
        }
        ctx.putImageData(imgPixels, 0, 0, 0, 0, imgPixels.width, imgPixels.height);
        return canvas.toDataURL();
    };
 };
对于其他浏览器
// If the browser does not support CSS filters filters, we are applying grayscale.js function
// This part of Grayscale images applies on Opera, Firefox and Safari browsers
if (!Modernizr.cssfilters) {
    var $images = $(".grayscale img"), imageCount = $images.length, counter = 0;

    // One instead of on, because it need only fire once per image
    $images.one("load",function(){
        // increment counter every time an image finishes loading
        counter++;
        if (counter == imageCount) {
            // do stuff when all have loaded
            grayscale($('.grayscale img'));
            $(".grayscale img").hover(
                function () {
                    grayscale.reset($(this));
                }, 
                function () {
                    grayscale($(this));
                }
            );
        }
    }).each(function () {
    if (this.complete) {
        // manually trigger load event in
        // event of a cache pull
            $(this).trigger("load");
        }
    });
}
DEMO就不自己做了,大家看老外的 DEMO的。That's all.

---------------------------------------------------------------

前端开发whqet,关注web前端开发技术,分享网页相关资源。
---------------------------------------------------------------

你可能感兴趣的:(跨浏览器,解决方案,Modernizr)