简体   繁体   中英

Setting SVG Attributes with javascript in chrome

Maybe this is a bug with Chrome (88.0.4324.150) svg rendering, it appears reprodutible only in this browser. But maybe I am doing something wrong?

When I set the fill-mode attribute dynamically and repeatedly with javascript by using setAttribute, it is not always visible applied although correctly shown in the inspector. If the window getsa redraw eg. through resizing, it suddenly gets applied.

Why does the attribute change not show up? Am I missing some (undocumented) update call or is this just a browser bug?

You can see the issue in the snippet, repeatedly click on the fill-mode links.

 const doc = document.createElementNS("http://www.w3.org/2000/svg", 'svg'); doc.setAttribute("xmlns", "http://www.w3.org/2000/svg"); doc.setAttribute("viewBox", "0 0 200 200"); doc.setAttribute("width", 200); doc.setAttribute("height", 200); const polygon = document.createElementNS("http://www.w3.org/2000/svg", 'polygon'); polygon.setAttribute('stroke', 'black'); polygon.setAttribute('stroke-width', 3); polygon.setAttribute('fill', 'blue'); polygon.setAttribute('fill-rule', 'evenodd'); polygon.setAttribute('points', '150,100,59,129,115,52,115,147,59,70'); doc.appendChild(polygon); document.getElementById('dest').appendChild(doc); // setting up event handlers [...document.querySelectorAll('[data-color]')].forEach((el) => el.addEventListener( "click", (e) => polygon.setAttribute('fill', e.target.getAttribute('data-color')) ) ); [...document.querySelectorAll('[data-fill-rule]')].forEach((el) => el.addEventListener( "click", (e) => polygon.setAttribute('fill-rule', e.target.getAttribute('data-fill-rule')) ) );
 <a href="#" data-color="red">set red</a> - <a href="#" data-color="green">set green</a> - <a href="#" data-color="blue">set blue</a><br> Problematic, swap multiple: <a href="#" data-fill-rule="evenodd">set evenodd</a> <a href="#" data-fill-rule="nonzero">set nonzero</a> <div id="dest"></div>

Definitely a bug.
getComputedstyle(polygon).fill-rule shows the correct fill-rule state, but it is not applied.

Interesting.. the MDN page has no Browser compatibility info:
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-rule

A work-around is to move the polygon inside the SVG with: this.closest('svg').append(this);

If you have more complex SVG you can use insertBefore :
https://developer.mozilla.org/en-US/docs/Web/API/Node/insertBefore
to move the element 'inplace' before itself

Moving redraws the polygon with the correct fill-rule state
(but you may get unwanted side-effects with animations)

  • SO snippet below has incorrect behavior on a click (in Chromium browsers)

  • Hold down the Ctrl key on a click to use the work-around
    (2 clicks ofcourse when the previous click did not apply the state)

 <b>Click Red color to toggle fill-rule: evenodd/nonzero</b><br> <svg xmlns="http://www.w3.org/2000/svg" viewBox="50 50 100 100" width="200"> <polygon fill-rule="evenodd" fill="red" points="150,100,59,129,115,52,115,147,59,70" onclick="let fr = this.getAttribute('fill-rule')=='evenodd'? 'nonzero': 'evenodd'; this.setAttribute('fill-rule', fr ); if (event.ctrlKey) this.closest('svg').append(this)"></polygon> </svg>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM