Skip to content

Commit

Permalink
Rename “view” to “transform”.
Browse files Browse the repository at this point in the history
I think this better describes what it is, and affords some similarity with the
Canvas 2D transform (albeit limited to scale and translate).
  • Loading branch information
mbostock committed May 18, 2016
1 parent 36ec2b3 commit 3de9018
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 77 deletions.
3 changes: 2 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export {version} from "./build/package";
export {default as zoom, view as zoomView} from "./src/zoom";
export {default as zoom} from "./src/zoom";
export {default as zoomTransform} from "./src/transform";
4 changes: 2 additions & 2 deletions src/event.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export default function ZoomEvent(type, view) {
this.type = type;
this.scale = view._k;
this.translate = [view._x, view._y];
this.scale = view.k;
this.translate = [view.x, view.y];
}
29 changes: 29 additions & 0 deletions src/transform.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export function Transform(k, x, y) {
this.k = k;
this.x = x;
this.y = y;
}

Transform.prototype = {
constructor: Transform,
apply: function(point) {
return [point[0] * this.k + this.x, point[1] * this.k + this.y];
},
invert: function(location) {
return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k];
},
scale: function(k) {
return new Transform(this.k * k, this.x, this.y);
},
translate: function(x, y) {
return new Transform(this.k, this.x + this.k * x, this.y + this.k * y);
}
};

export var identity = new Transform(1, 0, 0);

transform.prototype = Transform.prototype;

export default function transform(node) {
return node == null ? identity : node.__zoom;
}
32 changes: 0 additions & 32 deletions src/view.js

This file was deleted.

83 changes: 41 additions & 42 deletions src/zoom.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,7 @@ import {event, customEvent, select, mouse} from "d3-selection";
import {interrupt, transition} from "d3-transition";
import constant from "./constant";
import ZoomEvent from "./event";
import View from "./view";

var identity = new View(1, 0, 0);

view.prototype = View.prototype;

export function view(node) {
return node == null ? identity : node.__zoom;
}
import {Transform, identity} from "./transform";

// Ignore horizontal scrolling.
// Ignore right-click, since that should open the context menu.
Expand Down Expand Up @@ -57,36 +49,46 @@ export default function(started) {
}

// TODO Enforce scaleExtent.
zoom.view = function(selection, view) {
zoom.transform = function(selection, transform) {
if (selection instanceof transition) {
schedule(selection, view, centerPoint);
schedule(selection, transform, centerPoint);
} else {
selection
.interrupt()
.each(emitStart)
.property("__zoom", view)
.property("__zoom", transform)
.each(emitZoom)
.each(emitEnd);
}
};

zoom.scaleBy = function(selection, k) {
zoom.scaleTo(selection, function() {
return this.__zoom._k * (typeof k === "function" ? k.apply(this, arguments) : k);
var k0 = this.__zoom.k,
k1 = typeof k === "function" ? k.apply(this, arguments) : k;
return k0 * k1;
});
};

zoom.scaleTo = function(selection, s) {
zoom.view(selection, function() {
return this.__zoom.scaleTo(
Math.max(scaleMin, Math.min(scaleMax, typeof s === "function" ? s.apply(this, arguments) : s)),
centerPoint || centroid.apply(this, arguments)
);
zoom.scaleTo = function(selection, k) {
zoom.transform(selection, function() {
var p0 = centerPoint || (p0 = size.apply(this, arguments), [p0[0] / 2, p0[1] / 2]),
p1 = this.__zoom.invert(p0),
k1 = typeof k === "function" ? k.apply(this, arguments) : k;
return translate(scale(this.__zoom, k1), p0, p1);
});
};

function scale(transform, k) {
return new Transform(Math.max(scaleMin, Math.min(scaleMax, k)), transform.x, transform.y);
}

function translate(transform, p0, p1) {
return p1 = transform.apply(p1), new Transform(transform.k, transform.x + p0[0] - p1[0], transform.y + p0[1] - p1[1]);
}

// TODO Enforce scaleExtent.
function schedule(transition, view, center) {
function schedule(transition, transform, center) {
transition
.on("start.zoom", emitStart)
.on("interrupt.zoom end.zoom", emitEnd)
Expand All @@ -97,11 +99,11 @@ export default function(started) {
p = center || [s[0] / 2, s[1] / 2],
w = Math.max(s[0], s[1]),
a = that.__zoom,
b = typeof view === "function" ? view.apply(that, args) : view,
i = interpolateZoom(a.invert(p).concat(w / a._k), b.invert(p).concat(w / b._k));
b = typeof transform === "function" ? transform.apply(that, args) : transform,
i = interpolateZoom(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k));
return function(t) {
if (t === 1) that.__zoom = b; // Avoid rounding error on end.
else { var l = i(t), k = w / l[2]; that.__zoom = new View(k, p[0] - l[0] * k, p[1] - l[1] * k); }
else { var l = i(t), k = w / l[2]; that.__zoom = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k); }
emitZoom.apply(that, args);
};
});
Expand All @@ -123,18 +125,13 @@ export default function(started) {
customEvent(new ZoomEvent(type, that.__zoom), listeners.apply, listeners, [type, that, args]);
}

function centroid() {
var s = size.apply(this, arguments);
return [s[0] / 2, s[1] / 2];
}

// TODO Clean this up.
function wheeled() {
if (!filter.apply(this, arguments)) return;

var that = this,
args = arguments,
view = that.__zoom;
transform = that.__zoom;

if (wheelTimer) clearTimeout(wheelTimer);

Expand All @@ -143,24 +140,24 @@ export default function(started) {
// over the duration of the gesture: if you zoom in a lot and then zoom out,
// we want you to return to the original location exactly.
else {
if (centerPoint) centerLocation = view.invert(centerPoint);
mouseLocation = view.invert(mousePoint = mouse(that));
if (centerPoint) centerLocation = transform.invert(centerPoint);
mouseLocation = transform.invert(mousePoint = mouse(that));
interrupt(that), emitStart.apply(that, args);
}

view = view.scaleTo(Math.max(scaleMin, Math.min(scaleMax, view._k * Math.pow(2, -event.deltaY * (event.deltaMode ? 120 : 1) / 500))));
transform = scale(transform, transform.k * Math.pow(2, -event.deltaY * (event.deltaMode ? 120 : 1) / 500));

// There may be a concurrent mousedown-mouseup gesture! Scaling around an
// explicit center changes the mouse location, so must update the mouse
// location that was captured on mousedown.
if (centerPoint) {
view = view.translateTo(centerPoint, centerLocation);
mouseLocation = view.invert(mousePoint);
transform = translate(transform, centerPoint, centerLocation);
mouseLocation = transform.invert(mousePoint);
} else {
view = view.translateTo(mousePoint, mouseLocation);
transform = translate(transform, mousePoint, mouseLocation);
}

that.__zoom = view;
that.__zoom = transform;
event.preventDefault();
wheelTimer = setTimeout(wheelidled, wheelDelay);
emitZoom.apply(that, args);
Expand All @@ -187,7 +184,7 @@ export default function(started) {
interrupt(that), emitStart.apply(that, args);

function mousemoved() {
that.__zoom = that.__zoom.translateTo(mousePoint = mouse(that), mouseLocation);
that.__zoom = translate(that.__zoom, mousePoint = mouse(that), mouseLocation);
if (centerPoint) centerLocation = that.__zoom.invert(centerPoint);
emitZoom.apply(that, args);
}
Expand All @@ -200,11 +197,13 @@ export default function(started) {

function dblclicked() {
if (!filter.apply(this, arguments)) return;
var center = centerPoint || mouse(this),
scale = this.__zoom._k * (event.shiftKey ? 0.5 : 2),
view = this.__zoom.scaleTo(Math.max(scaleMin, Math.min(scaleMax, scale)), center);
if (duration > 0) select(this).transition().duration(duration).call(schedule, view, center);
else this.__zoom = view;
var t0 = this.__zoom,
p0 = centerPoint || mouse(this),
p1 = t0.invert(p0),
k1 = t0.k * (event.shiftKey ? 0.5 : 2),
t1 = translate(scale(t0, k1), p0, p1);
if (duration > 0) select(this).transition().duration(duration).call(schedule, t1, p0);
else this.__zoom = t1;
}

function touchstarted() {
Expand Down

0 comments on commit 3de9018

Please sign in to comment.