xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
</style>
</head>
<body>
<div id=buttonContain>
<button id="update">update</button>
</div>
<script>
// Initializaing width and height of svg
var width = 960, height = 500
// setting up the svg
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
var x_pad = 20;
var y_pad = 30;
var x = d3.scaleLinear()
.domain([0, 1])
.range([0, width]);
var y = d3.scaleLinear()
.domain([0, 1])
.range([0, height])
var n_points = 100
var data = d3.range(n_points).map(function(){
return [Math.random(), Math.random()];
});
svg.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('r', 3)
.attr('cx', d => x(d[0]))
.attr('cy', d => y(d[1]))
.attr('fill', 'black')
.attr('opacity', 0.7)
.attr('class', (d, i) => 'index' + i)
.classed("points", true);
console.log(data)
var nodes = data;
var voronoi = d3.voronoi()
.x(d => x(d[0]))
.y(d => y(d[1]))
.extent([[0, 0], [width, height]])
console.log(voronoi.polygons(nodes));
console.log(voronoi(nodes));
// var polygon = svg.append('g')
// .attr('class', 'voronoi_contain')
// //.select('path')
// .selectAll(".voronoi")
// .data(voronoi.polygons(nodes)) //Use vononoi() with your dataset inside
// .enter().append("path")
// .attr("class", "voronoi")
// .style("stroke", "#2074A0") //If you want to look at the cells
// .style("fill-opacity", 0)
// .attr('class', (d, i) => 'index' + i)
// .classed('cell', true)
// .call(redrawPolygon);
var polygon = svg.append("defs")
.selectAll(".clip")
.data(voronoi.polygons(nodes))
//First append a clipPath element
.enter().append("clipPath")
.attr("class", "clip")
//Make sure each clipPath will have a unique id (connected to the circle element)
.attr("id", function(d, i) { return "clip-index" + i; })
//Then append a path element that will define the shape of the clipPath
.append("path")
.attr("class", "clip-path-circle")
.attr("d", function(d) { return "M" + d.join(",") + "Z"; })
.style("stroke", 'grey')
.style("stroke-width", 1);
//Append larger circles
svg.selectAll(".circle-catcher")
.data(nodes)
.enter().append("circle")
.attr("class", function(d,i) { return "circle-catcher " + "index" + i; })
//Apply the clipPath element by referencing the one with the same countryCode
.attr("clip-path", function(d, i) { return "url(#clip-" + "index" + i + ")"; })
//Bottom line for safari, which doesn't accept attr for clip-path
.style("clip-path", function(d, i) { return "url(#clip-" + "index" + i + ")"; })
.attr("cx", function(d) {return x(d[0]);})
.attr("cy", function(d) {return y(d[1]);})
//Make the radius a lot bigger
.attr("r", 50)
.style("fill", "grey")
.style("opacity", 0.5)
.style("pointer-events", "all")
//Notice that we now have the mousover events on these circles
.on("mouseover", activateHover(100))
.on("mouseout", deactivateHover(100));
function redrawPolygon(polygon) {
polygon
.attr("d", function(d) { return d ? "M" + d.join("L") + "Z" : null; })
.style("stroke", "#2074A0") //If you want to look at the cells
.style("stroke-width", 0.5)
.style("fill-opacity", 0)
//.attr("id", d => (d != null) ? d.data.seat : "NA")
}
// svg.selectAll('path.cell').on('mouseover', activateHover(500));
// svg.selectAll('path.cell').on('mouseout', deactivateHover(500));
function activateHover(trans_time){
return function(d, i){
var unique_class = d3.select(this).attr('class').replace("circle-catcher ", "")
d3.select("circle" + "." + unique_class)
.transition(trans_time)
.ease(d3.easeQuad)
.attr('r', 5)
.attr('stroke', 'black')
.attr('stroke-width', 1)
.style('opacity', 1);
}
}
function deactivateHover(trans_time){
return function(d, i){
var unique_class = d3.select(this).attr('class').replace("circle-catcher ", "")
d3.select("circle" + "." + unique_class)
.transition(trans_time)
.ease(d3.easeQuad)
.attr('r', 3)
.attr('stroke', 'black')
.attr('stroke-width', 0)
.style('opacity', 0.7);
}
}
function update(trans_time){
// update the nodes
data = d3.range(n_points).map(function(){
return [Math.random(), Math.random()];
});
nodes = data
console.log(nodes);
d3.selectAll('circle.points')
.data(nodes)
.transition()
.duration(trans_time)
.attr("cx", function(d) {return x(d[0]);})
.attr("cy", function(d) {return y(d[1]);})
var oldVorData = d3.selectAll('defs clipPath.clip').data();
d3.selectAll('defs clipPath.clip')
.data(voronoi.polygons(nodes))
.select("path")
.data(voronoi.polygons(nodes))
//.attr("d", function(d) { return "M" + d.join(",") + "Z"; });
.transition()
.duration(trans_time)
.attrTween('d', pathTween(oldVorData))
svg.selectAll(".circle-catcher")
.data(nodes)
.transition()
.duration(trans_time)
.attr("cx", function(d) {return x(d[0]);})
.attr("cy", function(d) {return y(d[1]);})
}
function pathTween(oldData){
return function(d, i){
return function(t){
pathInterp = d3.interpolate(oldData[i], d);
return "M" + pathInterp(t).join(",") + "Z";
}
}
}
d3.select('#buttonContain').on("click", function(){
update(2000)
})
;
</script>
</body>
https://d3js.org/d3.v4.min.js