如何基于filter实现网站整体变灰功能


Posted in Javascript onApril 17, 2020

前言

政府网站会遇到公祭日的时候,网站整体颜色变灰的情况。今天正好调了一下。在此把解决方案分享给大家。方案简单实用,笔者已在生产环境使用过。通过整体的html使用filter来进行过滤。如下,只要引入即可。

解决方案

html { 
  filter: url("data:image/svg+xml;utf8,#grayscale"); 
  -webkit-filter: grayscale(100%); 
  filter: grayscale(100%); 
  filter: gray; 
  filter:progid:DXImageTransform.Microsoft.BasicImage(grayscale=1);
}

IE11 和 IE10的解决方案

经过测试发现,以上代码的方式对于谷歌,火狐,IE8,9都很好使。对于IE11和IE10效果不奏效。于是我们采取另一种方式,通过引用grayscale.js来使用。由于不能上传文件,在此将grayscale.js的代码写下来。

/*
 * -- grayscale.js --
 * Copyright (C) James Padolsey (http://james.padolsey.com)
 * Download by //3water.com
 */

var grayscale = (function(){
  
  var config = {
      colorProps: ['color','backgroundColor','borderBottomColor','borderTopColor','borderLeftColor','borderRightColor','backgroundImage'],
      externalImageHandler : {
        /* Grayscaling externally hosted images does not work
          - Use these functions to handle those images as you so desire */
        /* Out of convenience these functions are also used for browsers
          like Chrome that do not support CanvasContext.getImageData */
        init : function(el, src) {
          if (el.nodeName.toLowerCase() === 'img') {
            // Is IMG element...
          } else {
            // Is background-image element:
            // Default - remove background images
            data(el).backgroundImageSRC = src;
            el.style.backgroundImage = '';
          }
        },
        reset : function(el) {
          if (el.nodeName.toLowerCase() === 'img') {
            // Is IMG element...
          } else {
            // Is background-image element:
            el.style.backgroundImage = 'url(' + (data(el).backgroundImageSRC || '') + ')';
          }
        }
      }
    },
    log = function(){
      try { window.console.log.apply(console, arguments); }
      catch(e) {};
    },
    isExternal = function(url) {
      // Checks whether URL is external: 'CanvasContext.getImageData'
      // only works if the image is on the current domain.
      return (new RegExp('https?://(?!' + window.location.hostname + ')')).test(url);
    },
    data = (function(){
      
      var cache = [0],
      expando = 'data' + (+new Date());
      
      return function(elem) {
        var cacheIndex = elem[expando],
          nextCacheIndex = cache.length;
        if(!cacheIndex) {
          cacheIndex = elem[expando] = nextCacheIndex;
          cache[cacheIndex] = {};
        }
        return cache[cacheIndex];
      };
      
    })(),
    desatIMG = function(img, prepare, realEl) {
      
      // realEl is only set when img is temp (for BG images)
      
      var canvas = document.createElement('canvas'),
        context = canvas.getContext('2d'),
        height = img.naturalHeight || img.offsetHeight || img.height,
        width = img.naturalWidth || img.offsetWidth || img.width,
        imgData;
        
      canvas.height = height;
      canvas.width = width;
      context.drawImage(img, 0, 0);
      try {
        imgData = context.getImageData(0, 0, width, height);
      } catch(e) {}
      
      if (prepare) {
        desatIMG.preparing = true;
        // Slowly recurse through pixels for prep,
        // :: only occurs on grayscale.prepare()
        var y = 0;
        (function(){
          
          if (!desatIMG.preparing) { return; }
          
          if (y === height) {
            // Finished!
            context.putImageData(imgData, 0, 0, 0, 0, width, height);
            realEl ? (data(realEl).BGdataURL = canvas.toDataURL())
                : (data(img).dataURL = canvas.toDataURL())
          }
          
          for (var x = 0; x < width; x++) {
            var i = (y * width + x) * 4;
            // Apply Monoschrome level across all channels:
            imgData.data[i] = imgData.data[i+1] = imgData.data[i+2] =
            RGBtoGRAYSCALE(imgData.data[i], imgData.data[i+1], imgData.data[i+2]);
          }
          
          y++;
          setTimeout(arguments.callee, 0);
          
        })();
        return;
      } else {
        // If desatIMG was called without 'prepare' flag
        // then cancel recursion and proceed with force! (below)
        desatIMG.preparing = false;
      }
      
      for (var y = 0; y < height; y++) {
        for (var x = 0; x < width; x++) {
          var i = (y * width + x) * 4;
          // Apply Monoschrome level across all channels:
          imgData.data[i] = imgData.data[i+1] = imgData.data[i+2] =
          RGBtoGRAYSCALE(imgData.data[i], imgData.data[i+1], imgData.data[i+2]);
        }
      }
      
      context.putImageData(imgData, 0, 0, 0, 0, width, height);
      return canvas;
    
    },
    getStyle = function(el, prop) {
      var style = document.defaultView && document.defaultView.getComputedStyle ? 
            document.defaultView.getComputedStyle(el, null)[prop]
            : el.currentStyle[prop];
      // If format is #FFFFFF: (convert to RGB)
      if (style && /^#[A-F0-9]/i.test(style)) {
          var hex = style.match(/[A-F0-9]{2}/ig);
          style = 'rgb(' + parseInt(hex[0], 16) + ','
                  + parseInt(hex[1], 16) + ','
                  + parseInt(hex[2], 16) + ')';
      }
      return style;
    },
    RGBtoGRAYSCALE = function(r,g,b) {
      // Returns single monochrome figure:
      return parseInt( (0.2125 * r) + (0.7154 * g) + (0.0721 * b), 10 );
    },
    getAllNodes = function(context) {
      var all = Array.prototype.slice.call(context.getElementsByTagName('*'));
      all.unshift(context);
      return all;
    };
    
  var init = function(context) {
    
    // Handle if a DOM collection is passed instead of a single el:
    if (context && context[0] && context.length && context[0].nodeName) {
      // Is a DOM collection:
      var allContexts = Array.prototype.slice.call(context),
        cIndex = -1, cLen = allContexts.length;
      while (++cIndex<cLen) { init.call(this, allContexts[cIndex]); }
      return;
    }
    
    context = context || document.documentElement;
    
    if (!document.createElement('canvas').getContext) {
      context.style.filter = 'progid:DXImageTransform.Microsoft.BasicImage(grayscale=1)';
      context.style.zoom = 1;
      return;
    }
    
    var all = getAllNodes(context),
      i = -1, len = all.length;
      
    while (++i<len) {
      var cur = all[i];
      
      if (cur.nodeName.toLowerCase() === 'img') {
        var src = cur.getAttribute('src');
        if(!src) { continue; }
        if (isExternal(src)) {
          config.externalImageHandler.init(cur, src);
        } else {
          data(cur).realSRC = src;
          try {
            // Within try statement just encase there's no support....
            cur.src = data(cur).dataURL || desatIMG(cur).toDataURL();
          } catch(e) { config.externalImageHandler.init(cur, src); }
        }
        
      } else {
        for (var pIndex = 0, pLen = config.colorProps.length; pIndex < pLen; pIndex++) {
          var prop = config.colorProps[pIndex],
          style = getStyle(cur, prop);
          if (!style) {continue;}
          if (cur.style[prop]) {
            data(cur)[prop] = style;
          }
          // RGB color:
          if (style.substring(0,4) === 'rgb(') {
            var monoRGB = RGBtoGRAYSCALE.apply(null, style.match(/\d+/g));
            cur.style[prop] = style = 'rgb(' + monoRGB + ',' + monoRGB + ',' + monoRGB + ')';
            continue;
          }
          // Background Image:
          if (style.indexOf('url(') > -1) {
            var urlPatt = /\(['"]?(.+?)['"]?\)/,
              url = style.match(urlPatt)[1];
            if (isExternal(url)) {
              config.externalImageHandler.init(cur, url);
              data(cur).externalBG = true;
              continue;
            }
            // data(cur).BGdataURL refers to caches URL (from preparation)
            try {
              var imgSRC = data(cur).BGdataURL || (function(){
                  var temp = document.createElement('img');
                  temp.src = url;
                  return desatIMG(temp).toDataURL();
                })();
              
              cur.style[prop] = style.replace(urlPatt, function(_, url){
                return '(' + imgSRC + ')';
              });
            } catch(e) { config.externalImageHandler.init(cur, url); }
          }
        }
      }
    }
    
  };
  
  init.reset = function(context) {
    // Handle if a DOM collection is passed instead of a single el:
    if (context && context[0] && context.length && context[0].nodeName) {
      // Is a DOM collection:
      var allContexts = Array.prototype.slice.call(context),
        cIndex = -1, cLen = allContexts.length;
      while (++cIndex<cLen) { init.reset.call(this, allContexts[cIndex]); }
      return;
    }
    context = context || document.documentElement;
    if (!document.createElement('canvas').getContext) {
      context.style.filter = 'progid:DXImageTransform.Microsoft.BasicImage(grayscale=0)';
      return;
    }
    var all = getAllNodes(context),
      i = -1, len = all.length;
    while (++i<len) {
      var cur = all[i];
      if (cur.nodeName.toLowerCase() === 'img') {
        var src = cur.getAttribute('src');
        if (isExternal(src)) {
          config.externalImageHandler.reset(cur, src);
        }
        cur.src = data(cur).realSRC || src;
      } else {
        for (var pIndex = 0, pLen = config.colorProps.length; pIndex < pLen; pIndex++) {
          if (data(cur).externalBG) {
            config.externalImageHandler.reset(cur);
          }
          var prop = config.colorProps[pIndex];
          cur.style[prop] = data(cur)[prop] || '';
        }
      }
    }
  };
  
  init.prepare = function(context) {
    
    // Handle if a DOM collection is passed instead of a single el:
    if (context && context[0] && context.length && context[0].nodeName) {
      // Is a DOM collection:
      var allContexts = Array.prototype.slice.call(context),
        cIndex = -1, cLen = allContexts.length;
      while (++cIndex<cLen) { init.prepare.call(null, allContexts[cIndex]); }
      return;
    }
    
    // Slowly recurses through all elements
    // so as not to lock up on the user.
    
    context = context || document.documentElement;
    
    if (!document.createElement('canvas').getContext) { return; }
    
    var all = getAllNodes(context),
      i = -1, len = all.length;
    
    while (++i<len) {
      var cur = all[i];
      if (data(cur).skip) { return; }
      if (cur.nodeName.toLowerCase() === 'img') {
        if (cur.getAttribute('src') && !isExternal(cur.src)) {
          desatIMG(cur, true);
        }
        
      } else {
        var style = getStyle(cur, 'backgroundImage');
        if (style.indexOf('url(') > -1) {
          var urlPatt = /\(['"]?(.+?)['"]?\)/,
            url = style.match(urlPatt)[1];
          if (!isExternal(url)) {
            var temp = document.createElement('img');
            temp.src = url;
            desatIMG(temp, true, cur);
          }
        }
      }
    }
  };
  
  return init;

})();
使用方式如下,中心思想就是当我们是ie10和ie11浏览器的时候,调用graystyle的js函数。

<script type="text/javascript">
 var navStr = navigator.userAgent.toLowerCase();
 if(navStr.indexOf("msie 10.0")!==-1||navStr.indexOf("rv:11.0")!==-1){ // 判断是IE10或者IE11
  $(function () {
    grayscale($('body'));
  })
 }
</script>

这里建议直接捕捉body,如果想针对某一个,换其中的捕捉元素就可以。

总结

至此,网站变灰的方案就完美了。完美兼容各种浏览器,笔者已经在生产环境使用过了,大家放心使用。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript 无符号右移赋值操作
Apr 17 Javascript
文档对象模型DOM通俗讲解
Nov 01 Javascript
node.js中的http.request.end方法使用说明
Dec 10 Javascript
最精简的JavaScript实现鼠标拖动效果的方法
May 11 Javascript
jQuery实现向下滑出的二级菜单效果实例
Aug 22 Javascript
BootStrap入门教程(二)之固定的内置样式
Sep 19 Javascript
js鼠标跟随运动效果
Mar 11 Javascript
React.js中常用的ES6写法总结(推荐)
May 09 Javascript
使用canvas实现一个vue弹幕组件功能
Nov 30 Javascript
关于vue的npm run dev和npm run build的区别介绍
Jan 14 Javascript
vue component 中引入less文件报错 Module build failed
Apr 17 Javascript
Javascript摸拟自由落体与上抛运动原理与实现方法详解
Apr 08 Javascript
javascript设计模式 ? 解释器模式原理与用法实例分析
Apr 17 #Javascript
javascript设计模式 ? 迭代器模式原理与用法实例分析
Apr 17 #Javascript
vue制作抓娃娃机的示例代码
Apr 17 #Javascript
Vue+tracking.js 实现前端人脸检测功能
Apr 16 #Javascript
tracking.js实现前端人脸识别功能
Apr 16 #Javascript
electron 如何将任意资源打包的方法步骤
Apr 16 #Javascript
vue中keep-alive内置组件缓存的实例代码
Apr 16 #Javascript
You might like
php数组相加 array(“a”)+array(“b”)结果还是array(“a”)
2012/09/19 PHP
页面乱码问题的根源及其分析
2013/08/09 PHP
php实现分页显示
2015/11/03 PHP
CentOS系统中PHP安装扩展的方式汇总
2017/04/09 PHP
PHP实现执行外部程序的方法详解
2017/08/17 PHP
js实现的真正的iframe高度自适应(兼容IE,FF,Opera)
2010/03/07 Javascript
模拟多级复选框效果的jquery代码
2013/08/13 Javascript
jquery五角星评分插件示例分享
2014/02/21 Javascript
AngularJS基础学习笔记之控制器
2015/05/10 Javascript
理解javascript中的with关键字
2016/02/15 Javascript
jQuery实现鼠标经过像翻页和描点链接效果
2016/08/08 Javascript
Vuejs第九篇之组件作用域及props数据传递实例详解
2016/09/05 Javascript
jQuery Validate设置onkeyup验证的实例代码
2016/12/09 Javascript
AngularJS中$http使用的简单介绍
2017/03/17 Javascript
原生JS封装animate运动框架的实例
2017/10/12 Javascript
jQuery解析json格式数据示例
2018/09/01 jQuery
vue项目首屏加载时间优化实战
2019/04/23 Javascript
mpvue网易云短信接口实现小程序短信登录的示例代码
2020/04/03 Javascript
Windows下用py2exe将Python程序打包成exe程序的教程
2015/04/08 Python
python实现ping的方法
2015/07/06 Python
简述Python中的进程、线程、协程
2016/03/18 Python
Python使用sax模块解析XML文件示例
2019/04/04 Python
python的pytest框架之命令行参数详解(下)
2019/06/27 Python
python中bs4.BeautifulSoup的基本用法
2019/07/27 Python
深入浅析Python科学计算库Scipy及安装步骤
2019/10/12 Python
Tensorflow tf.tile()的用法实例分析
2020/05/22 Python
keras:model.compile损失函数的用法
2020/07/01 Python
anaconda3安装及jupyter环境配置全教程
2020/08/24 Python
python实现简单的井字棋游戏(gui界面)
2021/01/22 Python
Holiday Inn中国官网:IHG旗下假日酒店预订
2018/04/08 全球购物
利用异或运算实现两个无符号数的加法运算
2013/12/20 面试题
Laravel的加密解密与哈希实例讲解
2021/03/24 PHP
2013的个人自我评价
2013/12/26 职场文书
收银员岗位职责范本
2015/04/07 职场文书
学困生转化工作总结
2015/08/13 职场文书
团队合作精神学习心得体会
2016/01/19 职场文书