关于javascript:css-的-filter属性竟然如此好玩

60次阅读

共计 7543 个字符,预计需要花费 19 分钟才能阅读完成。

css 的 filter 属性居然如此好玩

背景

     在此之前我对 css 外面的 filter 属性不是很理解, 只晓得应用这个属性来扭转 svg 图片的色彩, 最近恰好查了很多相干文档并做了大量试验, 并有了一些启发与想法, 索性就在这里分享进去。

一、filter 滤镜

     “ 滤镜 ” 这个名字很贴切了, 能够了解成为元素增加各种显示成果, 先不必记各种名词咱们间接看成果, 应用办法 & 效果图:

<style>
  #lulu {filter: grayscale(1);
  }
</style>

<body>
  <img id="lulu" src="./img/ 头像.jpeg" />
</body>

     看上图里的这些成果, 比方第一排第一个, 咱们会想到在某些特定的纪念日网站整体会变成灰色的款式, 应该就是用的这个属性, 第二排的第一张就能够用与某些事物被 ” 雷击 ”?

二、做一个 ’ 抖动 ’ 特效


     看到这张图我第一个想法就是做个抖动的特效, 就是那种很动感的成果:

     当然配合上一旋转成果也不错:

     原理就是两个图片层叠在一起, 下面的图片进行放大与旋转动画:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Document</title>
  <style>
    .box {
      position: relative;
      border: 1px solid gray;
      display: flex;
      overflow: hidden;
      width: 110px;
      padding: 0px;
      margin-top: 100px;
      margin-left: 300px;
    }

    .box>img {
      width: 100px;
      height: 100px;
      margin-left: 6px;
      filter: invert(1);
    }

    .mk {
      position: absolute;
      top: 0;
      left: 0;
      opacity: 0.5;
      animation: cc 0.5s linear infinite;
    }

    @keyframes cc {
      from {transform: scale(1.2);
      }

      to {transform: scale(1);
      }
    }

    .mk2 {
      position: absolute;
      top: 0;
      left: 0;
      opacity: 0.5;
      animation: cc2 0.5s linear infinite alternate;
      border-radius: 50%;
      overflow: hidden;
    }

    @keyframes cc2 {
      from {transform: scale(2.2) rotate(30deg);
      }

      to {transform: scale(1) rotate(0deg);
      }
    }
  </style>
</head>

<body>
  <div class="box">
    <img src="./img/ 头像.jpeg" />
    <img class="mk" src="./img/ 头像.jpeg" />
  </div>

  <div class="box">
    <img src="./img/ 头像.jpeg" />
    <img class="mk2" src="./img/ 头像.jpeg" />
  </div>
</body>

</html>

三、drop-shadow 暗影

     filter属性通过设置 drop-shadow 为元素增加暗影, 可是早就有 box-shadow 属性了呀, 那这两个属性有什么区别了?

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Document</title>
  <style>
    #w1 {
      width: 50px;
      height: 50px;
      font-size: 36px;
      font-weight: 900;
      box-shadow: 0 0 2px red;
    }

    #w2 {
      width: 50px;
      height: 50px;
      font-size: 36px;
      font-weight: 900;
      filter: drop-shadow(0px 0px 2px red);
    }
  </style>
</head>

<body>
  <p id="w1"> 九 </p>
  <p id="w2"> 九 </p>
</body>

</html>

     上图可知, box-shadow是针对整个 dom 元素 进行暗影的产生, 然而 drop-shadow 会疏忽掉 ” 通明 ” 的局部。

四、drop-shadow 复制 (做一个看图猜人物游戏)

     留神: 我这里应用的都是 svg 图片。

     既然与 box-shadow 都有为元素设置暗影的能力, 那么 box-shadow 有复制本身样的能力 drop-shadow 是都也有?

     所谓 box-shadow 的复制本身款式如图所示, box-shadow能够制作 n 个与元素自身形态雷同或不同的款式, 下图右侧红色的方块就是左图的暗影:

     再看一下 drop-shadow 的体现:

     看到下面的图我第一反馈就是 ” 猜人物 ” 小游戏, 咱们把人物的轮廓也就是右图显示进去, 而后在颁布答案的时候展现左侧的原图即可。

赋值 gif 图有 bug

     赋值 gif 图会有 bug, 成果如下:

五、drop-shadow 批量复制

     box-shadow属性是能够写多个属性值的, 我个别会利用这个属性进行一个繁多款式的 dom 元素的复制 成果如下图:

     drop-shadow有点 ’ 狠 ’, 他的每一次复制都是基于上次的整体成果进行的暗影投射:

     上图能够看出, 第一个复制后是呈现了横排的 2 个, 第二次投射是产生了下方的两个, 并且每次投射都是叠加的, 上面咱们看一组更夸大的:

     可想而知这种增长形式有多可怕, 略微写几遍就能够笼罩满屏幕了。

“ 找不同 ” 小游戏

     咱们能够做一片暗影, 然而其中某个咱们独自做一个款式进行笼罩, 考考大家的目力, 就如图例所示:

     这里就是利用 drop-shadow 产生暗影, 而后再进行一点批改, 正确答案在这里:

     所以只有再写两段代码, 就能够让这个 8 ×8 变成 16×16 那么多, 应该还挺好玩的。

六、drop-shadow 与 box-shadow 的联结

     drop-shadowbox-shadow 都有投射的能力, 那么他两个属性独特作用于一个元素会是怎么的:

     box-shadow会基于 drop-shadow 属性产生的全副投影进行透射暗影, 第一排是 drop-shadow 的投影, 第二排是 box-shadow 的投影, 具体怎么玩我还没想到太适宜的。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
        #wrap {
            position: relative;
            height: 350px;
            width: 500px;
            margin: 50px auto;
            overflow: hidden;
        }

        #n {
            border: 1px solid gray;
            width: 50px;
            box-shadow: 0 200px;
            transform: rotate(10deg);
            filter: drop-shadow(70px 0) drop-shadow(140px 0px);
        }
    </style>
</head>

<body>
    <div id="wrap">
        <img id="n" src="./svg/ 人.svg" /
    </div>
</body>

</html>

七、drop-shadow 复制后的 ’ 静止 ’

     既然能够投射出那么多投影, 那么如果我元素进行旋转的话, 投影是否也会进行旋转? 并且它是以什么法则静止的那?

     上面演示的是, 物体投影 + 物体自身旋转:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
        #wrap {
            position: relative;
            height: 350px;
            width: 400px;
            margin: 250px auto;
        }

        #n {
            width: 20px;
            filter: drop-shadow(25px 0) drop-shadow(50px 0px) drop-shadow(100px 0);
            animation: rr 2s linear infinite;
        }

        @keyframes rr {
            0% {transform: rotate(0);
            }

            100% {transform: rotate(360deg);
            }
        }
    </style>
</head>

<body>
    <div id="wrap">
        <img id="n" src="./svg/ 人.svg" />
    </div>
</body>

</html>

     下面是整体以 ’ 元素 ’ 自身为旋转点进行旋转, 那要如何让 ’ 元素 ’ 的每个投影都以本身为原点旋转那?

     这里的思路就是, 在 img 外包裹一层 div, 咱们对外层div 进行投影, 外部的 img 负责旋转:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
        #wrap {
            position: relative;
            height: 350px;
            width: 400px;
            margin: 250px auto;
        }

        #box {
            width: 20px;
            height: 20px;
            filter: drop-shadow(25px 0) drop-shadow(50px 0px) drop-shadow(100px 0);
        }

        #n {
            width: 20px;
            animation: rr 2s linear infinite;
        }

        @keyframes rr {
            0% {transform: rotate(0);
            }

            100% {transform: rotate(360deg);
            }
        }
    </style>
</head>

<body>
    <div id="wrap">
        <div id="box">
            <img id="n" src="./svg/ 人.svg" />
        </div>
    </div>
</body>

</html>

八、filter 属性着色 (svg + png) 图片

     扭转 svg 色彩最间接的办法就是改其自身的 fill 属性, 这里不做探讨, 这里要钻研的是到底为什么 filter 能够扭转图片的色彩, 是什么原理? 这里咱们就一起探索一下(这里只探讨纯色图片)。

轮廓的造成

     并不是所有的图片被赋予 drop-shadow 属性后都会呈现出物体的轮廓, 投影会疏忽通明背景的中央, 所以 png 这种能够定义通明背景的图片才能够被投射出相应的轮廓而不是矩形轮廓, svg 同理。

     比方 jpg 图片无奈设置通明的背景, 所以其投影成果就与 box-shadow 雷同了。

svg + png 投影变色

     咱们能够利用 drop-shadow 制作一个指定色彩的投影, 而后只有将元素自身暗藏, 只留下投影就 ok 了。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
        #box2 {
            display: inline-block;
            overflow: hidden;
        }

        #glasses2 {filter: drop-shadow(200px 0 red);
            transform: translateX(-200px);
        }
    </style>
</head>

<body>
    <div>
        <div id="box2">
            <img id="glasses2" src="./img/ 太阳镜.png" />
        </div>
    </div>
</body>
</html>
色彩的叠加变色有点强!

     有没有方法是间接扭转元素自身的色彩? 我尝试将 drop-shadow 投射在本身地位, 然而投射的暗影永远在元素前面, 我尝试将元素的 opacity 改小, 暗影也会随之变小, 如果设置 opacity:0 则投影也不可见了。

     不论什么色彩无非是三原色合成的色彩, filter属性能够定义那么多种滤镜, 那是不是代表着某些滤镜成果的叠加态就是咱们想要的指标色彩:

     手动生成那么多的属性不事实, 顺着这个思路我找到了一个真的这样做的网站:

为图片混合调色官网

  1. 须要多点几次 Compute Filters 按钮, 直到生成差别度较小的属性。
  2. 如果咱们的元素不是纯彩色, 须要先赋予 filter: brightness(0) saturate(100%) 将其变为纯黑, 因为不同的底色须要变成指标色彩的 filter 属性不同。
  3. 当然啦这里属于头脑一波, 理论我的项目中不会这样去做的。

九、部分清晰

     这里所谓的部分清晰能够设想为, 某张图全部都是含糊的, 然而咱们把一个放大镜放在某处, 此处就会变得清晰, 先看我做的成果:

     这里的原理是这样的, 一共两层, 上层是含糊滤镜的图片, 下层是一个圆形的 div, 并且这个div 的背景图是图片的清晰版, 设置 background-position, 在拖动div 的同时, 实时变换背景的 background-position 地位, 就实现了图里的成果。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Document</title>
  <style>
    * {box-sizing: border-box;}

    #wrap {position: relative;}

    #acc {
      position: absolute;
      left: 0;
      right: 0;
      width: 540px;
      filter: blur(7px);
      pointer-events: none;
    }

    #mk {
      z-index: 2;
      height: 100px;
      width: 100px;
      border-radius: 50%;
      overflow: hidden;
      border: 1px solid blue;
      position: absolute;
      left: 0;
      top: 0;
      background-image: url("./img/ 利姆露 jpeg.jpeg");
      background-size: 540px 562px;
      background-position: 0 0;
      background-repeat: no-repeat;
    }
  </style>
</head>

<body>
  <div id="wrap">
    <div id="mk"></div>
    <img id="acc" src="./img/ 利姆露 jpeg.jpeg" />
  </div>
  <script>
    function drag(elementId) {const element = document.getElementById(elementId);
      const position = {
        offsetX: 0,
        offsetY: 0,
        state: 0,
      }
      function getEvent(event) {return event || window.event;}
      element.addEventListener(
        "mousedown",
        function (event) {var e = getEvent(event);
          position.offsetX = e.offsetX;
          position.offsetY = e.offsetY;
          position.state = 1;
        },
        false
      );
      document.addEventListener(
        "mousemove",
        function (event) {var e = getEvent(event);
          if (position.state) {
            position.endX = e.clientX;
            position.endY = e.clientY;
            element.style.top = position.endY - position.offsetY + "px";
            element.style.left = position.endX - position.offsetX + "px";
            element.style.backgroundPositionX = "-" + element.style.left;
            element.style.backgroundPositionY = "-" + element.style.top;
          }
        },
        false
      );
      element.addEventListener(
        "mouseup",
        function (event) {position.state = 0;},
        false
      );
    }
    drag("mk");
  </script>
</body>

</html>

end

     这次就是这样, 心愿与你一起提高。

正文完
 0