Reputation: 34489
I've got some SVG that I've put together, but one of the things I'm stuggling with is to move a mask that I've created. It's easiest to describe with an example:
function createFog(imageUrl) {
const mapImage = new Image();
mapImage.onload = function() {
// Grab the dimensions of the map
const width = this.width;
const height = this.height;
d3.selectAll(".full-size").attr({
height,
width
});
d3.select("#map").attr("xlink:href", imageUrl);
};
mapImage.src = imageUrl;
}
createFog("https://oneinchsquare.files.wordpress.com/2015/01/greenest_transparent_grid.jpg");
img, svg, canvas {
position: absolute;
top: 0;
left: 0;
}
html, body {
overflow: hidden;
background: black;
}
#interaction {
fill: none;
pointer-events: all;
}
#light {
opacity: 0.9;
}
#fog {
opacity: 0;
fill: black;
}
.explore-outline {
fill: none;
stroke: #aaa;
}
.torch-outline {
fill: none;
stroke: #ff9800;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.3.13/d3.min.js"></script>
<svg class="full-size">
<g id="view" transform="scale(0.25)">
<defs>
<radialGradient id="radGrad" class="full-size" r="0.31">
<stop offset="0%" stop-color="black" />
<stop offset="50%" stop-color="#aaa" />
<stop offset="60%" stop-color="#bbb" />
<stop offset="70%" stop-color="#ccc" />
<stop offset="80%" stop-color="#ddd" />
<stop offset="90%" stop-color="#eee" />
<stop offset="100%" stop-color="white" />
</radialGradient>
<mask class="full-size" id="explored">
<rect class="full-size" id="unexplored" x="0" y="0" width="500" height="500" fill="white"/>
<g id="explored"></g>
</mask>
<mask id="hole">
<rect id="mask" class="full-size" x="0" y="0" width="500" height="500" fill="url(#radGrad)"></rect>
</mask>
</defs>
<image class="full-size" id="map" x="0" y="0"/>
<rect class="full-size" id="light" x="0" y="0" width="500" height="500" mask="url(#hole)"></rect>
<rect class="full-size" id="fog" x="0" y="0" width="500" height="500" mask="url(#explored)"></rect>
</g>
<rect id="interaction" class="full-size" x="0" y="0"></rect>
</svg>
What I wish to be able to do is to move the "light" effect when someone clicks on the background, moving the lighting to that point. This light effect is actually created by cutting a hole in the middle of a dark layer. I don't need help with the code from that point of view, it's more the things I've tried to do in SVG don't seem to produce the effect I want.
The problem I've got is I don't seem to be able to move the radialGradient
, I assumed I could set the cx
or cy
but they don't seem to do anything.
This leaves me with another option that I've tried - translating the #mask
or #light
elements, however doing so then leaves a portion of the map uncovered. I thought I'd be able to just oversize these layers to compensate - but then unfortunately that scales the hole to larger which I don't want to do.
Is there anyway I can move this "hole" effectively?
Upvotes: 1
Views: 669
Reputation: 101820
I assumed I could set the cx or cy but they don't seem to do anything.
It seems to work fine when the cx
and cy
are changed.
function createFog(imageUrl) {
const mapImage = new Image();
mapImage.onload = function() {
// Grab the dimensions of the map
const width = this.width;
const height = this.height;
d3.selectAll(".full-size").attr({
height,
width
});
d3.select("#map").attr("xlink:href", imageUrl);
};
mapImage.src = imageUrl;
}
createFog("https://oneinchsquare.files.wordpress.com/2015/01/greenest_transparent_grid.jpg");
img, svg, canvas {
position: absolute;
top: 0;
left: 0;
}
html, body {
overflow: hidden;
background: black;
}
#interaction {
fill: none;
pointer-events: all;
}
#light {
opacity: 0.9;
}
#fog {
opacity: 0;
fill: black;
}
.explore-outline {
fill: none;
stroke: #aaa;
}
.torch-outline {
fill: none;
stroke: #ff9800;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.3.13/d3.min.js"></script>
<svg class="full-size">
<g id="view" transform="scale(0.25)">
<defs>
<radialGradient id="radGrad" class="full-size" r="0.31"
cx="0.3" cy="0.7">
<stop offset="0%" stop-color="black" />
<stop offset="50%" stop-color="#aaa" />
<stop offset="60%" stop-color="#bbb" />
<stop offset="70%" stop-color="#ccc" />
<stop offset="80%" stop-color="#ddd" />
<stop offset="90%" stop-color="#eee" />
<stop offset="100%" stop-color="white" />
</radialGradient>
<mask class="full-size" id="explored">
<rect class="full-size" id="unexplored" x="0" y="0" width="500" height="500" fill="white"/>
<g id="explored"></g>
</mask>
<mask id="hole">
<rect id="mask" class="full-size" x="0" y="0" width="500" height="500" fill="url(#radGrad)"></rect>
</mask>
</defs>
<image class="full-size" id="map" x="0" y="0"/>
<rect class="full-size" id="light" x="0" y="0" width="500" height="500" mask="url(#hole)"></rect>
<rect class="full-size" id="fog" x="0" y="0" width="500" height="500" mask="url(#explored)"></rect>
</g>
<rect id="interaction" class="full-size" x="0" y="0"></rect>
</svg>
Upvotes: 1