Skip to content

Commit

Permalink
Allow a reference point to be specified.
Browse files Browse the repository at this point in the history
  • Loading branch information
mbostock committed Aug 9, 2019
1 parent 6bf7b7c commit fbd16ed
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 22 deletions.
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ Alternatively, use [*zoom*.filter](#zoom_filter) for greater control over which

Applying the zoom behavior also sets the [-webkit-tap-highlight-color](https://developer.apple.com/library/mac/documentation/AppleApplications/Reference/SafariWebContent/AdjustingtheTextSize/AdjustingtheTextSize.html#//apple_ref/doc/uid/TP40006510-SW5) style to transparent, disabling the tap highlight on iOS. If you want a different tap highlight color, remove or re-apply this style after applying the drag behavior.

<a href="#zoom_transform" name="zoom_transform">#</a> <i>zoom</i>.<b>transform</b>(<i>selection</i>, <i>transform</i>) [<>](https://github.com/d3/d3-zoom/blob/master/src/zoom.js#L76 "Source")
<a href="#zoom_transform" name="zoom_transform">#</a> <i>zoom</i>.<b>transform</b>(<i>selection</i>, <i>transform</i>[, <i>point</i>]) [<>](https://github.com/d3/d3-zoom/blob/master/src/zoom.js#L76 "Source")

If *selection* is a selection, sets the [current zoom transform](#zoomTransform) of the selected elements to the specified *transform*, instantaneously emitting start, zoom and end [events](#zoom-events). If *selection* is a transition, defines a “zoom” tween to the specified *transform* using [d3.interpolateZoom](https://github.com/d3/d3-interpolate#interpolateZoom), emitting a start event when the transition starts, zoom events for each tick of the transition, and then an end event when the transition ends (or is interrupted). The *transform* may be specified either as a [zoom transform](#zoom-transforms) or as a function that returns a zoom transform. If a function, it is invoked for each selected element, being passed the current datum `d` and index `i`, with the `this` context as the current DOM element.
If *selection* is a selection, sets the [current zoom transform](#zoomTransform) of the selected elements to the specified *transform*, instantaneously emitting start, zoom and end [events](#zoom-events). If *selection* is a transition, defines a “zoom” tween to the specified *transform* using [d3.interpolateZoom](https://github.com/d3/d3-interpolate/blob/master/README.md#interpolateZoom), emitting a start event when the transition starts, zoom events for each tick of the transition, and then an end event when the transition ends (or is interrupted). The transition will attempt to minimize the visual movement around the specified *point*; if the *point* is not specified, it defaults to the center of the viewport [extent](#zoom_extent). The *transform* may be specified either as a [zoom transform](#zoom-transforms) or as a function that returns a zoom transform; similarly, the *point* may be specified either as a two-element array [*x*, *y*] or a function that returns such an array. If a function, it is invoked for each selected element, being passed the current datum `d` and index `i`, with the `this` context as the current DOM element.

This function is typically not invoked directly, and is instead invoked via [*selection*.call](https://github.com/d3/d3-selection#selection_call) or [*transition*.call](https://github.com/d3/d3-transition#transition_call). For example, to reset the zoom transform to the [identity transform](#zoomIdentity) instantaneously:

Expand All @@ -125,17 +125,17 @@ This method requires that you specify the new zoom transform completely, and doe

If *selection* is a selection, [translates](#transform_translate) the [current zoom transform](#zoomTransform) of the selected elements by *x* and *y*, such that the new *t<sub>x1</sub>* = *t<sub>x0</sub>* + *kx* and *t<sub>y1</sub>* = *t<sub>y0</sub>* + *ky*. If *selection* is a transition, defines a “zoom” tween translating the current transform. This method is a convenience method for [*zoom*.transform](#zoom_transform). The *x* and *y* translation amounts may be specified either as numbers or as functions that returns numbers. If a function, it is invoked for each selected element, being passed the current datum `d` and index `i`, with the `this` context as the current DOM element.

<a href="#zoom_translateTo" name="zoom_translateTo">#</a> <i>zoom</i>.<b>translateTo</b>(<i>selection</i>, <i>x</i>, <i>y</i>) [<>](https://github.com/d3/d3-zoom/blob/master/src/zoom.js#L119 "Source")
<a href="#zoom_translateTo" name="zoom_translateTo">#</a> <i>zoom</i>.<b>translateTo</b>(<i>selection</i>, <i>x</i>, <i>y</i>[, <i>p</i>]) [<>](https://github.com/d3/d3-zoom/blob/master/src/zoom.js#L119 "Source")

If *selection* is a selection, [translates](#transform_translate) the [current zoom transform](#zoomTransform) of the selected elements such that the specified position ⟨*x*,*y*⟩ appears at the center of the [viewport extent](#zoom_extent). The new *t<sub>x</sub>* = *c<sub>x</sub>* - *kx* and *t<sub>y</sub>* = *c<sub>y</sub>* - *ky*, where ⟨*c<sub>x</sub>*,*c<sub>y</sub>* is the center. If *selection* is a transition, defines a “zoom” tween translating the current transform. This method is a convenience method for [*zoom*.transform](#zoom_transform). The *x* and *y* coordinates may be specified either as numbers or as functions that returns numbers. If a function, it is invoked for each selected element, being passed the current datum `d` and index `i`, with the `this` context as the current DOM element.
If *selection* is a selection, [translates](#transform_translate) the [current zoom transform](#zoomTransform) of the selected elements such that the given position ⟨*x*,*y*⟩ appears at given point *p*. The new *t<sub>x</sub>* = *p<sub>x</sub>* - *kx* and *t<sub>y</sub>* = *p<sub>y</sub>* - *ky*. If *p* is not specified, it defaults to the center of the viewport [extent](#zoom_extent). If *selection* is a transition, defines a “zoom” tween translating the current transform. This method is a convenience method for [*zoom*.transform](#zoom_transform). The *x* and *y* coordinates may be specified either as numbers or as functions that returns numbers; similarly the *p* point may be specified either as a two-element array [*p<sub>x</sub>*,*p<sub>y</sub>*] or a function. If a function, it is invoked for each selected element, being passed the current datum `d` and index `i`, with the `this` context as the current DOM element.

<a href="#zoom_scaleBy" name="zoom_scaleBy">#</a> <i>zoom</i>.<b>scaleBy</b>(<i>selection</i>, <i>k</i>) [<>](https://github.com/d3/d3-zoom/blob/master/src/zoom.js#L91 "Source")
<a href="#zoom_scaleBy" name="zoom_scaleBy">#</a> <i>zoom</i>.<b>scaleBy</b>(<i>selection</i>, <i>k</i>[, <i>p</i>]) [<>](https://github.com/d3/d3-zoom/blob/master/src/zoom.js#L91 "Source")

If *selection* is a selection, [scales](#transform_scale) the [current zoom transform](#zoomTransform) of the selected elements by *k*, such that the new *k₁* = *k₀k*. If *selection* is a transition, defines a “zoom” tween translating the current transform. This method is a convenience method for [*zoom*.transform](#zoom_transform). The *k* scale factor may be specified either as numbers or as functions that returns numbers. If a function, it is invoked for each selected element, being passed the current datum `d` and index `i`, with the `this` context as the current DOM element.
If *selection* is a selection, [scales](#transform_scale) the [current zoom transform](#zoomTransform) of the selected elements by *k*, such that the new *k₁* = *k₀k*. The reference point *p* does move. If *p* is not specified, it defaults to the center of the viewport [extent](#zoom_extent). If *selection* is a transition, defines a “zoom” tween translating the current transform. This method is a convenience method for [*zoom*.transform](#zoom_transform). The *k* scale factor may be specified either as a number or a function that returns a number; similarly the *p* point may be specified either as a two-element array [*p<sub>x</sub>*,*p<sub>y</sub>*] or a function. If a function, it is invoked for each selected element, being passed the current datum `d` and index `i`, with the `this` context as the current DOM element.

<a href="#zoom_scaleTo" name="zoom_scaleTo">#</a> <i>zoom</i>.<b>scaleTo</b>(<i>selection</i>, <i>k</i>) [<>](https://github.com/d3/d3-zoom/blob/master/src/zoom.js#L99 "Source")
<a href="#zoom_scaleTo" name="zoom_scaleTo">#</a> <i>zoom</i>.<b>scaleTo</b>(<i>selection</i>, <i>k</i>[, <i>p</i>]) [<>](https://github.com/d3/d3-zoom/blob/master/src/zoom.js#L99 "Source")

If *selection* is a selection, [scales](#transform_scale) the [current zoom transform](#zoomTransform) of the selected elements to *k*, such that the new *k₁* = *k*. If *selection* is a transition, defines a “zoom” tween translating the current transform. This method is a convenience method for [*zoom*.transform](#zoom_transform). The *k* scale factor may be specified either as numbers or as functions that returns numbers. If a function, it is invoked for each selected element, being passed the current datum `d` and index `i`, with the `this` context as the current DOM element.
If *selection* is a selection, [scales](#transform_scale) the [current zoom transform](#zoomTransform) of the selected elements to *k*, such that the new *k₁* = *k*. The reference point *p* does move. If *p* is not specified, it defaults to the center of the viewport [extent](#zoom_extent). If *selection* is a transition, defines a “zoom” tween translating the current transform. This method is a convenience method for [*zoom*.transform](#zoom_transform). The *k* scale factor may be specified either as a number or a function that returns a number; similarly the *p* point may be specified either as a two-element array [*p<sub>x</sub>*,*p<sub>y</sub>*] or a function. If a function, it is invoked for each selected element, being passed the current datum `d` and index `i`, with the `this` context as the current DOM element.

<a href="#zoom_constrain" name="zoom_constrain">#</a> <i>zoom</i>.<b>constrain</b>([<i>constrain</i>]) [<>](https://github.com/d3/d3-zoom/blob/master/src/zoom.js#403 "Source")

Expand Down
3 changes: 2 additions & 1 deletion src/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,6 @@ export var identity = new Transform(1, 0, 0);
transform.prototype = Transform.prototype;

export default function transform(node) {
return node.__zoom || identity;
while (!node.__zoom) if (!(node = node.parentNode)) return identity;
return node.__zoom;
}
26 changes: 13 additions & 13 deletions src/zoom.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,11 @@ export default function() {
.style("-webkit-tap-highlight-color", "rgba(0,0,0,0)");
}

zoom.transform = function(collection, transform) {
zoom.transform = function(collection, transform, point) {
var selection = collection.selection ? collection.selection() : collection;
selection.property("__zoom", defaultTransform);
if (collection !== selection) {
schedule(collection, transform);
schedule(collection, transform, point);
} else {
selection.interrupt().each(function() {
gesture(this, arguments)
Expand All @@ -95,23 +95,23 @@ export default function() {
}
};

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

zoom.scaleTo = function(selection, k) {
zoom.scaleTo = function(selection, k, p) {
zoom.transform(selection, function() {
var e = extent.apply(this, arguments),
t0 = this.__zoom,
p0 = centroid(e),
p0 = p == null ? centroid(e) : typeof p === "function" ? p.apply(this, arguments) : p,
p1 = t0.invert(p0),
k1 = typeof k === "function" ? k.apply(this, arguments) : k;
return constrain(translate(scale(t0, k1), p0, p1), e, translateExtent);
});
}, p);
};

zoom.translateBy = function(selection, x, y) {
Expand All @@ -123,16 +123,16 @@ export default function() {
});
};

zoom.translateTo = function(selection, x, y) {
zoom.translateTo = function(selection, x, y, p) {
zoom.transform(selection, function() {
var e = extent.apply(this, arguments),
t = this.__zoom,
p = centroid(e);
return constrain(identity.translate(p[0], p[1]).scale(t.k).translate(
p0 = p == null ? centroid(e) : typeof p === "function" ? p.apply(this, arguments) : p;
return constrain(identity.translate(p0[0], p0[1]).scale(t.k).translate(
typeof x === "function" ? -x.apply(this, arguments) : -x,
typeof y === "function" ? -y.apply(this, arguments) : -y
), e, translateExtent);
});
}, p);
};

function scale(transform, k) {
Expand All @@ -149,7 +149,7 @@ export default function() {
return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2];
}

function schedule(transition, transform, center) {
function schedule(transition, transform, point) {
transition
.on("start.zoom", function() { gesture(this, arguments).start(); })
.on("interrupt.zoom end.zoom", function() { gesture(this, arguments).end(); })
Expand All @@ -158,7 +158,7 @@ export default function() {
args = arguments,
g = gesture(that, args),
e = extent.apply(that, args),
p = center || centroid(e),
p = point == null ? centroid(e) : typeof point === "function" ? point.apply(that, args) : point,
w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]),
a = that.__zoom,
b = typeof transform === "function" ? transform.apply(that, args) : transform,
Expand Down

0 comments on commit fbd16ed

Please sign in to comment.