|
1 var w = 960, |
|
2 h = 500, |
|
3 line = d3.svg.line(), |
|
4 points = d3.range(1, 5).map(function(i) { return [i * w / 5, 50 + Math.random() * (h - 100)]; }), |
|
5 dragged = null, |
|
6 selected = points[0]; |
|
7 |
|
8 var vis = d3.select("#chart").append("svg:svg") |
|
9 .attr("width", w) |
|
10 .attr("height", h); |
|
11 |
|
12 vis.append("svg:rect") |
|
13 .attr("width", w) |
|
14 .attr("height", h) |
|
15 .on("mousedown", function() { |
|
16 points.push(selected = dragged = d3.svg.mouse(vis.node())); |
|
17 update(); |
|
18 }); |
|
19 |
|
20 vis.append("svg:path") |
|
21 .data([points]) |
|
22 .attr("class", "line") |
|
23 .call(update); |
|
24 |
|
25 d3.select(window) |
|
26 .on("mousemove", mousemove) |
|
27 .on("mouseup", mouseup) |
|
28 .on("keydown", keydown); |
|
29 |
|
30 // Add interpolator dropdown |
|
31 d3.select("#interpolate") |
|
32 .on("change", function() { |
|
33 line.interpolate(this.value); |
|
34 update(); |
|
35 }) |
|
36 .selectAll("option") |
|
37 .data([ |
|
38 "linear", |
|
39 "step-before", |
|
40 "step-after", |
|
41 "basis", |
|
42 "basis-open", |
|
43 "basis-closed", |
|
44 "cardinal", |
|
45 "cardinal-open", |
|
46 "cardinal-closed", |
|
47 "monotone" |
|
48 ]) |
|
49 .enter().append("option") |
|
50 .attr("value", String) |
|
51 .text(String); |
|
52 |
|
53 function update() { |
|
54 vis.select("path").attr("d", line); |
|
55 |
|
56 var circle = vis.selectAll("circle") |
|
57 .data(points, function(d) { return d; }); |
|
58 |
|
59 circle.enter().append("svg:circle") |
|
60 .attr("class", function(d) { return d === selected ? "selected" : null; }) |
|
61 .attr("cx", function(d) { return d[0]; }) |
|
62 .attr("cy", function(d) { return d[1]; }) |
|
63 .attr("r", 1e-6) |
|
64 .on("mousedown", function(d) { |
|
65 selected = dragged = d; |
|
66 update(); |
|
67 }) |
|
68 .transition() |
|
69 .duration(750) |
|
70 .ease("elastic") |
|
71 .attr("r", 6.5); |
|
72 |
|
73 circle |
|
74 .attr("class", function(d) { return d === selected ? "selected" : null; }) |
|
75 .attr("cx", function(d) { return d[0]; }) |
|
76 .attr("cy", function(d) { return d[1]; }); |
|
77 |
|
78 circle.exit().remove(); |
|
79 |
|
80 if (d3.event) { |
|
81 d3.event.preventDefault(); |
|
82 d3.event.stopPropagation(); |
|
83 } |
|
84 } |
|
85 |
|
86 |
|
87 function mousemove() { |
|
88 if (!dragged) return; |
|
89 var m = d3.svg.mouse(vis.node()); |
|
90 dragged[0] = Math.max(0, Math.min(w, m[0])); |
|
91 dragged[1] = Math.max(0, Math.min(h, m[1])); |
|
92 update(); |
|
93 } |
|
94 |
|
95 function mouseup() { |
|
96 if (!dragged) return; |
|
97 mousemove(); |
|
98 dragged = null; |
|
99 } |
|
100 |
|
101 function keydown() { |
|
102 if (!selected) return; |
|
103 switch (d3.event.keyCode) { |
|
104 case 8: // backspace |
|
105 case 46: { // delete |
|
106 var i = points.indexOf(selected); |
|
107 points.splice(i, 1); |
|
108 selected = points.length ? points[i > 0 ? i - 1 : 0] : null; |
|
109 update(); |
|
110 break; |
|
111 } |
|
112 } |
|
113 } |