如何基于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 相关文章推荐
基于Unit PNG Fix.js有时候在ie6下不正常的解决办法
Jun 26 Javascript
JS Loading功能的简单实现
Nov 29 Javascript
BootStrap3学习笔记(一)之网格系统
May 20 Javascript
微信小程序 css使用技巧总结
Jan 09 Javascript
利用ES6语法重构React组件详解
Mar 02 Javascript
jQuery Validate 校验多个相同name的方法
May 18 jQuery
Three.js基础学习教程
Nov 16 Javascript
Bootstrap 模态框自定义点击和关闭事件详解
Aug 10 Javascript
详解如何创建并发布一个 vue 组件
Nov 08 Javascript
ES6中Set和Map数据结构,Map与其它数据结构互相转换操作实例详解
Feb 28 Javascript
elementUI 动态生成几行几列的方法示例
Jul 11 Javascript
在layui框架中select下拉框监听更改事件的例子
Sep 20 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
dedecms采集中可以过滤多行代码的正则表达式
2007/03/17 PHP
Zend framework处理一个http请求的流程分析
2010/02/08 PHP
php定义参数数量可变的函数用法实例
2015/03/16 PHP
ThinkPHP中order()使用方法详解
2016/04/19 PHP
PHP laravel中的多对多关系实例详解
2017/06/07 PHP
PHP创建XML的方法示例【基于DOMDocument类及SimpleXMLElement类】
2019/09/10 PHP
用YUI做了个标签浏览效果
2007/02/20 Javascript
JavaScript 放大镜 放大倍率和视窗尺寸
2011/05/09 Javascript
HTML中的setCapture和releaseCapture使用介绍
2012/03/21 Javascript
JavaScript 参数中的数组展开 [译]
2012/09/21 Javascript
js获取当前日期代码适用于网页头部
2013/06/27 Javascript
jQuery验证元素是否为空的两种常用方法
2015/03/17 Javascript
JS 实现倒计时数字时钟效果【附实例代码】
2016/03/30 Javascript
Easyui ueditor 整合解决不能编辑的问题(推荐)
2017/06/25 Javascript
JS内部事件机制之单线程原理
2018/07/02 Javascript
JS选取DOM元素常见操作方法实例分析
2018/12/10 Javascript
JavaScript实现动态添加、移除元素或属性的方法分析
2019/01/03 Javascript
react-router4按需加载(踩坑填坑)
2019/01/06 Javascript
使用nvm和nrm优化node.js工作流的方法
2019/01/17 Javascript
如何使用CSS3和JQuery easing 插件制作绚丽菜单
2019/06/18 jQuery
如何实现一个简易版的vuex持久化工具
2019/09/11 Javascript
python检测是文件还是目录的方法
2015/07/03 Python
Python迭代和迭代器详解
2016/11/10 Python
python版微信跳一跳游戏辅助
2018/01/11 Python
pycharm下查看python的变量类型和变量内容的方法
2018/06/26 Python
python utc datetime转换为时间戳的方法
2019/01/15 Python
Python将列表数据写入文件(txt, csv,excel)
2019/04/03 Python
python 利用浏览器 Cookie 模拟登录的用户访问知乎的方法
2019/07/11 Python
Python自动化操作实现图例绘制
2020/07/09 Python
python遍历路径破解表单的示例
2020/11/21 Python
澳大利亚领先的在线美容商店:Facial Co
2017/10/22 全球购物
Myprotein比利时官方网站:欧洲第一运动营养品牌
2020/10/04 全球购物
XMLHttpRequest对象在IE和Firefox中创建方式有没有不同
2016/03/23 面试题
公益活动邀请函
2014/02/05 职场文书
优秀毕业生就业推荐信
2014/05/22 职场文书
高中美术教学反思
2016/02/17 职场文书