How to add class to SVGRect created dynamically us

2020-04-15 11:19发布

问题:

I am trying to add a class to an SVGRect element that I created with JavaScript. I can see the class is added to the element (in Developer Tools) but the element is not styled accordingly. If I add a class to a Rect that was created inline the element is styled.

  • The SVG element has Rect0
  • I use "drawSomething" to add Rect1 to the SVG element
  • I use "updateSomething" to add classes "task0" and "task1" to Rect0 and Rect1.

Rect0 is styled, Rect1 is not.

Do I need to "apply" after updating? The width of both Rect elements is updated after executing "updateSomething" which leads me to think that I don't need an "apply".

The "rect" rule is also not applied to the Rect created dynamically.

Also, I should also mention that my SVG element is part of an Angular component. Wondering if that changes anything.

function drawSomething()
{
  let SVG_NS = "http://www.w3.org/2000/svg";
  let svg = document.getElementById('editorSvg');
  let rect = document.createElementNS(SVG_NS, "rect");
  rect.setAttribute("id", "svg-rect-1");
  rect.setAttribute("x", "100");
  rect.setAttribute("y", "80");
  rect.setAttribute("width", "50");
  rect.setAttribute("height", "50");
  svg.appendChild(rect);
}

function updateSomething()
{
  let rect0 = document.getElementById("svg-rect-0");
  rect0.style.width = "100";
  rect0.setAttribute("class", "task0");
 let rect1 = document.getElementById("svg-rect-1");
  rect1.style.width = "100";
  rect1.setAttribute("class", "task1");
}

drawSomething();
updateSomething();
rect {
    stroke: red;
    stroke-width: 2;
}

.task0 {
    fill: green;
    stroke-width: 5;
}

.task1 {
    fill: orange;
    stroke-width: 5;
}
 <div id="svgContainer" class="svgContainer">
    <svg id='editorSvg' class='editorSvg' xmlns="http://www.w3.org/2000/svg">
      <rect id="svg-rect-0" x="10" y="10" width="50" height="50" class="task" ></rect>
    </svg>
  </div>

回答1:

The code seems to work fine. In Chrome at least.

Be aware that setting width via a CSS property (style.width="100") is an SVG 2 thing that doesn't work in all browsers yet. Currently, for instance, it'll work in Chrome, but not Firefox.

Another problem is that, in CSS, properties are supposed to have units. So technically you should be writing rect0.style.width = "100px"; (note the px)

Anyway, to work better cross-browser, I recommend using:

rect0.setAttribute("width", "100");

The way you are setting the class looks okay though. I don't see any reason why anything other than the width should be broken.

Update

Ah, I see what you are trying to do now.

You can do it this way:

import { Component, Renderer2 } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular';

  constructor(private renderer: Renderer2) {
  }

  public addRect1 = () => {
      let svg = document.getElementById('editorSvg');
      const rect = this.renderer.createElement("rect", 'svg');
      this.renderer.setAttribute(rect, "id", "svg-rect-1");
      this.renderer.setAttribute(rect, "x", "100");
      this.renderer.setAttribute(rect, "y", "80");
      this.renderer.setAttribute(rect, "width", "50");
      this.renderer.setAttribute(rect, "height", "50");
      this.renderer.appendChild(svg, rect)
  }

  styleRect0 = () => {
      let rect = document.getElementById("svg-rect-0"); // as unknown as SVGRectElement;
      rect.style.width = "100";
      rect.classList.add("task0");
  }

  styleRect1 = () => {
      let rect = document.getElementById("svg-rect-1"); // as unknown as SVGRectElement;
      rect.style.width = "100";
      rect.classList.add("task1");
  }
}

https://stackblitz.com/edit/angular-ytqmvv



标签: html angular svg