Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

In my application, it is more convenient for me to use an image to mask SVG shapes rather than the other way round. (The desired multi-color overlays effects can be achieved either way.) The problem is, when I use a normal (grayscale) image as the mask, the result looks like a negative film. Is there an SVG attribute or clever JS/D3 trick that I can use to tell the browser to invert its masking protocol or am I stuck with converting the images myself (which may end up being less convenient than doing it the other way)?

Update Minimal example:

<!DOCTYPE html>
<title>Image mask</title>

<script type="text/javascript"
  src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js">
</script>
<body>
<div>
<button>toggle</button>
</div>
</body>
<script>
var width = 194,
	height = 240;
	maskWidth = 30;
var svg = d3.select('body').append('svg')
	.attr('height', 500);

var myMask = svg.insert('mask', ':first-child')
	.attr('id', 'image_mask');

var marilyn = myMask.append('image')
	.attr('width', width)
	.attr('height', height)
	.attr('xlink:href', "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8d/Marilyn_Monroe_photo_pose_Seven_Year_Itch.jpg/194px-Marilyn_Monroe_photo_pose_Seven_Year_Itch.jpg");

var positive = svg.append('rect')
	.attr('width',maskWidth)
	.attr('height', height)
	.attr('fill', 'red')
	.attr('mask', 'url(#image_mask)');

var negative = svg.append('rect')
	.attr('x', maskWidth)
	.attr('width', width - maskWidth)
	.attr('height', height)
	.attr('fill', 'green')
	.attr('mask', 'url(#image_mask)');
	
var toggle = false;
d3.select('button').on('click', function() {
	toggle = !toggle;
	positive.transition()
		.attr('height', toggle ? height/2 : height);
});

</script>
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
190 views
Welcome To Ask or Share your Answers For Others

1 Answer

You'll need to use a <filter> to invert the image in your mask.

<svg height="500" xmlns:xlink="http://www.w3.org/1999/xlink" >
  <defs>
    <filter id="invert">
      <feComponentTransfer>
        <feFuncR type="table" tableValues="1 0"/>
        <feFuncG type="table" tableValues="1 0"/>
        <feFuncB type="table" tableValues="1 0"/>
      </feComponentTransfer>
    </filter> 
    <mask id="image_mask">
      <image width="194" height="240" xlink:href="https://upload.wikimedia.org/wikipedia/commons/thumb/8/8d/Marilyn_Monroe_photo_pose_Seven_Year_Itch.jpg/194px-Marilyn_Monroe_photo_pose_Seven_Year_Itch.jpg"
             filter="url(#invert)"/>
    </mask>
  </defs>
  
  <rect width="30" height="120" fill="red" mask="url(#image_mask)"/>
  <rect x="30" width="164" height="240" fill="green" mask="url(#image_mask)"/>
</svg>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...