I have zoom and pan working for the x axis but I'd like to add panning for the y axis. I tried using d3.behavior.zoom
and d3.event.translate[1]
to get the y translation value and use that but the translate value changes when zooming happens so while click-dragging does pan the y axis, zooming also pans the y axis (in a non-intuitive way).
I also tried using two d3.behavior.zoom
instances, one for the x axis and one for the y axis, but only the last one added is called on zoom events.
Here's an example that works for zoom and pan in the x direction that I'd also like to add y panning too (but not y zooming):
var x = d3.scale.linear()
.domain([0, 800])
.range([0, 800]);
var y = d3.scale.linear()
.domain([0, 800])
.range([0, 800]);
var rectangleSelector = d3.select('svg')
.append('g')
.selectAll('rect')
.data([[0, 0], [50, 50], [100, 100]])
.enter()
.append('rect')
.attr('fill', 'black')
.attr('x', d => x(d[0]))
.attr('y', d => y(d[1]))
.attr('width', d => x(d[0] + 40) - x(d[0]))
.attr('height', d => y(40));
d3.select('svg')
.call(d3.behavior.zoom().x(x).on('zoom', () => {
rectangleSelector
.attr('x', d => x(d[0]))
.attr('y', d => y(d[1]))
.attr('width', d => x(d[0] + 40) - x(d[0]))
.attr('height', d => y(40));
}));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg width="800" height="800"></svg>
In this example I attempt to use the y value from d3.event.translate[1]
and it works for dragging but the undesired behavior is that depending on where the user's mouse is zooming also changes the translate value for the y axis.
var x = d3.scale.linear()
.domain([0, 800])
.range([0, 800]);
var y = d3.scale.linear()
.domain([0, 800])
.range([0, 800]);
var rectangleSelector = d3.select('svg')
.append('g')
.selectAll('rect')
.data([[0, 0], [50, 50], [100, 100]])
.enter()
.append('rect')
.attr('fill', 'black')
.attr('x', d => x(d[0]))
.attr('y', d => y(d[1]))
.attr('width', d => x(d[0] + 40) - x(d[0]))
.attr('height', d => y(40));
d3.select('svg')
.call(d3.behavior.zoom().x(x).on('zoom', () => {
var translateY = d3.event.translate[1];
rectangleSelector
.attr('x', d => x(d[0]))
.attr('y', d => y(d[1] + translateY))
.attr('width', d => x(d[0] + 40) - x(d[0]))
.attr('height', d => y(40));
}));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg width="800" height="800"></svg>
d3.behavior.zoom()
is chainable withx()
andy()
; I'm only specifyingx()
and so the zoom behavior only changes the x axis. But it still reports translate values for the y axis, which I'd like to use to translate that axis--the issue is that they're affected by zooming, not just panning. – Beaud3.behavior.zoom()
instances there and they're each tied to a specific area of the screen--I tried two instances on the same area of the screen and only the last instance applied received events (though maybe twog
elements with the same dimensions could each receive one?) – Beaurect
elements each the size of the canvas, making themfill: white
andfill-opacity: 0
(so they're transparent) and attached a zoom behavior to each, and even withpointer-events: all
only the last addedd3.behavior.zoom()
fires events. – Beau