Charts: Unify d3 zoom handler

This commit is contained in:
Aysam Guerler
2014-06-14 00:25:38 -04:00
parent e0449af979
commit f2df472c23
7 changed files with 95 additions and 157 deletions
@@ -8,18 +8,10 @@ return function(chart) {
var settings = chart.settings;
var plot_config = {
enablePlugins: true,
seriesColors: function() {
var colors = [];
var colorScale = d3.scale.category20();
for (var i = 0; i < chart.groups.length; i++) {
colors.push(colorScale(i));
}
return colors;
}(),
seriesColors: d3.scale.category20().range(),
seriesDefaults: {
renderer : $.jqplot.LineRenderer,
//lineWidth : 1, // Width of the line in pixels.
//lineWidth : 1, // Width of the line in pixels.
shadow : false, // show shadow or not.
showLine : true, // whether to render the line segments or not.
@@ -80,9 +80,21 @@ return Backbone.View.extend(
.call(d3chart);
// add zoom/pan handler
var zoom_mode = chart.definition.zoomable;
if (zoom_mode == 'axis' || zoom_mode == 'svg') {
self._addZoom(d3chart, canvas, zoom_mode);
if (chart.definition.zoomable) {
// clip edges
if (d3chart.clipEdge) {
d3chart.clipEdge(true);
}
// add zoom
Tools.addZoom({
xAxis : d3chart.xAxis,
yAxis : d3chart.yAxis,
yDomain: d3chart.yDomain,
xDomain: d3chart.xDomain,
redraw : function() { d3chart.update() },
svg : canvas
});
}
// refresh on window resize
@@ -95,84 +107,11 @@ return Backbone.View.extend(
return true;
},
// add zoom handler
_addZoom: function(nvd3_model, svg, zoom_mode) {
// clip edges
if (nvd3_model.clipEdge) {
nvd3_model.clipEdge(true);
}
// get canvas dimensions
var width = parseInt(svg.style('width'));
var height = parseInt(svg.style('height'));
// create x scales
var x_domain = nvd3_model.xAxis.scale().domain();
var x = d3.scale.linear()
.domain(x_domain)
.range([0, width]);
// create y scale
var y_domain = nvd3_model.yAxis.scale().domain();
var y = d3.scale.linear()
.domain(y_domain)
.range([height, 0]);
// min/max boundaries
var x_boundary = nvd3_model.xScale().domain().slice();
var y_boundary = nvd3_model.yScale().domain().slice();
// create d3 zoom handler
var d3zoom = d3.behavior.zoom();
// fix domain
function fixDomain(domain, boundary) {
domain[0] = Math.max(domain[0], boundary[0]);
domain[1] = Math.min(domain[1], boundary[1]);
return domain;
};
// zoom event handler
function zoomed() {
if (zoom_mode == 'axis') {
nvd3_model.xDomain(fixDomain(x.domain(), x_boundary));
nvd3_model.yDomain(fixDomain(y.domain(), y_boundary));
nvd3_model.update();
} else {
var translate = d3.event.translate;
svg.select('.nvd3').attr("transform", "translate(" + translate + ") scale(" + d3.event.scale + ")");
}
};
// zoom event handler
function unzoomed() {
if (zoom_mode == 'axis') {
nvd3_model.xDomain(x_boundary);
nvd3_model.yDomain(y_boundary);
nvd3_model.update();
d3zoom.scale(1);
d3zoom.translate([0,0]);
} else {
var translate = d3.event.translate;
svg.select('.nvd3').attr("transform", "translate([0,0]) scale(1)");
}
};
// initialize wrapper
d3zoom.x(x)
.y(y)
.scaleExtent([1, 10])
.on("zoom", zoomed);
// add handler
svg.call(d3zoom).on("dblclick.zoom", unzoomed);
},
// create axes formatting
_makeAxes: function(d3chart, groups, settings) {
// result
var categories = Tools.makeCategories(groups);
// make axes
function makeAxis (id) {
Tools.makeAxis({
@@ -2,9 +2,8 @@ define(['plugin/charts/forms/default'], function(config_default) {
return $.extend(true, {}, config_default, {
title : 'Heat map',
//execute : 'heatmap',
category : 'Others',
query_limit : 5,
query_limit : 1,
library : 'Custom',
tag : 'div',
keywords : 'small',
@@ -56,7 +56,13 @@ return Backbone.View.extend({
this.redraw();
// add zoom
this._addZoom();
Tools.addZoom({
xAxis : this.xAxis,
yAxis : this.yAxis,
redraw : function() { self.redraw() },
svg : d3.select('#' + this.canvas_id),
discrete : true
});
// return
return true;
@@ -183,65 +189,6 @@ return Backbone.View.extend({
.attr('y', -boxHeight/2 + boxHeight);
},
// add zoom handler
_addZoom: function() {
// link this
var self = this;
// min/max boundaries
var x_boundary = this.xScale.domain().slice();
var y_boundary = this.yScale.domain().slice();
// create d3 zoom handler
var d3zoom = d3.behavior.zoom();
// fix domain
function fixDomain(domain, boundary) {
domain[0] = parseInt(domain[0]);
domain[1] = parseInt(domain[1]);
domain[0] = Math.max(domain[0], boundary[0]);
domain[1] = Math.max(0, Math.min(domain[1], boundary[1]));
return domain;
};
// zoom event handler
function zoomed() {
var yDomain = fixDomain(self.yScale.domain(), y_boundary);
if (Math.abs(yDomain[1]-yDomain[0]) > 30) {
self.yScale.domain(yDomain);
self.gyAxis.call(self.yAxis);
}
var xDomain = fixDomain(self.xScale.domain(), x_boundary);
if (Math.abs(xDomain[1]-xDomain[0]) > 30) {
self.xScale.domain(xDomain);
self.gxAxis.call(self.xAxis);
}
self.redraw();
};
// zoom event handler
function unzoomed() {
self.xScale.domain(x_boundary);
self.yScale.domain(y_boundary);
self.redraw();
d3zoom.scale(1);
d3zoom.translate([0,0]);
};
// initialize wrapper
d3zoom.x(this.xScale)
.y(this.yScale)
.scaleExtent([1, 10])
.on('zoom', zoomed);
// clip edges
//svg.clipEdge(true);
// add handler
var svg = d3.select('#' + this.canvas_id);
svg.call(d3zoom).on('dblclick.zoom', unzoomed);
},
// create axes formatting
_makeAxes: function(d3chart, settings) {
// make axes
@@ -259,8 +206,8 @@ return Backbone.View.extend({
}
});
};
//makeAxis('x');
//makeAxis('y');
makeAxis('x');
makeAxis('y');
},
// handle error
@@ -293,7 +293,70 @@ function makeAxis (options) {
}
}
};
// add zoom handler
function addZoom(options) {
// parameters
var yAxis = options.yAxis;
var xAxis = options.xAxis;
var xDomain = options.xDomain || xAxis.scale().domain;
var yDomain = options.yDomain || yAxis.scale().domain;
var redraw = options.redraw;
var svg = options.svg;
var discrete = options.discrete;
// scales
var xScale = xAxis.scale();
var yScale = yAxis.scale();
// min/max boundaries
var x_boundary = xScale.domain().slice();
var y_boundary = yScale.domain().slice();
// create d3 zoom handler
var d3zoom = d3.behavior.zoom();
// ensure nice axis
xScale.nice();
yScale.nice();
// fix domain
function fixDomain(domain, boundary) {
if (discrete) {
domain[0] = parseInt(domain[0]);
domain[1] = parseInt(domain[1]);
}
domain[0] = Math.max(domain[0], boundary[0]);
domain[1] = Math.max(0, Math.min(domain[1], boundary[1]));
return domain;
};
// zoom event handler
function zoomed() {
yDomain(fixDomain(yScale.domain(), y_boundary));
xDomain(fixDomain(xScale.domain(), x_boundary));
redraw();
};
// zoom event handler
function unzoomed() {
xDomain(x_boundary);
yDomain(y_boundary);
redraw();
d3zoom.scale(1);
d3zoom.translate([0,0]);
};
// initialize wrapper
d3zoom.x(xScale)
.y(yScale)
.scaleExtent([1, 10])
.on('zoom', zoomed);
// add handler
svg.call(d3zoom).on('dblclick.zoom', unzoomed);
};
// return
return {
panelHelper : panelHelper,
@@ -302,7 +365,8 @@ return {
makeSeries : makeSeries,
getDomains : getDomains,
mapCategories : mapCategories,
makeAxis : makeAxis
makeAxis : makeAxis,
addZoom : addZoom
}
});
@@ -11174,8 +11174,8 @@ nv.models.scatter = function() {
pointPaths.exit().remove();
pointPaths
.attr('d', function(d) {
if (d.data.length === 0)
return 'M 0 0'
if (!d || !d.data || d.data.length === 0)
return 'M 0 0';
else
return 'M' + d.data.join('L') + 'Z';
});
@@ -29,9 +29,6 @@
${h.javascript_link( app_root + "plugins/jqplot/jquery.jqplot.js" )}
${h.javascript_link( app_root + "plugins/jqplot/jquery.jqplot.plugins.js" )}
## dc
${h.javascript_link( app_root + "plugins/dc/crossfilter.js" )}
## load merged/minified code
${h.javascript_link( app_root + "build-app.js" )}