-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpolygon-interactor.js
106 lines (89 loc) · 3.4 KB
/
polygon-interactor.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
"use strict";
function polygonInteractor(state, x, y) {
// x, y are d3.scale objects (linear, log, etc) from parent
// dispatch is the d3 event dispatcher: should have event "update" register
//var state = options;
var name = state.name;
var radius = ( state.radius == null ) ? 5 : state.radius;
var event_name = "polygon." + state.name;
var dispatch = d3.dispatch("update");
var x = x || d3.scale.linear();
var y = y || d3.scale.linear();
var interpolation = (state.interpolation == null) ? 'linear' : state.interpolation;
var prevent_crossing = (state.prevent_crossing == null) ? false : state.prevent_crossing;
var show_points = (state.show_points == null) ? true : state.show_points;
var show_lines = (state.show_lines == null) ? true : state.show_lines;
var close_path = (state.close_path == null) ? false : state.close_path;
var fixed = (state.fixed == null) ? false : state.fixed;
var cursor = (fixed) ? "auto" : "move";
var line = d3.svg.line()
.x(function(d) { return x(d[0]); })
.y(function(d) { return y(d[1]); })
.interpolate(interpolation);
var drag_corner = d3.behavior.drag()
.on("drag", dragmove_corner)
.on("dragstart", function() { d3.event.sourceEvent.stopPropagation(); });
function interactor(selection) {
var group = selection.append("g")
.classed("interactors interactor-" + name, true)
.style("cursor", cursor)
var edge_group = group.append("g")
.attr("class", "edges")
.style("stroke", state.color1)
.style("stroke-linecap", "round")
.style("stroke-width", "4px")
.style("fill", "none")
//if (!fixed) edges.call(drag_edge);
var corner_group = group.append("g")
.classed("corners", true)
.attr("fill", state.color1)
interactor.update = function() {
var corners = corner_group.selectAll('.corner').data(state.points)
var new_corners = corners.enter().append("circle")
.classed("corner", true)
.attr("vertex", function(d,i) { return i.toFixed()})
.attr("r", radius);
if (!fixed) new_corners.call(drag_corner);
corners
.attr("cx", function(d) { return x(d[0]); })
.attr("cy", function(d) { return y(d[1]); });
corners.exit().remove();
var edge_data = (state.close_path) ? state.points.concat(state.points[0]) : state.points;
var edges = edge_group.selectAll('.edge').data([edge_data]);
edges.enter().append("path")
.classed("edge", true)
.attr("side", function(d,i) { return i.toFixed()})
edges.attr("d", line);
edges.exit().remove();
// fire!
dispatch.update();
}
interactor.update();
}
function dragmove_corner(d,i) {
var new_x = x.invert(d3.event.x),
new_y = y.invert(d3.event.y);
var sp = state.points;
if (prevent_crossing && sp[i+1] != null && sp[i+1][0] <= new_x) {
new_x = sp[i+1][0]
}
if (prevent_crossing && sp[i-1] != null && sp[i-1][0] >= new_x) {
new_x = sp[i-1][0]
}
state.points[i] = [new_x, new_y];
interactor.update();
}
interactor.x = function(_) {
if (!arguments.length) return x;
x = _;
return interactor;
};
interactor.y = function(_) {
if (!arguments.length) return y;
y = _;
return interactor;
};
interactor.state = state;
interactor.dispatch = dispatch;
return interactor
}