我可以沿 SVG 路径应用渐变吗?

Posted

技术标签:

【中文标题】我可以沿 SVG 路径应用渐变吗?【英文标题】:Can I apply a gradient along an SVG path? 【发布时间】:2013-01-16 00:02:39 【问题描述】:

我想在我的网站上放置一个由脚本触发的简单加载指示器。它应该是一个简单的圆弧,它有一个渐变并且在用户等待时正在旋转。我还没有尝试过动画部分,但现在停留在静态样式上。到目前为止,这是我所得到的:

<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg"
         >
        <defs>
            <linearGradient id="grad1">
                <stop offset="0%" stop-color="red"/>
                <stop offset="100%" stop-color="red" stop-opacity="0" />
            </linearGradient>
        </defs>
        <path d="M50 10  A40 40 0 1 0 90 50"
            stroke="url(#grad1)" stroke- fill="transparent"/>
    </svg>

它绘制弧线,从上边缘逆时针到右边缘(270°),但渐变是错误的。不是按照路径使开始(上边缘,0°)不透明,结束(右边缘,270°)透明,而是在屏幕空间中从左到右对弧形笔划的结果图像进行着色。

如何使渐变跟随我的弧形路径?

【问题讨论】:

请反对者解释为什么他们认为这个问题不值得问? 【参考方案1】:

迈克·博斯托克想出了一个办法,尽管这并不容易: https://bl.ocks.org/mbostock/4163057

基本上,此技术使用getPointAtLength 将笔画分割成许多短笔画,为每个短笔画指定内插色标,然后对这些标画之间的每个短笔画应用渐变。

如果你能接受挑战,祝你好运;)

编辑(2019 年 7 月 3 日):

There is now a library that will help you do exactly what you're looking for. 不需要使用 D3,但如果您愿意,可以使用。 Here's a tutorial on Medium.

【讨论】:

基本上这意味着“不”。 Mike Bostock 所做的是完全自己创建渐变。您可以复制他的代码,并尝试对其进行修改以满足您的需求,但就像已经说过的那样,它不会那么简单...... :) 这些正是我们现在急需更新 SVG 标准的确切例子!【参考方案2】:

这种渐变在 SVG 中不容易实现,请参阅SVG angular gradient。

另外,transparent 不是 SVG 中的有效颜色。你应该在这个例子中声明stop-opacity:http://jsfiddle.net/WF2CS/

恐怕最简单的解决方案可能是一系列具有不同不透明度的小弧形路径。

【讨论】:

是的,我想过合并许多小弧段,但不幸的是,您不能只指定边界框和开始和停止角度,而是需要告诉它停止的 x 和 y 坐标.这是一大堆十进制数字并离线计算它们。【参考方案3】:

path
 fill : url(#gradient)
<svg  >
  <defs>
    <linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="0%">
      <stop offset="0%"   stop-color="#05a"/>
      <stop offset="100%" stop-color="#0a5"/>
    </linearGradient>
  </defs>
 <path d="M150 0 L75 200 L225 200 Z" />
</svg>

【讨论】:

如果有多个path,则不是预期结果【参考方案4】:

我也遇到了这个问题,所以I created a library to assist 在创建遵循path 的渐变。如果您愿意,您可以在 javascript 中单独使用它或与 D3.js 一起使用它。该库 100% 基于 Mike Bostock 在第一个答案中引用的工作,但我已将 D3 作为必需的依赖项删除。

I've also written a brief tutorial on Medium describing the backstory and usage..

【讨论】:

请使用@Dostonbek Oripjonov 方法,因为使用这种方法,浏览器的开发人员将处理更新和修复。它还应该比 javascript 运行 x10 更好。 很棒的工作,@cereal。在没有 D3 的情况下使其可用的道具。 @jpsilver:您似乎忽略了当今浏览器在 JavaScript 引擎上运行的事实。你是说 JavaScript 比 JavaScript 好 10 倍?此外,您推荐的解决方案根本无法回答所提出的问题。 @tao 对不起,我不是很清楚,我的意思是优化的 javascript 比 javascript 好 10 倍,浏览器的开发人员会编写最适合浏览器的,在任何编程语言中最好使用内置方法,因为它们更加优化。【参考方案5】:

CSS 图像模块 - 第 4 级引入了conic-gradient。根据 MDN,it's supported 在除 IE 之外的所有主流浏览器中都可以使用。

虽然从技术上讲,它不是沿路径的渐变,但由于您的路径是一个圆圈,因此可以通过以下方式实现所需的结果:

.loader 
  --size: 7.5rem;
  --stroke-size: .5rem;
  --diff: calc(calc(var(--size)/2) - var(--stroke-size));
  background-image: conic-gradient(transparent 25%, red);
  width: var(--size);
  height: var(--size);
  border-radius: 50%;
  -webkit-mask:radial-gradient(circle var(--diff),transparent 98%,#fff 100%);
          mask:radial-gradient(circle var(--diff),transparent 98%,#fff 100%);
  animation: rotate 1.2s linear infinite;
  margin: 0 auto;

@keyframes rotate 
  from 
    transform: rotate(0);
  
  to 
    transform: rotate(1turn);
  

body 
  background: #f9fcfc url(https://picsum.photos/id/22/1323/880) 100% /cover;
  margin: 0;
  min-height: 100vh;
  padding-top: 2.5rem;

 *  box-sizing: border-box; 
&lt;div class="loader"&gt;&lt;/div&gt;

相关位是

background-image: conic-gradient(transparent 25%, red);

注意:如果不是很明显,CSS 变量不是必需的,我只是想要一种方法来测试它的多种尺寸,而不必在多个地方修改值。注意: 也可以使用&lt;svg /&gt; 来掩盖内圈。我怀疑它可能比mask 有更好的浏览器支持。但这超出了这个问题的范围。

在发布时,我的示例似乎在最新版本中按预期工作:Chrome、Firefox 和 Edge。没有测试过 Safari。没想到它可以在任何版本的 IE 中工作。

【讨论】:

【参考方案6】:

另一种方法是制作两个半圆并对每个笔划应用相反的线性渐变,并确保它们都包含在 g 元素中。 (在我的示例中,组合渐变不是 270 度而是 360。两个半圆垂直堆叠。第一个渐变(应用于顶部半圆的笔划)将是 100-50% 的不透明度,然后下一个将具有 0 % 到 50%。两个梯度都将单位向量设置为 x1,y1,y2=0 和 x2=1,使它们从左到右运行。)然后将 transform=rotate(deg,ctrX,ctrY) 应用于 g。

【讨论】:

听起来梯度分布不均匀。它在每个半圈的中间走得更快,并在它们的连接端静止不动。一个改进是使用 4 个四分之一圆,为了让它完美,你需要无限多的 sircle 段......即。渲染每个像素。【参考方案7】:

我设法在https://www.w3schools.com/graphics/svg_grad_radial.asp 之后应用了某种渐变。

例如: Codepen svg multiple path

<!DOCTYPE html>
<html>
<body>

<svg   >
  <defs>
    <radialGradient id="grad1" cx="50%" cy="55%" r="50%">
    <stop offset="90%" style="stop-color:rgb(31, 175, 198); stop-opacity: .5" />
    <stop offset="100%" style="stop-color:rgb(161, 211, 60); stop-opacity: .5" />
    </radialGradient>
  </defs>
  <path d="M92.2871 10.1699C90.3999 25.8964 84.8432 45.0828 82.1173 45.0828C81.3834 45.0828 76.3509 42.986 71.0038 40.4697C62.4067 36.4856 49.3012 32.5016 44.4784 32.5016C43.2202 32.5016 43.8493 34.3888 46.8898 40.5746C51.5029 49.9057 55.6966 64.4789 55.1724 69.5114L54.8579 72.8664L45.422 73.6004C17.9529 75.6972 5.05709 76.9554 5.05709 77.4796C5.05709 77.899 9.67022 82.8266 15.3318 88.593C25.921 99.2871 33.6795 110.715 33.1552 114.699C32.9455 116.167 27.5985 120.57 16.5899 128.224C7.67819 134.41 0.234278 139.966 0.0245907 140.491C-0.185097 141.015 0.968185 141.749 2.64569 142.168C13.864 144.58 18.6868 146.152 22.6709 148.459C28.1227 151.709 33.7843 156.532 36.6151 160.516L38.712 163.451L26.9694 175.089C17.1141 184.944 15.4366 186.937 16.6948 188.09C17.5335 188.824 23.8241 191.235 30.7438 193.332C37.6635 195.429 43.7445 197.631 44.2687 198.155C44.7929 198.679 43.9541 204.026 41.9621 211.365C40.1798 218.18 39.0265 224.156 39.341 224.68C39.8652 225.624 57.1645 224.785 59.9952 223.737C62.6163 222.793 63.6648 225.309 64.3987 233.592C64.8181 238.415 65.4471 242.504 65.8665 242.713C66.7052 243.238 78.4478 238.205 78.4478 237.366C78.4478 237.052 77.0848 234.85 75.4073 232.439C70.5845 225.414 67.3343 218.18 64.2938 208.115C62.826 202.873 60.6243 195.848 59.5759 192.388C58.4226 188.929 57.2693 184.211 57.0596 181.904C55.5918 170.791 55.3821 166.702 56.4306 166.702C56.9548 166.702 57.479 168.484 57.479 170.581C57.5838 175.299 59.8904 187.88 61.4631 192.388C62.0921 194.066 64.0842 200.252 65.8665 206.018C70.1651 219.543 76.3509 231.705 81.6979 237.052C84.2142 239.568 89.666 243.133 94.9082 245.544L103.715 249.633L103.401 253.512L103.086 257.392L79.7059 265.15L56.3257 273.013L53.2852 282.973C51.6077 288.53 46.8898 304.991 42.696 319.669C38.5023 334.242 34.5182 346.823 33.8891 347.452C33.2601 348.081 31.3729 353.743 29.8002 360.138C28.2276 366.429 26.7598 372.51 26.4452 373.454C25.921 375.236 30.1148 375.341 104.554 375.341C179.098 375.341 183.292 375.236 183.292 373.454C183.292 372.51 178.364 367.058 172.283 361.397C166.202 355.735 161.274 350.493 161.274 349.654C161.274 348.92 165.049 345.041 169.557 341.057C181.09 331.202 181.195 330.573 176.477 318.515C168.509 298.281 151.419 267.037 145.128 261.166C143.136 259.279 142.402 257.496 142.402 254.666C142.402 250.367 143.346 249.319 148.693 247.536C154.145 245.754 159.492 241.665 163.162 236.528C166.097 232.439 167.355 231.705 175.428 229.189C180.356 227.616 184.34 225.938 184.34 225.519C184.34 224.995 182.453 222.269 180.146 219.543C175.638 214.091 174.799 210.212 177.84 209.268C178.783 208.954 182.453 208.429 185.913 208.01C189.372 207.696 192.518 207.171 192.937 206.857C193.881 206.437 188.534 191.55 187.276 191.025C186.856 190.816 186.437 189.872 186.437 188.824C186.437 187.566 187.905 186.622 191.679 185.678C198.179 184.001 213.696 176.557 213.696 175.194C213.696 174.565 211.704 173.097 209.293 171.839C195.873 165.024 184.969 157.161 187.171 155.903C187.59 155.693 191.469 154.435 195.663 153.177C199.857 151.919 206.672 149.298 210.865 147.41C218.1 144.16 232.988 135.353 232.358 134.724C231.939 134.41 203.526 122.248 200.8 121.304C199.542 120.78 199.228 120.151 199.752 119.207C200.171 118.369 207.091 111.659 215.059 104.32C222.923 96.8757 229.423 90.4802 229.423 90.0608C229.423 89.2221 222.922 88.0688 203.736 85.3429C196.816 84.2944 190.735 83.246 190.316 82.8266C189.792 82.4072 194.615 73.181 201.01 62.3821C211.39 44.6635 213.382 40.8891 212.333 40.8891C212.124 40.8891 203.526 43.9296 193.252 47.7039C178.259 53.1558 174.17 54.2043 173.122 53.1558C170.815 50.8493 168.613 33.55 168.613 18.0331V3.04048L160.121 7.54876C150.161 12.8958 136.846 23.2753 130.66 30.5096C128.353 33.3403 125.942 35.6469 125.523 35.6469C124.998 35.6469 121.014 30.8241 116.506 24.848C108.748 14.5733 95.6421 6.4671e-06 94.1743 6.4671e-06C93.7549 6.4671e-06 92.9162 4.61313 92.2871 10.1699ZM95.2228 272.908C91.3435 275.949 71.5281 328.266 73.1007 330.992C73.6249 331.935 78.1332 336.234 83.1657 340.638C88.3031 345.041 92.6017 349.13 92.8114 349.759C93.021 350.388 91.7629 352.695 89.9806 354.896C88.3031 357.098 86.8353 358.251 86.8353 357.517C86.8353 356.888 87.7788 355.001 89.037 353.533L91.2387 350.703L81.1737 341.267C74.1492 334.661 71.1087 331.097 71.1087 329.419C71.1087 326.064 83.0609 293.982 90.3999 277.522C92.1823 273.537 93.6501 271.545 94.9082 271.545C96.5857 271.65 96.5857 271.755 95.2228 272.908Z" fill="url(#grad1)"></path>
<path d="M270.733 147.306C241.272 152.653 225.021 164.29 203.948 195.429C199.335 202.139 199.02 202.978 199.02 209.478C199.02 214.51 197.972 219.438 195.246 227.93C190.633 242.294 190.842 245.649 197.447 256.867C200.068 261.271 202.165 265.465 202.165 265.989C202.165 266.618 200.802 268.61 199.02 270.497C193.463 276.473 193.568 285.699 199.335 291.885C202.69 295.345 210.553 298.595 212.65 297.232C213.174 296.918 212.44 294.506 211.077 291.78C209.609 289.159 208.456 286.224 208.561 285.28C208.561 284.232 209.085 284.546 209.714 286.224C211.496 290.103 219.779 302.894 223.868 307.926C231.941 317.991 249.345 328.161 265.596 332.46C270.524 333.718 279.226 334.871 286.565 335.186C293.484 335.5 298.202 336.129 297.049 336.549C290.758 338.75 261.821 334.661 248.506 329.629L241.587 327.008L239.804 329.419C233.199 338.121 225.65 357.937 223.763 371.357L223.239 375.341H288.242C349.681 375.341 353.245 375.236 352.721 373.454C352.407 372.51 350.729 366.219 349.052 359.509C345.382 345.041 342.446 337.807 337.728 331.621C335.841 329.105 334.269 326.484 334.269 325.75C334.373 325.121 336.994 322.604 340.245 320.298C346.116 316.104 354.189 307.612 358.592 300.902C360.06 298.7 362.367 296.918 364.464 296.289C366.246 295.764 369.601 293.563 371.907 291.466C379.142 284.546 379.876 275.11 373.48 269.553C371.278 267.666 370.964 266.723 371.593 263.368C372.012 261.271 372.641 259.279 373.061 258.964C373.48 258.65 374.424 255.609 375.158 252.149C376.206 247.117 376.206 243.238 375.158 232.439C374.424 225.1 373.375 219.124 372.851 219.124C372.327 219.124 372.012 216.188 372.117 212.518C372.327 206.752 371.803 204.97 368.028 197.631C362.996 187.67 355.552 176.767 348.003 168.589C343.39 163.556 340.349 161.564 328.502 155.693C320.115 151.604 311.517 148.144 307.324 147.306C298.622 145.418 280.798 145.418 270.733 147.306Z" fill="url(#grad1)"></path>
<path d="M147.646 261.69C147.646 262.005 149.638 264.94 152.154 268.19C154.67 271.441 158.13 276.578 160.017 279.409C164.945 287.272 176.373 311.805 179.728 321.556C183.397 331.935 183.083 332.669 172.074 342C167.88 345.565 164.421 349.34 164.421 350.178C164.421 351.122 169.138 356.154 174.905 361.606C181.196 367.373 185.389 372.091 185.389 373.349C185.389 375.236 186.228 375.341 200.067 375.341C211.076 375.341 214.746 375.026 214.746 373.978C214.746 369.574 189.059 277.207 186.647 272.804C186.228 271.965 179.518 269.763 171.76 267.771C164.001 265.884 155.928 263.577 153.726 262.634C149.428 260.956 147.646 260.642 147.646 261.69Z" fill="url(#grad1)"></path>
</svg>

</body>
</html>

【讨论】:

以上是关于我可以沿 SVG 路径应用渐变吗?的主要内容,如果未能解决你的问题,请参考以下文章

完美水平路径的 SVG 渐变

iOS - 如何沿路径绘制渐变

在 SwiftUI 中沿路径填充颜色渐变

如何使用 SVG 滤镜创建透明渐变蒙版

SVG 沿路径重复对象或符号

沿 SVG 路径绘制