實現映像灰階(grayscale)最初有ie6推出的專屬屬性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不支援。
因此我們需要考慮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的瀏覽器安全色情況如所示。
首先,你需要在一個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次。對於IE瀏覽器
// IE 10 only CSS propertiesvar 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 propertiesfor (var i = 0; i < ie10Styles.length; i++) { property = ie10Styles[i]; if (s[property] != undefined) { brwoser = "ie10"; }}// Tests IE11 propertiesfor (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 browsersif (!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前端開發技術,分享網頁相關資源。
---------------------------------------------------------------