0

I have an icon that I want to use many times on my page. I want the icon to be filled dynamically (how much of it will be filled) from server data.

what I got so far is this:

<svg version="1.1" id="myWarningId" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
 viewBox="0 0 27.8 24" style="enable-background:new 0 0 27.8 24;" xml:space="preserve">
<defs>
    <symbol viewBox="0 0 27.8 24" y="0px" x="0px" id="warning" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg">
        <style type="text/css">
            #myWarningId .st1{fill:#FFFFFF;}
            #myWarningId polygon{fill: inherit;}
        </style>
        <linearGradient id="half" x2="0%" y2="100%">
            <stop offset="0%" stop-color="red" />
            <stop offset="50%" stop-color="red" />
            <stop offset="50%" stop-color="blue" />
            <stop offset="100%" stop-color="blue" />
        </linearGradient>
        <g>
            <polygon points="13.9,0 0,24 27.8,24"></polygon>
            <g>
                <path d="m13.9,16.1l0,0c-1.1,0 -2.1,-0.9 -2.1,-2.1l0,-4.9c0,-1.1 0.9,-2.1 2.1,-2.1l0,0c1.1,0 2.1,0.9 2.1,2.1l0,4.9c-0.1,1.2 -1,2.1 -2.1,2.1z" class="st1"></path>
                <circle r="1.7" cy="19.5" cx="13.9" class="st1"></circle>
            </g>
        </g>
    </symbol>
</defs>
<g class="layer">
    <!-- this use will be generated multiple times -->
    <use x="0" y="0" fill="url(#half)"  transform="matrix(0.20000000298023224,0,0,0.20000000298023224,0,0) " xlink:href="#warning" id="svg_2"></use>
</g>

Now, if I want to change where the line is I need to do it in the <def> tag. but this is changing all my <use> elements.

how can I change the % of the fill for each <use> dynamically and individually?

I don't think that making 100 <linearGradient> definitions for each precent and changing the fillUrl would be a good practice...

Dzak
  • 412
  • 4
  • 17
  • Don't use use elements at all, they exist to show the same thing multiple times. Simply draw whatever you want in each different way. – Robert Longson Oct 15 '18 at 06:35
  • let's say I have to... the svg is not generated by me at all. All I can do is ask that it will be generated by some kind of format – Dzak Oct 15 '18 at 06:39
  • @RobertLongson I think you meant symbols, not elements. – Waruyama Oct 15 '18 at 07:03
  • @Waruyama, I meant what I said, the word use is repeated. I.e. Don't use elements.... – Robert Longson Oct 15 '18 at 08:08
  • @Dzak use one element per thing being displayed, which is pretty inefficient but would work I suppose. – Robert Longson Oct 15 '18 at 08:09
  • @RobertLongson for my understanding (a couple of hours of reading), if I want to display icon many times, it is more efficient to define it once and use it as much as you want with the element. I would like to know why you think this is inefficient so I could point it out to my co-workers. – Dzak Oct 15 '18 at 08:18
  • That's true but if you use it many times, you'll get copies of that thing you're using many times and you don't want that because each of your instances is different. is only useful if you're using the **same** thing many times. – Robert Longson Oct 15 '18 at 09:20

1 Answers1

1

You should not put the gradient into the symbol if you want to change the percentage of the stop. If you are fine with steps (10%, 20%, 30%), you can implement one gradient for each step. It looks like this:

<svg version="1.1" id="myWarningId" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
 viewBox="0 0 27.8 24" style="enable-background:new 0 0 27.8 24;" xml:space="preserve">
<defs>
    <linearGradient id="_10" x2="0%" y2="100%">
        <stop offset="10%" stop-color="red" />
        <stop offset="10%" stop-color="blue" />
    </linearGradient>
    <linearGradient id="_20" x2="0%" y2="100%">
        <stop offset="20%" stop-color="red" />
        <stop offset="20%" stop-color="blue" />
    </linearGradient>
    <linearGradient id="_30" x2="0%" y2="100%">
        <stop offset="30%" stop-color="red" />
        <stop offset="30%" stop-color="blue" />
    </linearGradient>
    <symbol viewBox="0 0 27.8 24" y="0px" x="0px" id="warning" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg">
        <style type="text/css">
            #myWarningId .st1{fill:#FFFFFF;}
            #myWarningId polygon{fill: inherit;}
        </style>
        <g>
            <polygon points="13.9,0 0,24 27.8,24"></polygon>
            <g>
                <path d="m13.9,16.1l0,0c-1.1,0 -2.1,-0.9 -2.1,-2.1l0,-4.9c0,-1.1 0.9,-2.1 2.1,-2.1l0,0c1.1,0 2.1,0.9 2.1,2.1l0,4.9c-0.1,1.2 -1,2.1 -2.1,2.1z" class="st1"></path>
                <circle r="1.7" cy="19.5" cx="13.9" class="st1"></circle>
            </g>
        </g>
    </symbol>
</defs>

<g class="layer">
    <!-- this use will be generated multiple times -->
    <use x="0" y="0" fill="url(#_10)" transform="matrix(0.20000000298023224,0,0,0.20000000298023224,0,0) " xlink:href="#warning" id="svg_1"></use>
    <use x="0" y="32" fill="url(#_20)" transform="matrix(0.20000000298023224,0,0,0.20000000298023224,0,0) " xlink:href="#warning" id="svg_2"></use>
    <use x="0" y="64" fill="url(#_30)" transform="matrix(0.20000000298023224,0,0,0.20000000298023224,0,0) " xlink:href="#warning" id="svg_3"></use>
</g>
</svg>
Waruyama
  • 3,267
  • 1
  • 32
  • 42
  • I was afraid this would be the only answer for me... but what is the difference if I put it inside the symbol tag or in the def? – Dzak Oct 15 '18 at 07:48
  • If you you want the gradient to be used by different symbols, it just makes sense to put it outside the symbol. – Waruyama Oct 15 '18 at 08:30
  • didn't check yet. but thanks for pointing it out. and yes, in my case this style should be relevant only for this symbol – Dzak Oct 15 '18 at 08:39
  • https://stackoverflow.com/questions/15123953/svg-fill-url-behaving-strangely-in-firefox may help for the firefox problem – Dzak Oct 15 '18 at 08:39
  • can I chage the fill attribute on the `` element to a css class? – Dzak Oct 15 '18 at 09:17