Skip to content

Commit

Permalink
Merge branch 'release'
Browse files Browse the repository at this point in the history
  • Loading branch information
mbostock committed Jul 10, 2011
2 parents 3c8fabb + c1d7fbc commit 1885dd5
Show file tree
Hide file tree
Showing 33 changed files with 718 additions and 329 deletions.
1 change: 1 addition & 0 deletions Makefile
Expand Up @@ -38,6 +38,7 @@ d3.core.js: \
src/core/min.js \
src/core/max.js \
src/core/sum.js \
src/core/quantile.js \
src/core/zip.js \
src/core/bisect.js \
src/core/first.js \
Expand Down
207 changes: 127 additions & 80 deletions d3.behavior.js
Expand Up @@ -2,111 +2,158 @@
// TODO unbind zoom behavior?
// TODO unbind listener?
d3.behavior.zoom = function() {

var x = 0,
y = 0,
z = 0,
listeners = [],
pan,
zooming;
panning,
zooming,
locations = {}, // identifier -> location
last = 0,
target,
targuments,
event = d3.dispatch("zoom");

// mousewheel events are totally broken!
// https://bugs.webkit.org/show_bug.cgi?id=40441
// not only that, but Chrome and Safari differ in re. to acceleration!
var div = d3.select("body").append("div")
.style("visibility", "hidden")
.style("top", 0)
.style("height", 0)
.style("width", 0)
.style("overflow-y", "scroll")
.append("div")
.style("height", "2000px")
.node().parentNode;

function zoom() {
var container = this
.on("mousedown", mousedown)
.on("mousewheel", mousewheel)
.on("DOMMouseScroll", mousewheel)
.on("dblclick", mousewheel);
this
.on("mousedown.zoom", mousedown)
.on("mousewheel.zoom", mousewheel)
.on("DOMMouseScroll.zoom", dblclick)
.on("dblclick.zoom", dblclick)
.on("touchstart.zoom", touchstart);

d3.select(window)
.on("mousemove", mousemove)
.on("mouseup", mouseup);
.on("mousemove.zoom", mousemove)
.on("mouseup.zoom", mouseup)
.on("touchmove.zoom", touchmove)
.on("touchend.zoom", touchup);
}

function mousedown(d, i) {
pan = {
x0: x - d3.event.clientX,
y0: y - d3.event.clientY,
target: this,
data: d,
index: i
};
function location(point) {
return [point[0] - x, point[1] - y, z];
}

// snapshot the target, data and index for subsequent dispatch
function start() {
target = this;
targuments = arguments;
}

// Note: Since we don't rotate, it's possible for the touches to become
// slightly detached from their original positions. Thus, we recompute the
// touch points on touchend as well as touchstart!
function touchup() {
var touches = d3.svg.touches(target),
i = -1,
n = touches.length,
touch;
while (++i < n) locations[(touch = touches[i]).identifier] = location(touch);
return touches;
}

function touchstart() {
start.apply(this, arguments);
var touches = touchup(),
touch,
now = Date.now();

// doubletap detection
if ((touches.length === 1) && (now - last < 300)) {
var touch = touches[0];
zoomto(1 + Math.floor(z), touch, locations[touch.identifier]);
}
last = now;
}

function touchmove() {
var touches = d3.svg.touches(target);
switch (touches.length) {

// single-touch pan
case 1: {
var touch = touches[0];
zoomto(z, touch, locations[touch.identifier]);
break;
}

// double-touch pan + zoom
case 2: {
var p0 = touches[0],
p1 = touches[1],
p2 = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2],
l0 = locations[p0.identifier],
l1 = locations[p1.identifier],
l2 = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2, l0[2]];
zoomto(Math.log(d3.event.scale) / Math.LN2 + l0[2], p2, l2);
break;
}
}
}

function mousedown() {
start.apply(this, arguments);
panning = location(d3.svg.mouse(target));
d3.event.preventDefault();
window.focus(); // TODO focusableParent
window.focus();
}

function mousemove() {
zooming = null;
if (pan) {
x = d3.event.clientX + pan.x0;
y = d3.event.clientY + pan.y0;
dispatch.call(pan.target, pan.data, pan.index);
}
if (panning) zoomto(z, d3.svg.mouse(target), panning);
}

function mouseup() {
if (pan) {
if (panning) {
mousemove();
pan = null;
panning = null;
}
}

// mousewheel events are totally broken!
// https://bugs.webkit.org/show_bug.cgi?id=40441
// not only that, but Chrome and Safari differ in re. to acceleration!
function mousewheel() {
start.apply(this, arguments);

var outer = d3.select("body").append("div")
.style("visibility", "hidden")
.style("position", "absolute")
.style("top", "-3000px")
.style("height", 0)
.style("overflow-y", "scroll")
.append("div")
.style("height", "2000px")
.node().parentNode;
// store starting mouse location
if (!zooming) zooming = location(d3.svg.mouse(target));

function mousewheel(d, i) {
var e = d3.event;

// initialize the mouse location for zooming (to avoid drift)
if (!zooming) {
var p = d3.svg.mouse(this.nearestViewportElement || this);
zooming = {
x0: x,
y0: y,
z0: z,
x1: x - p[0],
y1: y - p[1]
};
// detect the pixels that would be scrolled by this wheel event
var e = d3.event, delta;
try {
div.scrollTop = 1000;
div.dispatchEvent(e);
delta = 1000 - div.scrollTop;
} catch (error) {
delta = e.wheelDelta || -e.detail;
}

// adjust zoom level
if (e.type === "dblclick") {
z = e.shiftKey ? Math.ceil(z - 1) : Math.floor(z + 1);
} else {
var delta = e.wheelDelta || -e.detail;
if (delta) {
try {
outer.scrollTop = 1000;
outer.dispatchEvent(e);
delta = 1000 - outer.scrollTop;
} catch (error) {
// Derp! Hope for the best?
}
delta *= .005;
}
z += delta;
}
zoomto(delta * .005 + z, d3.svg.mouse(target), zooming);
}

// adjust x and y to center around mouse location
var k = Math.pow(2, z - zooming.z0) - 1;
x = zooming.x0 + zooming.x1 * k;
y = zooming.y0 + zooming.y1 * k;
function dblclick() {
start.apply(this, arguments);
var mouse = d3.svg.mouse(target);
zoomto(d3.event.shiftKey ? Math.ceil(z - 1) : Math.floor(z + 1), mouse, location(mouse));
}

// dispatch redraw
dispatch.call(this, d, i);
function zoomto(z1, x0, x1) {
var k = Math.pow(2, (z = z1) - x1[2]);
x = x0[0] - k * x1[0];
y = x0[1] - k * x1[1];
dispatch();
}

function dispatch(d, i) {
function dispatch() {
var o = d3.event, // Events can be reentrant (e.g., focus).
k = Math.pow(2, z);

Expand All @@ -126,16 +173,16 @@ d3.behavior.zoom = function() {
}

try {
for (var j = 0, m = listeners.length; j < m; j++) {
listeners[j].call(this, d, i);
}
event.zoom.dispatch.apply(target, targuments);
} finally {
d3.event = o;
}

o.preventDefault();
}

zoom.on = function(type, listener) {
if (type == "zoom") listeners.push(listener);
event[type].add(listener);
return zoom;
};

Expand Down
2 changes: 1 addition & 1 deletion d3.behavior.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions d3.chart.js
Expand Up @@ -290,11 +290,11 @@ function d3_chart_boxWhiskers(d) {
}

function d3_chart_boxQuartiles(d) {
var n = d.length;
return [.25, .5, .75].map(function(q) {
q *= n;
return ~~q === q ? (d[q] + d[q + 1]) / 2 : d[Math.round(q)];
});
return [
d3.quantile(d, .25),
d3.quantile(d, .5),
d3.quantile(d, .75)
];
}
// Chart design based on the recommendations of Stephen Few. Implementation
// based on the work of Clint Ivy, Jamie Love, and Jason Davies.
Expand Down

0 comments on commit 1885dd5

Please sign in to comment.