Last active
August 29, 2015 14:06
-
-
Save boxdot/7162dd85f3055d6b5de5 to your computer and use it in GitHub Desktop.
A working example of a graph, which can be zoomed/panned and also resized. Resizing does not change the scale of the graph but changes the viewport. Therefore domain and range of the axes should also be changed, which does not fully works with zoom behaviour of d3. The latter changes the corresponding scale, but changing the scales does not auto…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<title>Programmatic Change of Domain/Range and Zoom/Pan</title> | |
<link rel="stylesheet" href="http://code.jquery.com/ui/1.11.1/themes/black-tie/jquery-ui.css"> | |
<style> | |
html, body { | |
margin: 1em; | |
} | |
body { | |
font: 10px sans-serif; | |
shape-rendering: crispEdges; | |
} | |
div { | |
margin: 2em; | |
width: 500px; | |
height: 500px; | |
} | |
svg { | |
fill: none; | |
pointer-events: all; | |
} | |
.axis path, .axis line { | |
stroke-width: 1px; | |
stroke: lightslategray; | |
fill: none; | |
} | |
.axis text { | |
fill: lightslategray; | |
} | |
.graph .body circle { | |
fill: black; | |
} | |
</style> | |
</head> | |
<body> | |
<button>redraw</button> | |
<div></div> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script> | |
<script src="http://code.jquery.com/ui/1.11.1/jquery-ui.min.js"></script> | |
<script> | |
var margin = { left: 35, right: 15, top: 30, bottom: 15 } | |
var div = d3.select('body > div') | |
var width = parseInt(div.style('width')) - margin.left - margin.right | |
var height = parseInt(div.style('height')) - margin.top - margin.bottom | |
var x = d3.scale.linear() | |
.domain([0, 2000]) | |
.range([margin.left, width + margin.left]) | |
var x0 = x.copy() | |
var y = d3.scale.linear() | |
.domain([-100, 100]) | |
.range([height + margin.top, margin.top]) | |
var y0 = y.copy() | |
var x_axis = d3.svg.axis() | |
.scale(x) | |
.orient('top') | |
var y_axis = d3.svg.axis() | |
.scale(y) | |
.orient('left') | |
var zoom = d3.behavior.zoom() | |
.x(x) | |
.y(y) | |
.scaleExtent([0.2, 8]) | |
.on('zoom', zoomed) | |
// markup: | |
// | |
// svg | |
// meta | |
// axes | |
// clip | |
// body[clip] | |
// graph | |
var svg = div.append('svg') | |
.attr('width', width + margin.left + margin.right) | |
.attr('height', height + margin.top + margin.bottom) | |
.call(zoom) | |
var meta = svg.append('g') | |
.attr('class', 'meta') | |
var x_axis_el = meta.append('g') | |
.attr('class', 'x axis') | |
.attr('transform', 'translate(0, '+ (margin.top - 5) +')') | |
.call(x_axis) | |
var y_axis_el = meta.append('g') | |
.attr('class', 'y axis') | |
.attr('transform', 'translate(' + (margin.left - 5) + ', 0)') | |
.call(y_axis) | |
var clip = meta.append('clipPath') | |
.attr('id', 'clip') | |
.append('rect') | |
.attr('x', margin.left) | |
.attr('y', margin.top) | |
.attr('width', width + margin.right) | |
.attr('height', height + margin.bottom) | |
var graph = svg.append('g') | |
.attr('class', 'graph') | |
.style('fill', 'none') | |
.attr('clip-path', 'url(#clip)') | |
var body = graph.append('g') | |
.style('fill', 'none') | |
.attr('class', 'body') | |
var data | |
generate_data() | |
draw() | |
$(div).resizable({ | |
stop: resize | |
}); | |
d3.select('button').on('click', function() { | |
var v = zoom.translate() | |
var s = zoom.scale() | |
zoom.translate([0, 0]).scale(1) | |
generate_data() | |
draw() | |
zoom.translate(v).scale(s) | |
}) | |
function generate_data() { | |
data = d3.range(2000).map(function(i) { | |
return Math.random()*200-100 | |
}) | |
} | |
function draw() { | |
var circles = body.selectAll("circle") | |
.data(data) | |
circles.enter().append("circle") | |
.attr("r", 2.5) | |
.attr('cx', function(d, i) { return x(i) }) | |
.attr('cy', function(d, i) { return y(d) }) | |
circles | |
.attr("r", 2.5) | |
.attr('cx', function(d, i) { return x(i) }) | |
.attr('cy', function(d, i) { return y(d) }) | |
} | |
function zoomed() { | |
body.attr('transform', 'translate(' + d3.event.translate + ')'+ | |
'scale(' + d3.event.scale + ')'); | |
x_axis_el.call(x_axis) | |
y_axis_el.call(y_axis) | |
} | |
function resize(event, ui) { | |
var full_w = ui.size.width | |
var full_h = ui.size.height | |
// new width and height | |
w = full_w - margin.left - margin.right | |
h = full_h - margin.top - margin.bottom | |
svg.attr('width', full_w).attr('height', full_h) | |
clip.attr('width', w).attr('height', h) | |
var xr = x0.range() | |
var xd = x0.domain() | |
xr[1] = w + margin.left | |
xd[1] = x0.invert(xr[1]) | |
x.domain(xd).range(xr) | |
var yr = y0.range() | |
var yd = y0.domain() | |
yr[0] = h + margin.top | |
yd[0] = y0.invert(yr[0]) | |
y.domain(yd).range(yr) | |
var v = zoom.translate() | |
var s = zoom.scale() | |
zoom.x(x).y(y) | |
zoom.translate(v).scale(s) | |
x_axis_el.call(x_axis) | |
y_axis_el.call(y_axis) | |
width = w | |
height = h | |
} | |
</script> | |
</body> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment