9

I would like to change the color of pattern upon usage.

For example, I would like to have a green pattern in the red stroked circle.

<svg width="300" height="300" viewBox="0 0 300 300"
    xmlns="http://www.w3.org/2000/svg">
  <defs>
    <pattern id="checked" width="2" height="2" stroke="black" stroke-linecap="square" stroke-width="1" patternTransform="rotate(45) scale(2)"
        patternUnits="userSpaceOnUse">
      <line x1="0" y1="0" x2="0" y2="2"></line>
      <line x1="0" y1="0" x2="2" y2="0"></line>
    </pattern>
  </defs>
  <circle cx="60" cy="60" r="50" stroke="red" fill="url(#checked)"/>
  <circle cx="120" cy="60" r="50" stroke="blue" fill="url(#checked)"/>
</svg>

http://codepen.io/anon/pen/RVNmRY

Is it possible to do so without having to create a new pattern for every color?

I have read in a comment that this might be possible using filters (https://stackoverflow.com/a/21427316/1981832). But I don't know how.

Community
  • 1
  • 1
Daniel
  • 3,383
  • 4
  • 30
  • 61
  • What's wrong with a pattern per colour? – Robert Longson Apr 15 '17 at 08:55
  • @RobertLongson Thanks. On my page a user should be able choose colors and patterns to draw. Having a pattern per color would mean that I have to attach a new pattern to the page each time the user switches colors. That seems quite cumbersome to me. But maybe I am overlooking something here. – Daniel Apr 15 '17 at 09:03
  • put the colour name in the pattern id (or in a data- attribute) and create it if it doesn't exist. You can set colours in CSS and update the CSS but that would affect all existing shapes with that pattern. – Robert Longson Apr 15 '17 at 09:07
  • @RobertLongson: Can't work with CSS since I need to support standalone SVG without it. If I understood the idea with the pattern-id correctly then I would have to create and attach a new pattern every time the user chooses to draw the pattern with a new color. Yes, that would work but still seems cumbersome and will add a lot of code to the SVG that differs only slightly, i.e. its stroke color. – Daniel Apr 15 '17 at 09:19
  • Not sure what you mean but standalone SVG supports CSS as long as you link to the CSS from the standalone file itself. – Robert Longson Apr 15 '17 at 09:25
  • @RobertLongson Well, I meant that I need to support SVG applications that do not support CSS. (Also updating CSS on the fly isn't that nice either.) – Daniel Apr 15 '17 at 09:46
  • One way to reduce the code a bit is to use ``: http://codepen.io/anon/pen/ybydvK. Unfortunately, I cannot use `` either. But it might help others. – Daniel Apr 15 '17 at 09:57

2 Answers2

7

It works if you fill the circles with the desired color and then apply the pattern as a mask. Here is an example for green and magenta:

<svg width="300" height="300" viewBox="0 0 300 300"
    xmlns="http://www.w3.org/2000/svg">
  <defs>  
    <pattern id="checked" width="2" height="2" stroke="white" stroke-linecap="square" stroke-width="1" patternTransform="rotate(45) scale(2)"
        patternUnits="userSpaceOnUse">
      <line x1="0" y1="0" x2="0" y2="2"></line>
      <line x1="0" y1="0" x2="2" y2="0"></line>
    </pattern>
    <mask id="checked-mask" x="0" y="0" width="1" height="1" >
      <rect x="0" y="0" width="1000" height="1000" fill="url(#checked)" />
    </mask>
  </defs>  
  <circle cx="60" cy="60" r="50" stroke="red" mask="url(#checked-mask)" fill="green" />
  <circle cx="120" cy="60" r="50" stroke="blue" mask="url(#checked-mask)" fill="magenta" />
</svg>
Waruyama
  • 3,267
  • 1
  • 32
  • 42
5

Here's how you recolor a shape with a filter, using a "blue-screen" technique. The filter leaves red components alone (the first 1 in the matrix), converts blue to green (the next "1") and leaves opacity unchanged (the final "1"). This specific filter obviously only works on your example, but you can write a more general filter to use a specific source color as the color that's going to be converted to something else.

<svg width="300" height="300" viewBox="0 0 300 300"
    xmlns="http://www.w3.org/2000/svg">
  <defs>
  <filter id="blue-to-green">
     <feColorMatrix type="matrix" values="1 0 0 0 0
                                          0 0 1 0 0 
                                          0 0 0 0 0 
                                          0 0 0 1 0"/>
  </filter>
  
    <pattern id="checked" width="2" height="2" stroke="blue" stroke-linecap="square" stroke-width="1" patternTransform="rotate(45) scale(2)"
        patternUnits="userSpaceOnUse">
      <line x1="0" y1="0" x2="0" y2="2"></line>
      <line x1="0" y1="0" x2="2" y2="0"></line>
    </pattern>
  </defs>
  
  <circle cx="60" cy="60" r="50" stroke="red" fill="url(#checked)" filter="url(#blue-to-green)"/>
  <circle cx="120" cy="60" r="50" stroke="blue" fill="url(#checked)"/>
</svg>
Michael Mullany
  • 30,283
  • 6
  • 81
  • 105
  • 1
    Thanks. Yes, as it stands one will have to add a filter for each color. That is not much of an improvement over having to add a pattern for each color. – Daniel Apr 17 '17 at 07:24
  • 1
    yes, would be great if SVG had parameterized filters, but alas no. – Michael Mullany Apr 17 '17 at 15:35