HTML SVG는 <use>와 함께 <g> 그룹을 재사용하고 각 인스턴스에 대해 개별적으로 내부 요소의 속성을 변경합니다.

Aug 21 2020

따라서 그룹화 된 svg 모양을 재사용하고 각 인스턴스에 대해 그룹 내부 요소 중 하나의 속성 하나를 개별적으로 변경하고 싶습니다. 다음 간단한 예제는 내부에 사각형이있는 두 번째 원을 만듭니다. 이제 자바 스크립트를 사용하여 각 도형에 대해 "my-rect"사각형의 "너비"속성을 개별적으로 변경하고 싶습니다. 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>

답변

4 ccprog Aug 20 2020 at 23:43

약간의 속임수로 가능합니다. 그림자 요소 내에서 일부 속성 값을 얻으려면 CSS 상속을 활용해야합니다. 이 경우 사각형의 크기를 조정하고 위치를 지정하는 데 사용되는 사용자 지정 변수가됩니다.

이를 위해 마크 업을 약간 다시 작성해야합니다. 먼저, <defs>요소 안에 그룹을 작성하여 재사용을위한 템플릿으로 만들지 만 자체적으로 렌더링하지는 않습니다. 둘째, 직사각형은 중첩 된 <svg overflow="visible">요소 내부에 배치됩니다 . 이 요소에 x / y 좌표를 부여하고 요소에 대해 0으로두면 <rect>변형 작업 후 직사각형의 왼쪽이 끝나는 위치를 쉽게 추적 할 수 있습니다.

이제 rect의 너비 변경은 위치에 대한 scaleX()변환과 a 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>

5 Danny'365CSI'Engelman Aug 21 2020 at 03:37

Sean은 다음과 같이 말했습니다.

Web Components Custom Elements가 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 용 Custom Elements는 많은 oldskool SVG 해킹에 대한 최신 솔루션입니다.

최신 정보

OP가 원이있는 SVG 하나를 원하면 shadowDOM을 사용할 수 있으며 lightDOM 내부의 요소가 표시되지 않는다는 사실을 사용할 수 있습니다. 우리는 심지어 사용할 수있는 정의되지 않은 <rect> SVG 문자열에 쉽게 분사합니다 (HTML 네임 스페이스) 요소 우리가 할 수있는 정도.

<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 답변 : 사용자 지정 요소 및 SVG

2 Sean Aug 20 2020 at 22:28

이것은 불가능합니다. 이 use요소는을 생성합니다 closed shadow root. 이는 해당 콘텐츠가 JS에 액세스 할 수 없음을 의미합니다. 재사용 된 요소의 인스턴스 속성을 개별적으로 설정할 수 있지만 (원래 요소에 설정되지 않은 경우) 재사용 된 요소의 하위 요소에 영향을 미칠 수 없습니다.

다른 방법은 직사각형 및 원 요소를 직접 재사용하여 새 그룹에 배치하는 것입니다.

AmirFo Sep 27 2020 at 17:27

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.273,23.273h129.997L192.999,286.09    c-9.089,9.089-9.089,23.823,0,32.912c4.543,4.544,10.499,6.816,16.455,6.816c5.956,0,11.913-2.271,16.457-6.817L465.455,79.458    v129.997c0,12.853,10.42,23.273,23.273,23.273c12.853,0,23.273-10.42,23.273-23.273V23.273C512,10.42,501.58,0,488.727,0z"/></g><g><path d="M395.636,232.727c-12.853,0-23.273,10.42-23.273,23.273v209.455H46.545V139.636H256c12.853,0,23.273-10.42,23.273-23.273    S268.853,93.091,256,93.091H23.273C10.42,93.091,0,103.511,0,116.364v372.364C0,501.58,10.42,512,23.273,512h372.364    c12.853,0,23.273-10.42,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>

출처 : D