svgdotjs / svg.js

The lightweight library for manipulating and animating SVG
https://svgjs.dev
Other
11.14k stars 1.08k forks source link

Setting fill does not work on existing elements with `fill: none` #1099

Closed bluenote10 closed 4 years ago

bluenote10 commented 4 years ago

Bug report

Fiddle

Issue arises in a non-fiddle use case, reproducible in a self-contained .svg instead.

Explanation

I'm trying to animate SVGs generated by Inkscape by embedding svg.js code into the .svg file. A minimal example would be:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   xmlns:xlink="http://www.w3.org/1999/xlink"
   width="210mm"
   height="297mm"
   viewBox="0 0 210 297"
   version="1.1"
   id="svg8"
   inkscape:version="0.92.3 (2405546, 2018-03-11)"
   sodipodi:docname="minimal_orig.svg">
  <defs
     id="defs2" />
  <sodipodi:namedview
     id="base"
     pagecolor="#ffffff"
     bordercolor="#666666"
     borderopacity="1.0"
     inkscape:pageopacity="0.0"
     inkscape:pageshadow="2"
     inkscape:zoom="0.35"
     inkscape:cx="-312.85714"
     inkscape:cy="560"
     inkscape:document-units="mm"
     inkscape:current-layer="layer1"
     showgrid="false"
     inkscape:window-width="1869"
     inkscape:window-height="1025"
     inkscape:window-x="51"
     inkscape:window-y="27"
     inkscape:window-maximized="1" />
  <metadata
     id="metadata5">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
        <dc:title></dc:title>
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <g
     inkscape:label="Layer 1"
     inkscape:groupmode="layer"
     id="layer1">
    <rect
       style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#2d2d2d;stroke-width:0.31407669;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
       id="rect10"
       width="100"
       height="100"
       x="0"
       y="0" />
  </g>

  <script type="text/javascript" xlink:href="https://cdn.jsdelivr.net/npm/@svgdotjs/svg.js@3.0/dist/svg.min.js"></script>
  <script type="text/javascript">
    <![CDATA[
      var rect = SVG('#rect10');
      console.log(rect);
      rect.animate().attr({ x: 100, y: 100 }).fill({ color: '#f06', opacity: 0.6 })
    ]]>
  </script>

</svg>

This setup works in general, resulting in an animated svg. What doesn't work is animating the fill though. This seems to be caused by the fill: none style, which Inkscape generates automatically on objects without fill. Removing the style generated by Inkscape manually makes the example fully functional. But shouldn't the fill call overwrite the style set initially? Can this work in general without manual adaptations to the styles from Inkscape?

Fuzzyma commented 4 years ago

Style always overwrites attributes. This is also true in html. However, you can just call style('fill',null) to remove the style from the element or remove the style attribute alltogether with attr('style', 'null')

bluenote10 commented 4 years ago

Thanks for the clarification -- I guess it makes sense not to check against style every time when setting an attribute and the work-around should be fine.

ja5perhawk commented 2 years ago

This is a really important clarification - I'm finding that any property of the an element set in the "style" attribute of an SVG element tag will take precedence over attributes attempting to be set by the .attr() function. I must remove those specifications from the SVG tag either by javascript, or just removing them by hand, then set them with .attr()