You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

567 lines
17 KiB

1 year ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
  1. // https://d3js.org/d3-brush/ v1.0.6 Copyright 2018 Mike Bostock
  2. (function (global, factory) {
  3. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-selection'), require('d3-dispatch'), require('d3-drag'), require('d3-interpolate'), require('d3-transition')) :
  4. typeof define === 'function' && define.amd ? define(['exports', 'd3-selection', 'd3-dispatch', 'd3-drag', 'd3-interpolate', 'd3-transition'], factory) :
  5. (factory((global.d3 = global.d3 || {}),global.d3,global.d3,global.d3,global.d3,global.d3));
  6. }(this, (function (exports,d3Selection,d3Dispatch,d3Drag,d3Interpolate,d3Transition) { 'use strict';
  7. function constant(x) {
  8. return function() {
  9. return x;
  10. };
  11. }
  12. function BrushEvent(target, type, selection) {
  13. this.target = target;
  14. this.type = type;
  15. this.selection = selection;
  16. }
  17. function nopropagation() {
  18. d3Selection.event.stopImmediatePropagation();
  19. }
  20. function noevent() {
  21. d3Selection.event.preventDefault();
  22. d3Selection.event.stopImmediatePropagation();
  23. }
  24. var MODE_DRAG = {name: "drag"},
  25. MODE_SPACE = {name: "space"},
  26. MODE_HANDLE = {name: "handle"},
  27. MODE_CENTER = {name: "center"};
  28. var X = {
  29. name: "x",
  30. handles: ["e", "w"].map(type),
  31. input: function(x, e) { return x && [[x[0], e[0][1]], [x[1], e[1][1]]]; },
  32. output: function(xy) { return xy && [xy[0][0], xy[1][0]]; }
  33. };
  34. var Y = {
  35. name: "y",
  36. handles: ["n", "s"].map(type),
  37. input: function(y, e) { return y && [[e[0][0], y[0]], [e[1][0], y[1]]]; },
  38. output: function(xy) { return xy && [xy[0][1], xy[1][1]]; }
  39. };
  40. var XY = {
  41. name: "xy",
  42. handles: ["n", "e", "s", "w", "nw", "ne", "se", "sw"].map(type),
  43. input: function(xy) { return xy; },
  44. output: function(xy) { return xy; }
  45. };
  46. var cursors = {
  47. overlay: "crosshair",
  48. selection: "move",
  49. n: "ns-resize",
  50. e: "ew-resize",
  51. s: "ns-resize",
  52. w: "ew-resize",
  53. nw: "nwse-resize",
  54. ne: "nesw-resize",
  55. se: "nwse-resize",
  56. sw: "nesw-resize"
  57. };
  58. var flipX = {
  59. e: "w",
  60. w: "e",
  61. nw: "ne",
  62. ne: "nw",
  63. se: "sw",
  64. sw: "se"
  65. };
  66. var flipY = {
  67. n: "s",
  68. s: "n",
  69. nw: "sw",
  70. ne: "se",
  71. se: "ne",
  72. sw: "nw"
  73. };
  74. var signsX = {
  75. overlay: +1,
  76. selection: +1,
  77. n: null,
  78. e: +1,
  79. s: null,
  80. w: -1,
  81. nw: -1,
  82. ne: +1,
  83. se: +1,
  84. sw: -1
  85. };
  86. var signsY = {
  87. overlay: +1,
  88. selection: +1,
  89. n: -1,
  90. e: null,
  91. s: +1,
  92. w: null,
  93. nw: -1,
  94. ne: -1,
  95. se: +1,
  96. sw: +1
  97. };
  98. function type(t) {
  99. return {type: t};
  100. }
  101. // Ignore right-click, since that should open the context menu.
  102. function defaultFilter() {
  103. return !d3Selection.event.button;
  104. }
  105. function defaultExtent() {
  106. var svg = this.ownerSVGElement || this;
  107. return [[0, 0], [svg.width.baseVal.value, svg.height.baseVal.value]];
  108. }
  109. // Like d3.local, but with the name “__brush” rather than auto-generated.
  110. function local(node) {
  111. while (!node.__brush) if (!(node = node.parentNode)) return;
  112. return node.__brush;
  113. }
  114. function empty(extent) {
  115. return extent[0][0] === extent[1][0]
  116. || extent[0][1] === extent[1][1];
  117. }
  118. function brushSelection(node) {
  119. var state = node.__brush;
  120. return state ? state.dim.output(state.selection) : null;
  121. }
  122. function brushX() {
  123. return brush$1(X);
  124. }
  125. function brushY() {
  126. return brush$1(Y);
  127. }
  128. function brush() {
  129. return brush$1(XY);
  130. }
  131. function brush$1(dim) {
  132. var extent = defaultExtent,
  133. filter = defaultFilter,
  134. listeners = d3Dispatch.dispatch(brush, "start", "brush", "end"),
  135. handleSize = 6,
  136. touchending;
  137. function brush(group) {
  138. var overlay = group
  139. .property("__brush", initialize)
  140. .selectAll(".overlay")
  141. .data([type("overlay")]);
  142. overlay.enter().append("rect")
  143. .attr("class", "overlay")
  144. .attr("pointer-events", "all")
  145. .attr("cursor", cursors.overlay)
  146. .merge(overlay)
  147. .each(function() {
  148. var extent = local(this).extent;
  149. d3Selection.select(this)
  150. .attr("x", extent[0][0])
  151. .attr("y", extent[0][1])
  152. .attr("width", extent[1][0] - extent[0][0])
  153. .attr("height", extent[1][1] - extent[0][1]);
  154. });
  155. group.selectAll(".selection")
  156. .data([type("selection")])
  157. .enter().append("rect")
  158. .attr("class", "selection")
  159. .attr("cursor", cursors.selection)
  160. .attr("fill", "#777")
  161. .attr("fill-opacity", 0.3)
  162. .attr("stroke", "#fff")
  163. .attr("shape-rendering", "crispEdges");
  164. var handle = group.selectAll(".handle")
  165. .data(dim.handles, function(d) { return d.type; });
  166. handle.exit().remove();
  167. handle.enter().append("rect")
  168. .attr("class", function(d) { return "handle handle--" + d.type; })
  169. .attr("cursor", function(d) { return cursors[d.type]; });
  170. group
  171. .each(redraw)
  172. .attr("fill", "none")
  173. .attr("pointer-events", "all")
  174. .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)")
  175. .on("mousedown.brush touchstart.brush", started);
  176. }
  177. brush.move = function(group, selection) {
  178. if (group.selection) {
  179. group
  180. .on("start.brush", function() { emitter(this, arguments).beforestart().start(); })
  181. .on("interrupt.brush end.brush", function() { emitter(this, arguments).end(); })
  182. .tween("brush", function() {
  183. var that = this,
  184. state = that.__brush,
  185. emit = emitter(that, arguments),
  186. selection0 = state.selection,
  187. selection1 = dim.input(typeof selection === "function" ? selection.apply(this, arguments) : selection, state.extent),
  188. i = d3Interpolate.interpolate(selection0, selection1);
  189. function tween(t) {
  190. state.selection = t === 1 && empty(selection1) ? null : i(t);
  191. redraw.call(that);
  192. emit.brush();
  193. }
  194. return selection0 && selection1 ? tween : tween(1);
  195. });
  196. } else {
  197. group
  198. .each(function() {
  199. var that = this,
  200. args = arguments,
  201. state = that.__brush,
  202. selection1 = dim.input(typeof selection === "function" ? selection.apply(that, args) : selection, state.extent),
  203. emit = emitter(that, args).beforestart();
  204. d3Transition.interrupt(that);
  205. state.selection = selection1 == null || empty(selection1) ? null : selection1;
  206. redraw.call(that);
  207. emit.start().brush().end();
  208. });
  209. }
  210. };
  211. function redraw() {
  212. var group = d3Selection.select(this),
  213. selection = local(this).selection;
  214. if (selection) {
  215. group.selectAll(".selection")
  216. .style("display", null)
  217. .attr("x", selection[0][0])
  218. .attr("y", selection[0][1])
  219. .attr("width", selection[1][0] - selection[0][0])
  220. .attr("height", selection[1][1] - selection[0][1]);
  221. group.selectAll(".handle")
  222. .style("display", null)
  223. .attr("x", function(d) { return d.type[d.type.length - 1] === "e" ? selection[1][0] - handleSize / 2 : selection[0][0] - handleSize / 2; })
  224. .attr("y", function(d) { return d.type[0] === "s" ? selection[1][1] - handleSize / 2 : selection[0][1] - handleSize / 2; })
  225. .attr("width", function(d) { return d.type === "n" || d.type === "s" ? selection[1][0] - selection[0][0] + handleSize : handleSize; })
  226. .attr("height", function(d) { return d.type === "e" || d.type === "w" ? selection[1][1] - selection[0][1] + handleSize : handleSize; });
  227. }
  228. else {
  229. group.selectAll(".selection,.handle")
  230. .style("display", "none")
  231. .attr("x", null)
  232. .attr("y", null)
  233. .attr("width", null)
  234. .attr("height", null);
  235. }
  236. }
  237. function emitter(that, args) {
  238. return that.__brush.emitter || new Emitter(that, args);
  239. }
  240. function Emitter(that, args) {
  241. this.that = that;
  242. this.args = args;
  243. this.state = that.__brush;
  244. this.active = 0;
  245. }
  246. Emitter.prototype = {
  247. beforestart: function() {
  248. if (++this.active === 1) this.state.emitter = this, this.starting = true;
  249. return this;
  250. },
  251. start: function() {
  252. if (this.starting) this.starting = false, this.emit("start");
  253. return this;
  254. },
  255. brush: function() {
  256. this.emit("brush");
  257. return this;
  258. },
  259. end: function() {
  260. if (--this.active === 0) delete this.state.emitter, this.emit("end");
  261. return this;
  262. },
  263. emit: function(type) {
  264. d3Selection.customEvent(new BrushEvent(brush, type, dim.output(this.state.selection)), listeners.apply, listeners, [type, this.that, this.args]);
  265. }
  266. };
  267. function started() {
  268. if (d3Selection.event.touches) { if (d3Selection.event.changedTouches.length < d3Selection.event.touches.length) return noevent(); }
  269. else if (touchending) return;
  270. if (!filter.apply(this, arguments)) return;
  271. var that = this,
  272. type = d3Selection.event.target.__data__.type,
  273. mode = (d3Selection.event.metaKey ? type = "overlay" : type) === "selection" ? MODE_DRAG : (d3Selection.event.altKey ? MODE_CENTER : MODE_HANDLE),
  274. signX = dim === Y ? null : signsX[type],
  275. signY = dim === X ? null : signsY[type],
  276. state = local(that),
  277. extent = state.extent,
  278. selection = state.selection,
  279. W = extent[0][0], w0, w1,
  280. N = extent[0][1], n0, n1,
  281. E = extent[1][0], e0, e1,
  282. S = extent[1][1], s0, s1,
  283. dx,
  284. dy,
  285. moving,
  286. shifting = signX && signY && d3Selection.event.shiftKey,
  287. lockX,
  288. lockY,
  289. point0 = d3Selection.mouse(that),
  290. point = point0,
  291. emit = emitter(that, arguments).beforestart();
  292. if (type === "overlay") {
  293. state.selection = selection = [
  294. [w0 = dim === Y ? W : point0[0], n0 = dim === X ? N : point0[1]],
  295. [e0 = dim === Y ? E : w0, s0 = dim === X ? S : n0]
  296. ];
  297. } else {
  298. w0 = selection[0][0];
  299. n0 = selection[0][1];
  300. e0 = selection[1][0];
  301. s0 = selection[1][1];
  302. }
  303. w1 = w0;
  304. n1 = n0;
  305. e1 = e0;
  306. s1 = s0;
  307. var group = d3Selection.select(that)
  308. .attr("pointer-events", "none");
  309. var overlay = group.selectAll(".overlay")
  310. .attr("cursor", cursors[type]);
  311. if (d3Selection.event.touches) {
  312. group
  313. .on("touchmove.brush", moved, true)
  314. .on("touchend.brush touchcancel.brush", ended, true);
  315. } else {
  316. var view = d3Selection.select(d3Selection.event.view)
  317. .on("keydown.brush", keydowned, true)
  318. .on("keyup.brush", keyupped, true)
  319. .on("mousemove.brush", moved, true)
  320. .on("mouseup.brush", ended, true);
  321. d3Drag.dragDisable(d3Selection.event.view);
  322. }
  323. nopropagation();
  324. d3Transition.interrupt(that);
  325. redraw.call(that);
  326. emit.start();
  327. function moved() {
  328. var point1 = d3Selection.mouse(that);
  329. if (shifting && !lockX && !lockY) {
  330. if (Math.abs(point1[0] - point[0]) > Math.abs(point1[1] - point[1])) lockY = true;
  331. else lockX = true;
  332. }
  333. point = point1;
  334. moving = true;
  335. noevent();
  336. move();
  337. }
  338. function move() {
  339. var t;
  340. dx = point[0] - point0[0];
  341. dy = point[1] - point0[1];
  342. switch (mode) {
  343. case MODE_SPACE:
  344. case MODE_DRAG: {
  345. if (signX) dx = Math.max(W - w0, Math.min(E - e0, dx)), w1 = w0 + dx, e1 = e0 + dx;
  346. if (signY) dy = Math.max(N - n0, Math.min(S - s0, dy)), n1 = n0 + dy, s1 = s0 + dy;
  347. break;
  348. }
  349. case MODE_HANDLE: {
  350. if (signX < 0) dx = Math.max(W - w0, Math.min(E - w0, dx)), w1 = w0 + dx, e1 = e0;
  351. else if (signX > 0) dx = Math.max(W - e0, Math.min(E - e0, dx)), w1 = w0, e1 = e0 + dx;
  352. if (signY < 0) dy = Math.max(N - n0, Math.min(S - n0, dy)), n1 = n0 + dy, s1 = s0;
  353. else if (signY > 0) dy = Math.max(N - s0, Math.min(S - s0, dy)), n1 = n0, s1 = s0 + dy;
  354. break;
  355. }
  356. case MODE_CENTER: {
  357. if (signX) w1 = Math.max(W, Math.min(E, w0 - dx * signX)), e1 = Math.max(W, Math.min(E, e0 + dx * signX));
  358. if (signY) n1 = Math.max(N, Math.min(S, n0 - dy * signY)), s1 = Math.max(N, Math.min(S, s0 + dy * signY));
  359. break;
  360. }
  361. }
  362. if (e1 < w1) {
  363. signX *= -1;
  364. t = w0, w0 = e0, e0 = t;
  365. t = w1, w1 = e1, e1 = t;
  366. if (type in flipX) overlay.attr("cursor", cursors[type = flipX[type]]);
  367. }
  368. if (s1 < n1) {
  369. signY *= -1;
  370. t = n0, n0 = s0, s0 = t;
  371. t = n1, n1 = s1, s1 = t;
  372. if (type in flipY) overlay.attr("cursor", cursors[type = flipY[type]]);
  373. }
  374. if (state.selection) selection = state.selection; // May be set by brush.move!
  375. if (lockX) w1 = selection[0][0], e1 = selection[1][0];
  376. if (lockY) n1 = selection[0][1], s1 = selection[1][1];
  377. if (selection[0][0] !== w1
  378. || selection[0][1] !== n1
  379. || selection[1][0] !== e1
  380. || selection[1][1] !== s1) {
  381. state.selection = [[w1, n1], [e1, s1]];
  382. redraw.call(that);
  383. emit.brush();
  384. }
  385. }
  386. function ended() {
  387. nopropagation();
  388. if (d3Selection.event.touches) {
  389. if (d3Selection.event.touches.length) return;
  390. if (touchending) clearTimeout(touchending);
  391. touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed!
  392. group.on("touchmove.brush touchend.brush touchcancel.brush", null);
  393. } else {
  394. d3Drag.dragEnable(d3Selection.event.view, moving);
  395. view.on("keydown.brush keyup.brush mousemove.brush mouseup.brush", null);
  396. }
  397. group.attr("pointer-events", "all");
  398. overlay.attr("cursor", cursors.overlay);
  399. if (state.selection) selection = state.selection; // May be set by brush.move (on start)!
  400. if (empty(selection)) state.selection = null, redraw.call(that);
  401. emit.end();
  402. }
  403. function keydowned() {
  404. switch (d3Selection.event.keyCode) {
  405. case 16: { // SHIFT
  406. shifting = signX && signY;
  407. break;
  408. }
  409. case 18: { // ALT
  410. if (mode === MODE_HANDLE) {
  411. if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;
  412. if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;
  413. mode = MODE_CENTER;
  414. move();
  415. }
  416. break;
  417. }
  418. case 32: { // SPACE; takes priority over ALT
  419. if (mode === MODE_HANDLE || mode === MODE_CENTER) {
  420. if (signX < 0) e0 = e1 - dx; else if (signX > 0) w0 = w1 - dx;
  421. if (signY < 0) s0 = s1 - dy; else if (signY > 0) n0 = n1 - dy;
  422. mode = MODE_SPACE;
  423. overlay.attr("cursor", cursors.selection);
  424. move();
  425. }
  426. break;
  427. }
  428. default: return;
  429. }
  430. noevent();
  431. }
  432. function keyupped() {
  433. switch (d3Selection.event.keyCode) {
  434. case 16: { // SHIFT
  435. if (shifting) {
  436. lockX = lockY = shifting = false;
  437. move();
  438. }
  439. break;
  440. }
  441. case 18: { // ALT
  442. if (mode === MODE_CENTER) {
  443. if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1;
  444. if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1;
  445. mode = MODE_HANDLE;
  446. move();
  447. }
  448. break;
  449. }
  450. case 32: { // SPACE
  451. if (mode === MODE_SPACE) {
  452. if (d3Selection.event.altKey) {
  453. if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;
  454. if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;
  455. mode = MODE_CENTER;
  456. } else {
  457. if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1;
  458. if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1;
  459. mode = MODE_HANDLE;
  460. }
  461. overlay.attr("cursor", cursors[type]);
  462. move();
  463. }
  464. break;
  465. }
  466. default: return;
  467. }
  468. noevent();
  469. }
  470. }
  471. function initialize() {
  472. var state = this.__brush || {selection: null};
  473. state.extent = extent.apply(this, arguments);
  474. state.dim = dim;
  475. return state;
  476. }
  477. brush.extent = function(_) {
  478. return arguments.length ? (extent = typeof _ === "function" ? _ : constant([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), brush) : extent;
  479. };
  480. brush.filter = function(_) {
  481. return arguments.length ? (filter = typeof _ === "function" ? _ : constant(!!_), brush) : filter;
  482. };
  483. brush.handleSize = function(_) {
  484. return arguments.length ? (handleSize = +_, brush) : handleSize;
  485. };
  486. brush.on = function() {
  487. var value = listeners.on.apply(listeners, arguments);
  488. return value === listeners ? brush : value;
  489. };
  490. return brush;
  491. }
  492. exports.brush = brush;
  493. exports.brushX = brushX;
  494. exports.brushY = brushY;
  495. exports.brushSelection = brushSelection;
  496. Object.defineProperty(exports, '__esModule', { value: true });
  497. })));