Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Two #71

Merged
merged 15 commits into from
Aug 23, 2020
Merged
82 changes: 53 additions & 29 deletions README.md

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@
"postpublish": "git push && git push --tags && cd ../d3.github.com && git pull && cp ../${npm_package_name}/dist/${npm_package_name}.js ${npm_package_name}.v${npm_package_version%%.*}.js && cp ../${npm_package_name}/dist/${npm_package_name}.min.js ${npm_package_name}.v${npm_package_version%%.*}.min.js && git add ${npm_package_name}.v${npm_package_version%%.*}.js ${npm_package_name}.v${npm_package_version%%.*}.min.js && git commit -m \"${npm_package_name} ${npm_package_version}\" && git push && cd - && zip -j dist/${npm_package_name}.zip -- LICENSE README.md dist/${npm_package_name}.js dist/${npm_package_name}.min.js"
},
"dependencies": {
"d3-dispatch": "1",
"d3-drag": "1",
"d3-interpolate": "1",
"d3-selection": "1",
"d3-transition": "1"
"d3-dispatch": "1 - 2",
"d3-drag": "2",
"d3-interpolate": "1 - 2",
"d3-selection": "2",
"d3-transition": "1 - 2"
},
"devDependencies": {
"eslint": "6",
Expand Down
152 changes: 91 additions & 61 deletions src/brush.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {dispatch} from "d3-dispatch";
import {dragDisable, dragEnable} from "d3-drag";
import {interpolate} from "d3-interpolate";
import {customEvent, event, touch, mouse, select} from "d3-selection";
import {pointer, select} from "d3-selection";
import {interrupt} from "d3-transition";
import constant from "./constant.js";
import BrushEvent from "./event.js";
Expand All @@ -12,6 +12,8 @@ var MODE_DRAG = {name: "drag"},
MODE_HANDLE = {name: "handle"},
MODE_CENTER = {name: "center"};

const {abs, max, min} = Math;

function number1(e) {
return [+e[0], +e[1]];
}
Expand All @@ -20,12 +22,6 @@ function number2(e) {
return [number1(e[0]), number1(e[1])];
}

function toucher(identifier) {
return function(target) {
return touch(target, event.touches, identifier);
};
}

var X = {
name: "x",
handles: ["w", "e"].map(type),
Expand Down Expand Up @@ -109,7 +105,7 @@ function type(t) {
}

// Ignore right-click, since that should open the context menu.
function defaultFilter() {
function defaultFilter(event) {
return !event.ctrlKey && !event.button;
}

Expand Down Expand Up @@ -216,10 +212,10 @@ function brush(dim) {
}

brush.move = function(group, selection) {
if (group.selection) {
if (group.selection && group.selection() !== group) {
Fil marked this conversation as resolved.
Show resolved Hide resolved
group
.on("start.brush", function() { emitter(this, arguments).beforestart().start(); })
.on("interrupt.brush end.brush", function() { emitter(this, arguments).end(); })
.on("start.brush", function(event) { emitter(this, arguments).beforestart().start(event); })
.on("interrupt.brush end.brush", function(event) { emitter(this, arguments).end(event); })
.tween("brush", function() {
var that = this,
state = that.__brush,
Expand Down Expand Up @@ -302,28 +298,40 @@ function brush(dim) {

Emitter.prototype = {
beforestart: function() {
if (++this.active === 1) this.state.emitter = this, this.starting = true;
if (++this.active === 1) this.state.emitter = this, this.starting = true, this.dispatch = listeners.copy();
return this;
},
start: function() {
if (this.starting) this.starting = false, this.emit("start");
else this.emit("brush");
start: function(event) {
if (this.starting) this.starting = false, this.emit("start", event);
else this.emit("brush", event);
return this;
},
brush: function() {
this.emit("brush");
brush: function(event) {
this.emit("brush", event);
return this;
},
end: function() {
if (--this.active === 0) delete this.state.emitter, this.emit("end");
end: function(event) {
if (--this.active === 0) delete this.state.emitter, this.emit("end", event);
return this;
},
emit: function(type) {
customEvent(new BrushEvent(brush, type, dim.output(this.state.selection)), listeners.apply, listeners, [type, this.that, this.args]);
emit: function(type, event) {
var dispatch = this.dispatch,
d = select(this.that).datum();
dispatch.call(
type,
this.that,
new BrushEvent(type, {
sourceEvent: event,
target: brush,
selection: dim.output(this.state.selection),
dispatch
}),
d
);
}
};

function started() {
function started(event) {
if (touchending && !event.touches) return;
if (!filter.apply(this, arguments)) return;

Expand All @@ -345,17 +353,25 @@ function brush(dim) {
shifting = signX && signY && keys && event.shiftKey,
lockX,
lockY,
pointer = event.touches ? toucher(event.changedTouches[0].identifier) : mouse,
point0 = pointer(that),
point = point0,
emit = emitter(that, arguments, true).beforestart();
points = Array.from(event.touches || [event], t => {
const i = t.identifier;
t = pointer(t, that);
t.point0 = t.slice();
t.identifier = i;
return t;
});

if (type === "overlay") {
if (selection) moving = true;
state.selection = selection = [
[w0 = dim === Y ? W : point0[0], n0 = dim === X ? N : point0[1]],
[e0 = dim === Y ? E : w0, s0 = dim === X ? S : n0]
];
const pts = [points[0], points[1] || points[0]];
state.selection = selection = [[
w0 = dim === Y ? W : min(pts[0][0], pts[1][0]),
n0 = dim === X ? N : min(pts[0][1], pts[1][1])
], [
e0 = dim === Y ? E : max(pts[0][0], pts[1][0]),
s0 = dim === X ? S : max(pts[0][1], pts[1][1])
]];
if (points.length > 1) move();
} else {
w0 = selection[0][0];
n0 = selection[0][1];
Expand All @@ -374,6 +390,9 @@ function brush(dim) {
var overlay = group.selectAll(".overlay")
.attr("cursor", cursors[type]);

interrupt(that);
var emit = emitter(that, arguments, true).beforestart();

if (event.touches) {
emit.moved = moved;
emit.ended = ended;
Expand All @@ -388,24 +407,30 @@ function brush(dim) {
dragDisable(event.view);
}

nopropagation();
interrupt(that);
redraw.call(that);
emit.start();

function moved() {
var point1 = pointer(that);
if (shifting && !lockX && !lockY) {
if (Math.abs(point1[0] - point[0]) > Math.abs(point1[1] - point[1])) lockY = true;
else lockX = true;
function moved(event) {
for (const p of event.changedTouches || [event]) {
for (const d of points)
if (d.identifier === p.identifier) d.cur = pointer(p, that);
}
point = point1;
if (shifting && !lockX && !lockY && points.length === 1) {
const point = points[0];
if (abs(point.cur[0] - point[0]) > abs(point.cur[1] - point[1]))
lockY = true;
else
lockX = true;
}
for (const point of points)
if (point.cur) point[0] = point.cur[0], point[1] = point.cur[1];
moving = true;
noevent();
move();
noevent(event);
move(event);
}

function move() {
function move(event) {
const point = points[0], point0 = point.point0;
var t;

dx = point[0] - point0[0];
Expand All @@ -414,20 +439,25 @@ function brush(dim) {
switch (mode) {
case MODE_SPACE:
case MODE_DRAG: {
if (signX) dx = Math.max(W - w0, Math.min(E - e0, dx)), w1 = w0 + dx, e1 = e0 + dx;
if (signY) dy = Math.max(N - n0, Math.min(S - s0, dy)), n1 = n0 + dy, s1 = s0 + dy;
if (signX) dx = max(W - w0, min(E - e0, dx)), w1 = w0 + dx, e1 = e0 + dx;
if (signY) dy = max(N - n0, min(S - s0, dy)), n1 = n0 + dy, s1 = s0 + dy;
break;
}
case MODE_HANDLE: {
if (signX < 0) dx = Math.max(W - w0, Math.min(E - w0, dx)), w1 = w0 + dx, e1 = e0;
else if (signX > 0) dx = Math.max(W - e0, Math.min(E - e0, dx)), w1 = w0, e1 = e0 + dx;
if (signY < 0) dy = Math.max(N - n0, Math.min(S - n0, dy)), n1 = n0 + dy, s1 = s0;
else if (signY > 0) dy = Math.max(N - s0, Math.min(S - s0, dy)), n1 = n0, s1 = s0 + dy;
if (points[1]) {
if (signX) w1 = max(W, min(E, points[0][0])), e1 = max(W, min(E, points[1][0])), signX = 1;
if (signY) n1 = max(N, min(S, points[0][1])), s1 = max(N, min(S, points[1][1])), signY = 1;
} else {
if (signX < 0) dx = max(W - w0, min(E - w0, dx)), w1 = w0 + dx, e1 = e0;
else if (signX > 0) dx = max(W - e0, min(E - e0, dx)), w1 = w0, e1 = e0 + dx;
if (signY < 0) dy = max(N - n0, min(S - n0, dy)), n1 = n0 + dy, s1 = s0;
else if (signY > 0) dy = max(N - s0, min(S - s0, dy)), n1 = n0, s1 = s0 + dy;
}
break;
}
case MODE_CENTER: {
if (signX) w1 = Math.max(W, Math.min(E, w0 - dx * signX)), e1 = Math.max(W, Math.min(E, e0 + dx * signX));
if (signY) n1 = Math.max(N, Math.min(S, n0 - dy * signY)), s1 = Math.max(N, Math.min(S, s0 + dy * signY));
if (signX) w1 = max(W, min(E, w0 - dx * signX)), e1 = max(W, min(E, e0 + dx * signX));
if (signY) n1 = max(N, min(S, n0 - dy * signY)), s1 = max(N, min(S, s0 + dy * signY));
break;
}
}
Expand Down Expand Up @@ -456,12 +486,12 @@ function brush(dim) {
|| selection[1][1] !== s1) {
state.selection = [[w1, n1], [e1, s1]];
redraw.call(that);
emit.brush();
emit.brush(event);
}
}

function ended() {
nopropagation();
function ended(event) {
nopropagation(event);
if (event.touches) {
if (event.touches.length) return;
if (touchending) clearTimeout(touchending);
Expand All @@ -474,10 +504,10 @@ function brush(dim) {
overlay.attr("cursor", cursors.overlay);
if (state.selection) selection = state.selection; // May be set by brush.move (on start)!
if (empty(selection)) state.selection = null, redraw.call(that);
emit.end();
emit.end(event);
}

function keydowned() {
function keydowned(event) {
switch (event.keyCode) {
case 16: { // SHIFT
shifting = signX && signY;
Expand All @@ -504,10 +534,10 @@ function brush(dim) {
}
default: return;
}
noevent();
noevent(event);
}

function keyupped() {
function keyupped(event) {
switch (event.keyCode) {
case 16: { // SHIFT
if (shifting) {
Expand Down Expand Up @@ -543,16 +573,16 @@ function brush(dim) {
}
default: return;
}
noevent();
noevent(event);
}
}

function touchmoved() {
emitter(this, arguments).moved();
function touchmoved(event) {
emitter(this, arguments).moved(event);
}

function touchended() {
emitter(this, arguments).ended();
function touchended(event) {
emitter(this, arguments).ended(event);
}

function initialize() {
Expand Down
6 changes: 1 addition & 5 deletions src/constant.js
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
export default function(x) {
return function() {
return x;
};
}
export default x => () => x;
22 changes: 18 additions & 4 deletions src/event.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
export default function(target, type, selection) {
this.target = target;
this.type = type;
this.selection = selection;
export default function BrushEvent(type, {
sourceEvent,
target,
selection,
dispatch
}) {
Object.defineProperties(this, {
type: {value: type, enumerable: true, configurable: true},
sourceEvent: {value: sourceEvent, enumerable: true, configurable: true},
target: {value: target, enumerable: true, configurable: true},
selection: {value: selection, enumerable: true, configurable: true},
_: {value: dispatch}
});
}

BrushEvent.prototype.on = function() {
var value = this._.on.apply(this._, arguments);
return value === this._ ? this : value;
};
6 changes: 2 additions & 4 deletions src/noevent.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import {event} from "d3-selection";

export function nopropagation() {
export function nopropagation(event) {
event.stopImmediatePropagation();
}

export default function() {
export default function(event) {
event.preventDefault();
event.stopImmediatePropagation();
}
Loading