如何基于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 相关文章推荐
打开超链需要“确认”对话框的方法
Mar 08 Javascript
网上抓的一个特效
May 11 Javascript
JavaScript开发规范要求(规范化代码)
Aug 16 Javascript
纯JS实现的批量图片预览加载功能
Aug 14 Javascript
js 判断一个元素是否在页面中存在
Dec 27 Javascript
js控制web打印(局部打印)方法整理
May 29 Javascript
让checkbox不选中即将选中的checkbox不选中
Jul 11 Javascript
jQuery 3.0 的变化及使用方法
Feb 01 Javascript
jquery实现具有收缩功能的垂直导航菜单
Feb 16 Javascript
微信小程序之picker日期和时间选择器
Feb 09 Javascript
浅谈Vue父子组件和非父子组件传值问题
Aug 22 Javascript
react+antd 递归实现树状目录操作
Nov 02 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
玩转虚拟域名◎+ .
2006/10/09 PHP
用PHP实现多级树型菜单
2006/10/09 PHP
php和javascript之间变量的传递实现代码
2012/12/19 PHP
php文件服务实现虚拟挂载其他目录示例
2014/04/17 PHP
php检测url是否存在的方法
2015/04/14 PHP
php实现分页功能的详细实例方法
2019/09/29 PHP
不错的JS中变量相关的细节分析
2007/08/13 Javascript
解决javascript:window.close()在chrome,Firefox下失效的问题
2013/05/07 Javascript
JS关闭窗口或JS关闭页面的几种代码分享
2013/10/25 Javascript
jquery对元素拖动排序示例
2014/01/16 Javascript
jquery的ajax异步请求接收返回json数据实例
2014/06/16 Javascript
javascript实现回车键提交表单方法总结
2015/01/10 Javascript
JavaScript实现常用二级省市级联下拉列表的方法
2015/03/25 Javascript
JavaScript动态修改背景颜色的方法
2015/04/16 Javascript
jquery中map函数遍历数组用法实例
2015/05/18 Javascript
Angularjs处理页面闪烁的解决方法
2017/03/09 Javascript
C#微信小程序服务端获取用户解密信息实例代码
2017/03/10 Javascript
Angular.Js中ng-include指令的使用与实现
2017/05/07 Javascript
jQuery复合事件结合toggle()方法的用法示例
2017/06/10 jQuery
微信小程序自定义底部导航带跳转功能
2018/11/27 Javascript
JS实现可切换图片的幻灯切换效果示例
2019/05/24 Javascript
Vue form表单动态添加组件实战案例
2019/09/02 Javascript
jQuery实现简单弹幕效果
2019/11/28 jQuery
js刷新页面location.reload()用法详解
2019/12/09 Javascript
[03:01]2014DOTA2国际邀请赛 小组赛7月13日TOPPLAY
2014/07/14 DOTA
python文件操作整理汇总
2014/10/21 Python
python利用正则表达式提取字符串
2016/12/08 Python
Pandas读取并修改excel的示例代码
2019/02/17 Python
创建Django项目图文实例详解
2019/06/06 Python
基于Django集成CAS实现流程详解
2020/11/28 Python
英国儿童图书网站:Scholastic
2017/03/26 全球购物
年度考核自我鉴定
2014/03/19 职场文书
2015年酒店工作总结
2015/04/28 职场文书
关于环保的宣传稿
2015/07/23 职场文书
浅谈Laravel中使用Slack进行异常通知
2021/05/29 PHP
win10忘记pin密码登录不了怎么办?win10忘记pin密码登不进去的解决方法
2022/07/07 数码科技