打工人必备!实现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,不然浏览器会给一个默认的宽高,会影响整体的布局。

最终看下成品效果:

相关推荐
treesforest11 分钟前
前端表单提效实践:基于IP地理位置实现国家区号智能预填
前端·网络协议·tcp/ip·ip定位·ip属地
用户2986985301413 分钟前
React 中 Word 文档转图片的实践方案
前端·javascript·react.js
Csvn13 分钟前
异步并发控制:手写并发池、竞态防护与取消的完整方案
前端·javascript
csuzhucong14 分钟前
二十一 - 四十阶魔方
javascript·css·html
专业抄代码选手21 分钟前
06|双缓冲与 Commit:让 Fiber 支持第二次渲染
前端·javascript·react.js
涛涛ing21 分钟前
4.8K Star!一套规则让 AI 帮你写出“像人写的”前端代码
前端
万物智能24 分钟前
OpenHarmony源码树解剖—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
前端·后端
天才熊猫君27 分钟前
通用虚拟滚动表格行拖拽排序:从思路到完整实现
前端·javascript
hh95029 分钟前
Agent Plan × DeepSeek Harness:角色 Prompt 驱动的 Agent 分工优化与协作质量实验
java·前端·人工智能·prompt·adg·agent plan·adg成都社区
xiaominlaopodaren30 分钟前
three.js最小地图运行时(九):TileKey 线框与 cursor 坐标探针
javascript·gis·three.js