forked from enoex's block: Fog of War SVG Filter Mask Example
forked from erikhazzard's block: Fog of War SVG Filter Mask Example
forked from anonymous's block: Fog of War SVG Filter Mask Example
license: mit |
forked from enoex's block: Fog of War SVG Filter Mask Example
forked from erikhazzard's block: Fog of War SVG Filter Mask Example
forked from anonymous's block: Fog of War SVG Filter Mask Example
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset='utf-8'> | |
<meta http-equiv='X-UA-Compatible' content='IE=edge'> | |
<style> | |
html, body { | |
background: #ffffff; | |
font-family: Helvetica, Arial, Tahoma, sans-serif; | |
margin: 0; | |
padding: 0; | |
} | |
path { | |
fill: none; | |
stroke: #343434; | |
} | |
.result { | |
fill: none; | |
stroke: #343434; | |
stroke-width: 4px; | |
} | |
h1,h2,h3 { | |
padding-left: 140px; | |
padding-top: 0px; | |
} | |
</style> | |
</head> | |
<body> | |
<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink= 'http://www.w3.org/1999/xlink' height=1500 width=1050> | |
<defs> | |
<filter id="filter-map" x="-0.15000001" y="-0.15000001" width="1.3" height="1.3" color-interpolation-filters="sRGB" > | |
<feGaussianBlur stdDeviation="8" in="SourceGraphic" result="result1" id="feGaussianBlur4202" /> | |
<feTurbulence type="fractalNoise" baseFrequency="0.1" numOctaves="3" result="result0" id="feTurbulence4204" /> | |
<feDisplacementMap in2="result0" scale="20" xChannelSelector="R" yChannelSelector="G" in="result1" result="result2" id="feDisplacementMap4206" /> | |
<feGaussianBlur stdDeviation="1" in="SourceGraphic" result="result4" id="feGaussianBlur4208" /> | |
<feComposite in2="result2" operator="arithmetic" k1="0.2" k2="-0.15" k3="0.8" k4="0" in="result4" result="result5" id="feComposite4210" /> | |
</filter> | |
</defs> | |
</svg> | |
<h3>Fog of War - Click to remove fog</h3> | |
<em>Note: this is not designed to be performant; this is just an example of how filters and masks can be used</em> | |
<script src='http://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js'></script> | |
<script> | |
(function setupMap(){ | |
// 0. setup groups | |
// ---------------------------------- | |
var svg = d3.select('svg'); | |
var wrapper = svg.append('g').attr({ 'class': 'map-wrapper'}); | |
var background = wrapper.append('g').attr({ 'class': 'background'}); | |
var characters = wrapper.append('g').attr({ 'class': 'characters'}); | |
// 1. Setup the mask | |
// ---------------------------------- | |
var maskGroup = svg.select('defs').append('mask') | |
.attr({ id: 'map-mask' }); | |
// 2. Add map images | |
// ---------------------------------- | |
// fog version - grayscaled and dark | |
var fogMap = background.append("image") | |
.attr({ | |
// TODO: use difference background image | |
'xlink:href': 'http://vasir-assets.s3.amazonaws.com/fog-of-war/map-dark.jpg', | |
'preserveAspectRatio': 'none', | |
'class': 'fog', x: 0, y: 0, | |
height: '100%', width: '100%' | |
}); | |
// full version | |
var visibleMap = background.append("image") | |
.attr({ | |
// TODO: use difference background image | |
'xlink:href': 'http://vasir-assets.s3.amazonaws.com/fog-of-war/map.jpg', | |
'preserveAspectRatio': 'none', | |
'class': 'visibleArea', x: 0, y: 0, | |
height: '100%', width: '100%' | |
}) | |
.style({ | |
// fill with full version of map | |
fill: '#336699', mask: 'url(#map-mask)' | |
}); | |
// 3. Add a starting circle to break the fog | |
// ---------------------------------- | |
// create a masked path to show visible nodes | |
var vertices = []; | |
function updateFog(){ | |
var masks = maskGroup.selectAll('.breakFog') | |
.data(vertices); | |
var newMasks = masks.enter() | |
.append('circle') | |
.style({ | |
fill: '#000000', | |
opacity: 1 | |
}); | |
// update existing masks | |
masks | |
.attr({ | |
'class': 'breakFog', | |
cx: function(d){ | |
console.log(d); | |
return d.x; }, | |
cy: function(d){ return d.y; }, | |
filter: 'url(#filter-map)', | |
r: function(d){ | |
var r = 50; | |
return r; | |
} | |
}).style({ fill: '#ffffff', opacity: 1 }); | |
masks.exit().remove(); | |
// add sprites | |
// ------------------------------ | |
/* | |
var sprites = characters.selectAll('.character') | |
.data(vertices); | |
var races = ['darkelf.gif', 'human.gif', 'elf.gif', 'mimirian.gif']; | |
sprites.enter() | |
.append("image") | |
.attr({ | |
'class': 'character', | |
'xlink:href': 'http://vasir-assets.s3.amazonaws.com/fog-of-war/' + | |
races[vertices.length % races.length], | |
'preserveAspectRatio': 'none', | |
x: function(d){ return d.x - 53/2; }, | |
y: function(d){ return d.y - 53/2; }, | |
height: 53, width: 53 | |
}); | |
sprites.exit().remove(); | |
*/ | |
}; | |
// Call it immediately | |
updateFog(); | |
// then, call whenever a point is added | |
wrapper.on('click', function(){ | |
vertices.push({ | |
x: d3.event.clientX, | |
y: d3.event.clientY | |
}); | |
updateFog(); | |
}); | |
wrapper.append('rect').attr({ x:0, y: 0, width: 20, height: 20 }).style({ }).on('click', function(){ | |
setTimeout(function(){ | |
vertices.pop(); vertices.pop(); | |
updateFog() | |
}, 200); | |
}) | |
let clickedI = 0; | |
let coords = [ | |
[100, 200], | |
[400, 20], | |
[100, 400], | |
[700, 20], | |
[300, 10], | |
[10, 400], | |
[50, 50] | |
] | |
setTimeout(function () { | |
coords.forEach(function (d, i) { | |
setTimeout(function () { | |
console.log('clicked', i); | |
vertices.push({ | |
x: coords[i][0], | |
y: coords[i][1] | |
}); | |
updateFog() | |
}, i * 400); | |
clickedI++; | |
}) | |
}, 500) | |
})(); | |
</script> | |
</body> | |
</html> |