Допустим, у меня есть массив произвольных точек, т.е.
var points = [
//e: terminals
//a: arm
//s: support
{x: 32, y: 256, t: "e"},
{x: 250, y: 256, t: "a"},
{x: 260, y: 256, t: "s"},
{x: 320, y: 256, t: "a"},
{x: 330, y: 256, t: "s"},
{x: 128, y: 256, t: "a"},
{x: 138, y: 256, t: "s"},
{x: 480, y: 256, t: "e"}
];
И еще один, называемый сегментами, который определяет, как эти точки устанавливаются в один путь:
var segments = [
{start: 0, support: null, end: 5},
{start: 5, support: 6, end: 1},
{start: 1, support: 2, end: 3},
{start: 3, support: 4, end: 7}
];
Рука точка (t: «a») всегда имеет следующие значения t: «s», поддерживающие единицу.
Двойным щелчком мыши на точке рычага (пурпурного цвета) код должен удалить ее, а также точку ее поддержки ( cyan) и переиндексировать массив точек и сегментов.
Например, если вы хотите удалить {x: 128, y: 256, t: "a"} и его пару {x: 138, y: 256, t: "s"}, переиндексированные массивы должны быть такими:
var points = [
{x: 32, y: 256, t: "e"},
{x: 250, y: 256, t: "a"},
{x: 260, y: 256, t: "s"},
{x: 320, y: 256, t: "a"},
{x: 330, y: 256, t: "s"},
{x: 480, y: 256, t: "e"}
];
var сегментов = [
{start: 0, support: null, end: 1},
{start: 1, support: 2, end: 3},
{start: 3, support: 5, end: 5}
];
И я мог бы найти эффективный способ сделать эту переиндексацию. Код прилагается.
var points = [
//e: terminals
//a: arm
//s: support
{x: 32, y: 256, t: "e"},
{x: 250, y: 256, t: "a"},
{x: 260, y: 256, t: "s"},
{x: 320, y: 256, t: "a"},
{x: 330, y: 256, t: "s"},
{x: 128, y: 256, t: "a"},
{x: 138, y: 256, t: "s"},
{x: 480, y: 256, t: "e"}
//the fist and last points are always end ones
];
var segments = [
{start: 0, support: null, end: 5},
{start: 5, support: 6, end: 1},
{start: 1, support: 2, end: 3},
{start: 3, support: 4, end: 7}
];
var svg = d3.select("#container");
var path = svg.append("path")
.attr("d", generatePath())
.attr("stroke", "#000000")
.attr("stroke-width", 2);
var node = svg.selectAll(".node")
.data(getAllPoints())
.enter()
.append("circle")
.attr("class", "node")
.attr("cx", function(d_) { return d_.x; })
.attr("cy", function(d_) { return d_.y; })
.attr("r", 4)
.attr("fill", function(d_){
if(d_.t == "e") { return "#FF0000"; }
else if(d_.t == "s") { return "#00FFFF"; }
return "#FF00FF";
})
.on("dblclick", function(d_){
if(d_.t == "a"){
console.log("have to delete this point and its support")
console.log("and reindex points and segments array")
//if there is only one pair of a/s points
//the solution is straight forward
//while first and last points are always end ones
if(segments.length == 2){
points.splice(d_.id, 2);
points.forEach(function(p_, i_){ p_.id = i_; });
newSegments = [{start: 0, support: null, end: 1}];
}else{
//could find effective solution here
//has to work but it doesn't
//segments.forEach(function(segment_){
//
// if(segment_.end != d_.id){
//
// var start = segment_.start,
// support = segment_.support,
// end = segment_.end;
//
// if(start > d_.id - 2) { start -= 2; }
// if(support > d_.id - 2 && support != null) { support -= 2; }
// if(end > d_.id - 2) { end -= 2; }
//
// newSegments.push({start: start, support: support, end: end})
//
// }
//
// points.splice(d_.id, 2);
// points.forEach(function(p_, i_){ p_.id = i_; });
// segments = newSegments;
}
}
})
function generatePath(){
var out = "";
segments.forEach(function(segment_, i_){
if(i_ == 0) {
//skip support point
out += "M" + points[segment_.start].x + " " + points[segment_.start].y;
out += " L" + points[segment_.end].x + " " + points[segment_.end].y;
}else{
out += " L" + points[segment_.start].x + " " + points[segment_.start].y;
out += " L" + points[segment_.support].x + " " + points[segment_.support].y;
out += " L" + points[segment_.end].x + " " + points[segment_.end].y;
}
})
return out;
}
function getAllPoints(){
var out = [];
points.forEach(function(point_, i_){ out.push(point_); out[out.length - 1].id = i_; });
return out;
}
body { margin: 0; }
#container {
position: absolute;
left: 0; top: 0;
width: 512px;
height: 512px;
background-color: darkgray;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>D3.JS: Points chain</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<svg id="container" width="512" height="512"></svg>
</body>
</html>