Warm tip: This article is reproduced from serverfault.com, please click

Why does the colored SVG I recolor using a mask turns the color lighter than the chosen color?

发布于 2020-12-04 15:11:20

I have a VueJS project in which I use SVGs with a hardcoded color, I try to give these SVGs another color by looping over them using mask and rect tags. This works, but I see that the higher the icon index gets, the lighter the color of the icon becomes. What am i doing wrong?

Here is the codepen example;

https://codepen.io/Kesselfest/pen/xxEZyBb

And the HTML template;

<template>
    <div id="app">
        <div class="flex-container">
            <div v-for="icon in icons" :key="icon.name">
                <div class="iconTile"> <svg viewBox="0 0 36 36">
                        <mask :id="`${icon.name}-mask`">
                            <image :href="icon.location" x="0" y="0" width="100%" height="100%" />
                        </mask>
                        <rect x="0" y="0" width="100%" height="100%" :fill="icon.color"
                            :mask="`url(#${icon.name}-mask)`" />
                    </svg> </div>
            </div>
        </div>
    </div>
</template>

Questioner
Kesselfest
Viewed
0
ccprog 2020-12-05 00:45:20

As said in the comments, a mask is not the preferable way to change the color of an icon. A filter can do a much better job. This is how I would do it. Excuse me if I abandon the Vue syntax in fvor of showing the result, but I am sure you can port this back easily.

The filter first floods the filter region with the intended color, then clips its aparent area back to the outline of the icon with the Porter-Duff atop operator.

.flex-container {
  justify-content: space-around;
  display: flex;
  padding: 20px;
}

.iconTile {
  margin: 0;
  padding: 10px;
  width: 100px;
  height: 100px;
}
<div class="flex-container">
  <div class="iconTile">
    <svg viewBox="0 0 36 36">
      <filter
           id="checkmark-filter" >
        <feFlood
          flood-color="purple"
          result="color"
        />
        <feComposite
         operator="atop"
         in2="SourceGraphic"
         in="color"
        />
      </filter>
      <image
         href="https://upload.wikimedia.org/wikipedia/commons/thumb/1/13/Icons8_flat_checkmark.svg/768px-Icons8_flat_checkmark.svg.png"
         x="0"
         y="0"
         width="100%"
         height="100%"
         filter="url(#checkmark-filter)"
      />
    </svg>
  </div>
  <div class="iconTile">
    <svg viewBox="0 0 36 36">
      <filter
             id="pencil-filter" >
          <feFlood
            flood-color="green"
            result="color"
          />
          <feComposite
           operator="atop"
           in2="SourceGraphic"
           in="color"
          />
        </filter>
        <image
           href="https://upload.wikimedia.org/wikipedia/commons/5/57/Red_pencil.svg"
           x="0"
           y="0"
           width="100%"
           height="100%"
           filter="url(#pencil-filter)"
        />
      </svg>
  </div>
</div>