【问题标题】:Changing SVG's gradient using JS使用 JS 更改 SVG 的渐变
【发布时间】:2019-10-10 09:40:46
【问题描述】:

我正在尝试通过更改 stop-color 属性来更改以下 SVG 元素中渐变的停止颜色,但它不起作用:

<svg><defs> 
<linearGradient gradientTransform="rotate(90)">
<stop offset="40%" stop-color="purple" id="firstGradient"/>
<stop offset="100%" stop-color="red" id="secondGradient"/>
</linearGradient>
</defs>
<Here's a long line of picture>
</svg>

我正在使用以下脚本语句来尝试更改停止颜色:

document.getElementById("firstGradient").stopColor ="red";

我也试过document.getElementById("firstGradient").attr.stop-color = "red";。

这两种方法都不起作用。如何更改停止颜色?

【问题讨论】:

  • &lt;Here's a long line of picture&gt; 到底是什么?该语法无效,请在此处放置一些有效内容-我们无法阅读您对渐变的确切用途的想法(更改渐变反映在某些内容上,而不是仅反映在渐变上,因此说“无效”很漂亮如果没有您的问题省略的内容,很多都无法验证)。
  • 顺便问一下,stopColor 属性是什么?你是从哪里听说的?

标签: javascript html svg gradient


【解决方案1】:

您犯的错误是假设-我不确定您使用什么资源作为参考-是在document.getElementByid("firstGradient") 返回的任何对象上定义了stopColor 属性。没有。

您称为“firstGradient”的元素是SVGStopElement,从规范中可以看出,它不提供任何stopColor 属性。

但不必担心——通过更改实际元素属性来更改停止颜色,这就是文档对象模型的工作方式——您根本不需要使用元素的任何特殊属性来更改实际属性:

document.getElementById("firstGradient").setAttribute("stop-color", "red");

就是这样。 setAttribute 函数可用于任何文档元素、SVG、HTML 或任何其他命名空间/种类。

顺便说一句,我不会将停止颜色称为渐变 - 将您调用的元素称为“firstGradient”只是一种误导 - 它是 停止颜色 而不是 渐变,渐变是实际的linearGradient 元素。因此,如果要分配标识符,请将“gradientFirstStopColor”和“gradientSecondStopColor”分别分配给第一个和第二个stop 元素,如果有的话。

但您也可以使用它们在子层次结构中的顺序来识别停止颜色元素:

document.querySelector("linearGradient > stop:nth-of-type(1)").setAttribute("stop-color", "red");

您可以使用其他 CSS 选择器或 API(例如 querySelectorAll("linearGradient &gt; stop")[1]),我的意思是您不必绝对求助于分配标识符,尽管这在某些情况下会有所帮助——它们绝对有其合法用途。

当然,在 stop 元素上使用 style 属性也可以,但我个人认为在非渲染(渐变本身不渲染)元素上使用 style 的语义是疯狂的——这是一个基本上是泄漏抽象。

【讨论】:

    【解决方案2】:

    现在是 2022 年,我们拥有原生 JavaScript Web 组件

    将您的&lt;svg&gt; 包装在&lt;svg-gradient&gt; 中 Onload 它将读取定义的GRAD 颜色数组并创建 &lt;stop &gt; 值在您的&lt;svg&gt; 中

    注意你定义和使用GRAD的3个地方;这允许在您的 &lt;svg&gt; 中使用多个渐变

    <svg-gradient GRAD="red,red,red,red,red,red,#f8991d,#ffe400,#51ff00,#0066ae,#1b449c,#792b87">
      <svg viewBox="0 0 512 512">
        <defs>
          <linearGradient id="GRAD"></linearGradient>
        </defs>
        <circle r="255" cx="256" cy="256" fill="url(#GRAD)" />
      </svg>
    </svg-gradient>
    
    
    <script>
      customElements.define("svg-gradient", class extends HTMLElement {
        connectedCallback() {
          setTimeout(() => { // make sure innerHTML was parsed
            this.querySelectorAll("linearGradient")
              .forEach(gradient => {
                gradient.innerHTML =
                  this
                  .getAttribute(gradient.id)
                  .split(",")
                  .map((color, idx, colors) => 
                     `<stop offset="${idx*1/colors.length}" stop-color="${color}"/>`)
                  .join("")
              });
          })
        }
      })
    </script>

    【讨论】:

      【解决方案3】:

      你试过了吗:

      document.getElementById("firstGradient").style.stopColor ="red";
      

      【讨论】:

      • 非常感谢。我不知道为什么我不尝试通过“风格”来做到这一点。它的工作。但是,我仍然不明白为什么这种构造有效,毕竟有名为“stop-color”但没有“stopColor”的样式。你知道它为什么有效吗?为什么输入“style.stop-color”不正确?
      • 由于一致性,您应该使用 camelCase 而不是 kebab-case
      • 它与一致性无关,它与流行的标准规范mandate it behave有关。这一切都在第 5.6.1 节中进一步详细说明。
      猜你喜欢
      • 2016-01-27
      • 1970-01-01
      • 2018-08-05
      • 2012-12-12
      • 1970-01-01
      • 2019-02-15
      • 2014-02-18
      • 2022-01-10
      相关资源
      最近更新 更多