打工人必备!实现JS控制的SVG渐变图标,让你的页面更加生动有趣

在我们开发界面时,有时候渐变的图像会相比固定颜色的图形更加富有层次感与有趣。熟悉css的同学都知道,我们可以通过样式让背景呈现一个线性的渐变图片,比如这样:

css 复制代码
.simple-linear {
  background: linear-gradient(blue, pink);
}

也可以通过裁剪背景颜色到文本的方式实现文本颜色渐变

css 复制代码
.text-gradient {
  background-image: linear-gradient(to right, orange, purple);
  -webkit-background-clip: text;
  color: transparent;
}

这些解决方案都是网络上随便都能搜到的,那么现在背景渐变有了,文本渐变有了,看上去我们似乎可以实现各种渐变了,但是我们还差一个非常常见的元素没有办法做到渐变,那就是svg图标。

目前网络上所能找到的所有关于svg渐变颜色的方案都是需要通过svg本身的配置来实现的。举个例子:

比如这样:

html 复制代码
<svg
  class="svg-gradient"
  xmlns="<http://www.w3.org/2000/svg>"
  width="24"
  height="24"
  viewBox="0 0 24 24"
>
  <defs xmlns="<http://www.w3.org/2000/svg>">
    <linearGradient y2="0" x2="1" y1="1" x1="1" id="svg_1">
      <stop stop-color="#ff0000" offset="0" />
      <stop stop-color="#ffff00" offset="1" />
    </linearGradient>
  </defs>
  <path
    d="M12 2a9 9 0 0 0-9 9v11l3-3l3 3l3-3l3 3l3-3l3 3V11a9 9 0 0 0-9-9M9 8a2 2 0 0 1 2 2a2 2 0 0 1-2 2a2 2 0 0 1-2-2a2 2 0 0 1 2-2m6 0a2 2 0 0 1 2 2a2 2 0 0 1-2 2a2 2 0 0 1-2-2a2 2 0 0 1 2-2Z"
    fill="url(#svg_1)"
  />
</svg>

这看上去很美好,因为我们我们只需要把这段svg代码复制到我们的项目中,然后需要的时候引用一下就好了。

当然是可以,但是在实际开发中我们往往会遇到更加复杂的挑战。比如我们用的图标是在一个图标库组件中,我们没有办法去直接修改(比如 react-icons )。比如我们需要让图标在渐变色(选中状态)和单色(未选中状态)之间来回切换。

难道我要准备两个一样的仅仅颜色不一样的图标因为状态来选择使用哪个图标么?这很丑陋,且难以维护。

想象一下我们是如何使用单色图标的?仅仅配置 color=#<hex-color> 即可实现不同颜色的切换。为什么渐变色图标不能有类似方式?

我搜索了网络上所有的资料,但是我没有找到我想要的方法,因此我决定自己探索。

一个很少有人会注意到的事实是,<defs> 标签的定义作用域不是父级的svg节点而是整个文档流。因此我们可以跨多个svg声明共用一个svg定义。然后只需要通过固定的id就可以了。

具体方案如下:

html 复制代码
<style>
  .svg-gradient {
    fill: url(#my-gradient);
  }
</style>

<svg width="0" height="0">
  <defs xmlns="<http://www.w3.org/2000/svg>">
    <linearGradient y2="0" x2="1" y1="1" x1="1" id="my-gradient">
      <stop stop-color="#ff0000" offset="0" />
      <stop stop-color="#ffff00" offset="1" />
    </linearGradient>
  </defs>
</svg>

<svg
  class="svg-gradient"
  xmlns="<http://www.w3.org/2000/svg>"
  width="24"
  height="24"
  viewBox="0 0 24 24"
>
  <path
    d="M12 2a9 9 0 0 0-9 9v11l3-3l3 3l3-3l3 3l3-3l3 3V11a9 9 0 0 0-9-9M9 8a2 2 0 0 1 2 2a2 2 0 0 1-2 2a2 2 0 0 1-2-2a2 2 0 0 1 2-2m6 0a2 2 0 0 1 2 2a2 2 0 0 1-2 2a2 2 0 0 1-2-2a2 2 0 0 1 2-2Z"
  />
</svg>

只需要我们把第一个表示颜色定义的svg放在全局预先加载,然后给定义的渐变色起一个有意义的名字,然后我们就可以在任意地方直接在svg的样式上告知需要采用的fill颜色即可 fill: url(#my-gradient);

颜色的切换就变成了 fill 属性的切换,这样就和单色图标一样了。

需要注意的是需要给用于声明的svg的宽高设为0,不然浏览器会给一个默认的宽高,会影响整体的布局。

最终看下成品效果:

相关推荐
海哥编程25 分钟前
Python 进阶(七):XML 基本操作
xml·javascript·python
未来之窗软件服务1 小时前
免费版酒店管理系统之极简表单设计登录设计——仙盟创梦IDE
前端·css·仙盟创梦ide·东方仙盟·登录设计
我是哈哈hh1 小时前
【AJAX】XMLHttpRequest、Promise 与 axios的关系
前端·javascript·ajax·xmlhttprequest·promise
nelly5214 小时前
CRMEB 单商户PRO多商户通用去版权教程
开发语言·前端·javascript
leo_qiu_s4 小时前
前端/后端,前台/中台/后台概念区别
前端·后端
穆罕周5 小时前
AI聊天方案:vue+nodeJs+SSE
前端·javascript·vue.js
ca_rry7 小时前
html结构解析
前端·html
子柒s7 小时前
HTML 基础
前端·html
三月的一天7 小时前
React+Three.js实现3D场景压力/温度/密度分布可视化
前端·javascript·react.js