Introducing a snippet of code that detects if the user is moving circles and prompts the creation of a new circle if they are not moving. Hopefully, this solution proves useful to you.
var roadClosed = true;
var canvasWidth = 960,
canvasHeight = 500;
var points = d3.range(1, 5).map(function(i) {
return [i * canvasWidth / 5, 50 + Math.random() * (canvasHeight - 100)];
});
var points1 = d3.range(1, 5).map(function(i) {
return [i * canvasWidth / 5, 50 + Math.random() * (canvasHeight - 100)];
});
var points2 = d3.range(1, 5).map(function(i) {
return [i * canvasWidth / 5, 50 + Math.random() * (canvasHeight - 100)];
});
var count = 0;
var ways = [];
var currentWay = null;
var selected = null;
var line = d3.svg.line();
var svg = d3.select("body").append("svg")
.attr("width", canvasWidth)
.attr("height", canvasHeight);
var rect = svg.append("rect")
.attr("width", canvasWidth)
.attr("height", canvasHeight);
ways.forEach(function(way, i) {
svg.append("path")
.datum(way)
.attr("id", "p" + way.id)
.attr("class", "line")
.call(redraw);
});
d3.select(window)
.on("keydown", keydown)
//.on("mousemove", mousemove)
.on("mouseup", mouseup)
.on("mousedown", mousedown)
.on("dblclick", dblclick);
function redraw(way) {
way.attr("d", function(d) { return line(d.pts); });
var circle = svg.selectAll(".way" + way.data()[0].id)
.data(way.data()[0].pts, function(d) { return d; });
circle.enter().append("circle")
.attr("class", "way" + way.data()[0].id)
.attr("r", 1e-6)
.on("mousedown", function(d) {
if (roadClosed) {
currentWay = way.data()[0];
selected = d;
if (d3.event) {
d3.event.preventDefault();
d3.event.stopPropagation();
}
}
})
.on("mouseover", function() { d3.select(d3.event.target).classed("highlight", true); })
.on("mouseout", function() { d3.select(d3.event.target).classed("highlight", false); })
.transition()
.duration(750)
.ease("elastic")
.attr("r", 6.5);
circle
.attr("cx", function(d) { return d[0]; })
.attr("cy", function(d) { return d[1]; });
////
var drag = d3.behavior.drag();
drag.on("dragstart", function(d) {
console.log('START');
})
.on("drag", function(d) {
console.log('MOVE');
var m = d3.mouse(svg.node());
d[0] = Math.max(0, Math.min(canvasWidth, m[0]));
d[1] = Math.max(0, Math.min(canvasHeight, m[1]));
//redraw(way);
redrawAll();
})
.on("dragend", function(d) {
console.log('END');
});
circle.call(drag);
////
circle.exit().remove();
/* if (d3.event) {
d3.event.preventDefault();
d3.event.stopPropagation();
}*/
}
function dblclick() {
currentWay.pts.pop();
//redraw(svg.select("#p" + currentWay.id));
redrawAll();
roadClosed = true;
}
function mousedown() {
start = event.pageX + event.pageY;
console.log(start);
}
function mouseup(){
if(start >= (event.pageX + event.pageY) - 10 && start <= (event.pageX + event.pageY) + 10){
if (roadClosed) {
currentWay = { id: ++count, pts: [] };
ways.push(currentWay);
svg.append("path")
.datum(currentWay)
.attr("id", "p" + currentWay.id)
.attr("class", "line")
.on("mouseover", function() {
d3.select(d3.event.target).classed("highlight", true);
})
.on("mouseout", function() { d3.select(d3.event.target).classed("highlight", false); })
.call(redraw);
roadClosed = false;
}
currentWay.pts.push(selected = d3.mouse(svg.node()));
//redraw(svg.select("#p" + currentWay.id));
redrawAll();
}else{
roadClosed = true;
}
}
function redrawAll() {
ways.forEach(function(way, i) {
redraw(svg.select("#p" + way.id));
});
}
function mousemove() {
}
function keydown() {
if (!selected) return;
switch (d3.event.keyCode) {
case 8: // backspace
case 46: { // delete
var i = currentWay.pts.indexOf(selected);
currentWay.pts.splice(i, 1);
selected = currentWay.pts.length ? currentWay.pts[i > 0 ? i - 1 : 0] : null;
redraw(svg.select("#p" + currentWay.id));
break;
}
}
}