微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

HTML SVG重用<use>组<g>并为每个实例分别更改内部元素的属性 更新

如何解决HTML SVG重用<use>组<g>并为每个实例分别更改内部元素的属性 更新

因此,我想重用已分组的svg形状,并针对每个实例分别更改组内元素之一的一个属性。 下面的简化示例创建一个第二个带有内部矩形的圆。现在,我想分别使用javascript更改每个形状的“ my-rect”矩形的“ width”属性。使用id“ my-rect”会更改两个矩形的宽度,但是我只想更改一个

我的目标(如果我的方法是胡说八道):我必须绘制多个这些形状,唯一不同的是矩形的位置和宽度。

<svg height="1000" width="1000">
  <a transform="translate(110,110)">
    <g id="my-group">
      <g>
        <circle r="100" fill="#0000BF" stroke="black" stroke-width="2" fill-opacity="0.8"></circle>
      </g>
      <g>
        <rect id="my-rect" y="-50" height="100" x="-50" width="50">
        </rect>
      </g>
    </g>
  </a>
  <use xlink:href="#my-group" x="340" y="110"/>
</svg>

解决方法

塞恩说:

如果将Web组件自定义元素扩展到SVG命名空间,
更复杂的重用将是可能的

这是真的,您还不能创建自定义SVG 元素。

但是您可以创建一个生成 SVG的自定义元素:

customElements.define("rect-in-circle",class extends HTMLElement{
  connectedCallback(){
    const a = x => this.getAttribute(x);
    this.innerHTML=`<svg viewBox="-100 -100 100 100">`+
                   `<g transform="translate(-50 -50)">`+
                     `<circle r="50" fill="#123456AB"/>`+
                     `<rect y="${a("y")}" height="${a("height")}"`+
                           `x="${a("x")}"  width="${a("width" )}"/>`+
                   `</g></svg>`
  }
});
svg{
  width:100px;
  height:100px;
  background:grey;
  fill:green;
}
<rect-in-circle x=-10 y=-10 width=20 height=20></rect-in-circle>
<rect-in-circle x=-40 y=-20 width=10 height=40></rect-in-circle>
<rect-in-circle x= 10 y= 20 width=30 height= 5></rect-in-circle>

SVG的自定义元素是许多旧式SVG黑客的现代解决方案

更新

如果OP想要一个带有圆形的SVG,我们可以使用shadowDOM和lightDOM内部的元素不显示的事实。我们甚至可以使用 undefined <rect>元素(在HTML名称空间中),以便我们可以轻松地将它们注入SVG字符串中。

<script>
  customElements.define("rects-in-circles",class extends HTMLElement {
    connectedCallback() {
      setTimeout(() => {
        const rects = [...this.children];
        const width = rects.length * 100;
        this.attachShadow({
          mode: "open"
        }).innerHTML = `<svg viewBox='0 0 ${width} 100'>` + 
          rects.map((rect,idx) => `<g transform='translate(${50+100*idx} 50)'>` +
          `<circle r='50' fill='green'/>` +
          rect.outerHTML +
          `</g>`) + "</svg>";

      })
    }
  });

</script>

<rects-in-circles>
  <rect x=-10 y=-10 width=20 height=20></rect>
  <rect x=-40 y=-20 width=10 height=40></rect>
  <rect x=10 y=20 width=30 height=5></rect>
  <rect x=-40 y=-40 width=50 height=50></rect>
</rects-in-circles>

(my)相关的StackOverflow答案:Custom Elements and SVG

,

通过一些技巧,这是可能的。您必须利用CSS继承来获取shadow元素内的一些属性值。在这种情况下,将使用自定义变量来缩放和定位矩形。

为此,必须对标记进行一些重写。首先,您将组写在<defs>元素内,使其成为可重用的模板,但不能单独呈现。其次,将矩形放置在嵌套的<svg overflow="visible">元素内。为该元素提供x / y坐标并将<rect>元素的x / y坐标保留为0,可以更轻松地跟踪在转换操作之后矩形的左侧将结束的位置。

现在,通过scaleX()变换加上位置的translate()实现了矩形的宽度变化。 必须采用CSS转换语法。使用transform属性尚无法使用(尚未)。因此,我们还需要一个transform-origin属性,该属性设置在封闭的<svg>元素的左侧。

该值不是表示比例的具体值,而是表示为默认值为1的变量:var(--scale,1);位置值相同。变量的值分别在style的每个<use>元素的style="--scale:2;--posX:20px; --posY:-10px"属性中设置。请注意,需要编写px个单位!

#my-rect {
    transform-origin: left top;
    transform: translate(var(--posX,0),var(--posY,0)) scaleX(var(--scale,1));
}
<svg height="1000" width="1000">
  <defs>
    <g id="my-group">
      <g>
        <circle r="100" fill="#0000BF" stroke="black" stroke-width="2" fill-opacity="0.8"></circle>
      </g>
      <svg x="-50" y="-50" overflow="visible">
        <rect id="my-rect" height="100" width="50">
        </rect>
      </svg>
    </g>
  </defs>
  <use xlink:href="#my-group" x="110" y="110" style="--scale:1"/>
  <use xlink:href="#my-group" x="340" y="110" style="--scale:2;--posX:20px; --posY:-10px"/>
</svg>

,

这是不可能的。 use元素创建一个closed shadow root,这意味着JS无法访问其内容。尽管您可以分别设置重用元素的实例属性(如果尚未在原始元素上设置它们的属性),则您将无法影响属于重用元素的子元素。

另一种方法是直接重用矩形和圆形元素,并将它们放在新的组中。

,

getAttribute方法对我不起作用,但是可以起作用:

customElements.define("source-link",class extends HTMLElement {
    static get observedAttributes() {
        return ['href'];
    }

    get href() {
        return this.getAttribute('href');
    }

    set href(val) {
        if (val) {
            this.setAttribute('href',val);
        } else {
            this.removeAttribute('href');
        }
    }
    connectedCallback(){
        this.innerHTML= '<a href="' + this.href + '" target="_blank" title="source"><svg fill="#37f" viewBox="0 0 512 512" width="16"><g><path d="M488.727,0H302.545c-12.853,0-23.273,10.42-23.273,23.273c0,12.853,10.42,23.273,23.273h129.997L192.999,286.09    c-9.089,9.089-9.089,23.823,32.912c4.543,4.544,10.499,6.816,16.455,6.816c5.956,11.913-2.271,16.457-6.817L465.455,79.458    v129.997c0,23.273c12.853,23.273-10.42,23.273-23.273V23.273C512,501.58,488.727,0z"/></g><g><path d="M395.636,232.727c-12.853,23.273v209.455H46.545V139.636H256c12.853,23.273-23.273    S268.853,93.091,256,93.091H23.273C10.42,103.511,116.364v372.364C0,512,512h372.364    c12.853,23.273-23.273V256C418.909,243.147,408.489,232.727,395.636,232.727z"/></g></svg></a>';
    }
});

用法

<source-link href="//google.com"></source-link>

Source :D

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。