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 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…