最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 前端模拟 win 10 日历背景特效

    正文概述 掘金(玄晓乌屋)   2021-08-20   498

    这几日学习了 svg 相关知识,想到曾经有同事说 win 10 日历背景特效狠厉害。当时还没有学习 svg,仅用 HTML + CSS 实现的话感觉非常复杂。这几日看了大部分 svg 相关知识后,觉得使用 svg 来实现的话会稍微简单些。

    点击 win 10 右下角的日期,用鼠标在日历间移动时,可以看到背景使用了一个径向渐变效果,并且这个渐变仅作用在边框上。

    html + css 实现

    如果使用 HTML + CSS,那么就需要在径向渐变的背景上使用 HTML 遮盖渐变,使其仅留出边框的区域。这听起来挺勉强的,实现起来也是一样,这将为每个日期框生成一个冗余的元素。因为是使用 HTML 元素对径向渐变进行覆盖,并配色上就不那么灵活,如果遇到背景是一张图片,那么这个将难以实现。

    假定背景为纯黑的情况下,使用 HTML + CSS 实现如下:

    <!DOCTYPE html>
    <html lang="zh-CN">
      <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>
          .root div {
            pointer-events: none;
          }
          .root {
            background: #000;
            width: 500px;
            height: 500px;
            position: relative;
          }
          .gradient {
            position: absolute;
            left: 20px;
            top: 30px;
            width: 200px;
            height: 200px;
            background: radial-gradient(rgba(200, 200, 200, 1), rgba(200, 200, 200, 0) 75%, rgba(200, 200, 200, 0));
          }
          .root div:not(.gradient) {
            position: relative;
            z-index: 1;
            box-sizing: border-box;
            width: 100px;
            height: 100px;
            float: left;
            padding: 10px;
            background: content-box #000;
            border: 2px solid #000;
          }
        </style>
      </head>
      <body>
        <div id="root" class="root">
          <div id="gradient" class="gradient"></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
        </div>
        <script>
          const root = document.getElementById("root");
          const gradient = document.getElementById("gradient");
          root.onmousemove = function (e) {
            gradient.style.left = e.offsetX - 100 + "px";
            gradient.style.top = e.offsetY - 100 + "px";
          };
        </script>
      </body>
    </html>
    

    使用 svg 实现

    使用 svg 实现会变得很自然,因为 svg 是可以把径向渐变绘制到日期边框所在区域上。

    我们只会要把日期框路径绘制出来,然后填充径向渐变即可。因为日期框是规则的,所以只需要一个二重循环即可生成路径。

    详细代码如下:

    <!DOCTYPE html>
    <html lang="zh-CN">
      <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>
      </head>
      <body>
        <svg id="Calendar" version="1.1" xmlns="http://www.w3.org/2000/svg" width="500" height="500" viewBox="0 0 70 70">
          <defs>
            <style type="text/css">
              rect {
                pointer-events: all;
              }
            </style>
            <radialGradient id="Linear-1" cx="0.2" cy="0.5" r="0.2">
              <stop stop-color="#bbb" stop-opacity="1" offset="0" />
              <stop stop-color="#bbb" stop-opacity="0" offset="1" />
            </radialGradient>
            <g id="boxs">
              <rect x="0" y="0" width="100%" height="100%" fill="#000" />
            </g>
          </defs>
          <use href="#boxs" />
          <path stroke="#eee" stroke-width="0.5" />
        </svg>
    
        <script>
          (function () {
            const NS = "http://www.w3.org/2000/svg";
            const boxs = document.getElementById("boxs");
            // 行数
            const rows = [..."1234567"];
            // 列数
            const dayLabels = [..."日一二三四五六"];
    
            function createSVGEl(name) {
              return document.createElementNS(NS, name);
            }
    
            function setElAttrbute(obj, attrs) {
              Object.keys(attrs).forEach((key) => obj.setAttribute(key, attrs[key]));
            }
    
            // 渐变路径
            const pathBox = createSVGEl("path");
            // 日期框数组,用来高亮每个日期框
            const rectBoxItems = [];
    
            // 整理路径
            const d = rows.reduce(function (prev, _, r) {
              var dRow = dayLabels.reduce(function (prev, _, i) {
                var x = i * 10 + 0.5;
                var y = r * 10 + 0.5;
    
                // 顺带生成日期框
                const rectBoxItem = createSVGEl("rect");
                setElAttrbute(rectBoxItem, {
                  x,
                  y,
                  width: 9,
                  height: 9,
                  "stroke-width": 0.5,
                  fill: "transparent",
                });
                // :hover 伪类不生效,只能使用事件高亮
                rectBoxItem.onmouseenter = () => (rectBoxItem.style.stroke = "#ddd");
                rectBoxItem.onmouseout = () => (rectBoxItem.style.stroke = "");
                rectBoxItems.push(rectBoxItem);
    
                return (prev += `M ${x} ${y} l 9 0 l 0 9 l -9 0 z `);
              }, "");
              return (prev += dRow);
            }, "");
    
            // 使用渐变渲染路径框
            setElAttrbute(pathBox, {
              d,
              stroke: "url(#Linear-1)",
              "stroke-width": 0.5,
            });
    
            // 挂载路径和日期框
            boxs.appendChild(pathBox);
            rectBoxItems.forEach((v) => boxs.appendChild(v));
    
            // 获取日历背景和渐变
            const Calendar = document.getElementById("Calendar");
            const Linear1 = document.getElementById("Linear-1");
    
            // 让渐变跟随日历内的鼠标移动
            Calendar.addEventListener("mousemove", function (e) {
              const { width, height } = e.target.getBoundingClientRect();
              const x = e.offsetX / width;
              const y = e.offsetY / height;
    
              requestAnimationFrame(function () {
                Linear1.setAttribute("cx", x);
                Linear1.setAttribute("cy", y);
              });
            });
          })();
        </script>
      </body>
    </html>
    

    起源地下载网 » 前端模拟 win 10 日历背景特效

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元