This block is a continuation of a previous block, and a recreation:
xxxxxxxxxx
<meta charset="utf-8">
<style>
#under-construction {
display: none;
position: absolute;
top: 200px;
left: 300px;
font-size: 40px;
}
.layer {
opacity: 0.9;
}
.particle .seed {
fill: black;
}
.influence-zone {
stroke: none;
}
#layer-0 .influence-zone {
fill: url("#radial-gradient-0");
}
#layer-1 .influence-zone {
fill: url("#radial-gradient-1");
}
#layer-2 .influence-zone {
fill: url("#radial-gradient-2");
}
</style>
<body>
<div id="under-construction">
UNDER CONSTRUCTION
</div>
<svg>
<defs>
<radialGradient id="radial-gradient-0" cx="50%" cy="50%" r="50%">
<stop offset="25%" stop-color="white"></stop>
<stop offset="100%" stop-color="green"></stop>
</radialGradient>
<radialGradient id="radial-gradient-1" cx="50%" cy="50%" r="50%">
<stop offset="25%" stop-color="white"></stop>
<stop offset="100%" stop-color="blue"></stop>
</radialGradient>
<radialGradient id="radial-gradient-2" cx="50%" cy="50%" r="50%">
<stop offset="25%" stop-color="white"></stop>
<stop offset="100%" stop-color="red"></stop>
</radialGradient>
</defs>
</svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="simplex-noise.min.js"></script>
<script src="https://raw.githack.com/kcnarf/d3-distancelimitedvoronoi/master/distance-limited-voronoi.js"></script>
<script>
var width = 960,
height = 500;
var layerCount = 3,
particleCountPerLayer = 25,
particles = new Array(layerCount),
influenceRadius = 20,
proximityTreshold = Math.pow(3*influenceRadius, 2),
baseOpacity= 0.25;
for (var l = 0; l < layerCount; ++l) {
particles[l] = new Array(particleCountPerLayer);
for (var i = 0; i < particleCountPerLayer; ++i) {
particles[l][i] = {
x: Math.random() * width,
y: Math.random() * height
};
}
}
var simplex = new SimplexNoise();
var limitedVoronoi = d3.distanceLimitedVoronoi()
.limit(influenceRadius)
.extent([[-influenceRadius,-influenceRadius],[width+influenceRadius,height+influenceRadius]])
.x( function(d) { return d.x })
.y( function(d) { return d.y });
var svg = d3.select("svg");
svg.attr("width", width)
.attr("height", height);
//begin: add layers
svg.selectAll("g").data(d3.range(layerCount))
.enter()
.append("g")
.classed("layer", true)
.attr("id", function(d) { return "layer-"+d; });
//end: add layers
//begin: add particles on appropriate layer
for (var l = 0; l < layerCount; l++) {
var layer = svg.select("#layer-"+l);
var clipPathName = "clip-"+l+"-";
var drawnParticles = layer.selectAll(".particle").data(particles[0]);
enteringParticles = drawnParticles.enter()
.append("g")
.classed("particle", true);
enteringParticles
.append("clipPath")
.attr("id", function(d,i){ return clipPathName+i; })
.append("path")
.classed("clip", true);
enteringParticles.append("circle")
.classed("influence-zone", true)
.attr("r", influenceRadius)
.attr("clip-path", function(d, i){ return "url(#"+clipPathName+i+")"; });
}
//end: add particles on appropriate layer
d3.timer(function(elapsed) {
//begin: update particles' position using SimplexNoise
for (var l = 0; l < layerCount; l++) {
var layer = svg.select("#layer-"+l);
for (var i = 0; i < particleCountPerLayer; ++i) {
var p = particles[l][i];
p.x += simplex.noise2D(10*l+i, elapsed/10000);
p.y += simplex.noise2D(elapsed/10000, 10*l+i);
if (p.x < -influenceRadius) {
p.x += (width+2*influenceRadius);
} else if (p.x > width+influenceRadius) {
p.x -= (width+2*influenceRadius);
}
if (p.y < -influenceRadius) {
p.y += (height+2*influenceRadius);
} else if (p.y > height+influenceRadius) {
p.y -= (height+2*influenceRadius);
}
}
//end: update particles' position using SimplexNoise
var limitedCells = limitedVoronoi(particles[l]);
var minSquareDists = computeMinSquareDists(particles[l]);
//begin: update drawn particles' clip for blobbing effect
layer.selectAll(".particle .clip").data(limitedCells)
.attr("d", function(d) { return d.path; });
//and: update drawn particles' clip for blobbing effect
//begin: update drawn particles' position and opacity
layer.selectAll(".particle .influence-zone").data(limitedCells)
.attr("cx", function(d) { return d.datum.x; })
.attr("cy", function(d) { return d.datum.y; })
.style("fill-opacity", function(d,i) {
var minSquareDist = minSquareDists[i];
if (minSquareDist>proximityTreshold) {
return baseOpacity;
} else {
return baseOpacity + (1-baseOpacity)*(1-minSquareDist/proximityTreshold);
}
});
//begin: update drawn particles' position and opacity
}
function computeMinSquareDists (particles) {
var minSquareDists = [];
for(var i=0; i<particleCountPerLayer; i++) {
minSquareDists[i] = Infinity;
}
for(var i=0; i<particleCountPerLayer; i++) {
for(var j=i+1; j<particleCountPerLayer; j++) {
var squareDist = Math.pow(particles[i].x-particles[j].x,2)+Math.pow(particles[i].y-particles[j].y,2)
if (squareDist<minSquareDists[i]) {
minSquareDists[i] = squareDist;
}
if (squareDist<minSquareDists[j]) {
minSquareDists[j] = squareDist;
}
}
}
return minSquareDists;
}
});
</script>
</body>
Updated missing url https://raw.githack.com/Kcnarf/d3-distanceLimitedVoronoi/master/distance-limited-voronoi.js to https://raw.githack.com/kcnarf/d3-distancelimitedvoronoi/master/distance-limited-voronoi.js
https://d3js.org/d3.v4.min.js
https://raw.githack.com/Kcnarf/d3-distanceLimitedVoronoi/master/distance-limited-voronoi.js