Reputation: 1097
I have a d3 graph where I'd like one specific object to remain the same height after zoom is called (so it still extends the height of the chart), but the width zooms in and out accordingly.
Essentially, I just want the zoom to affect it horizontally (x). Other items need to remain a two-dimensional zoom.
Here is the whole project: https://codepen.io/lahesty/pen/XYoyxV?editors=0001 The blue rectangles are what I'm talking about. Lines 295-319
Here is my zoom function:
function zoomed() {
svg.selectAll("path.line")
.attr("transform", d3.event.transform);
svg.selectAll("g.anomrect")
.attr("transform", d3.event.transform);
svg.selectAll("g.dot")
.attr("transform", d3.event.transform);
gX.call(xAxis.scale(d3.event.transform.rescaleX(x)))
gY.call(yAxis.scale(d3.event.transform.rescaleY(y)))}
Calling zoom:
var zoom = d3.zoom()
.scaleExtent([1, 40])
.on("zoom", zoomed);
Object(s) I'm zooming on:
var anamoly = svg.append('g')
.attr('clip-path', 'url(#clipper)')
.selectAll('.anomrect')
.data(anamoly_data, function(d, i) { return d[0];
}).enter().append("g").attr("class", "anomrect");
anamoly.selectAll('.anomrect')
.data(function(d) { return d; }, function(d_, i_) { return i_})
.enter()
.append('rect')
.attr("id", function(d,i){return id_list[i%id_list.length]})
.attr("height", height)
.attr("width", function(d) { return x(d.ended_at)-x(d.started_at); })
.attr("x", function(d) { return x(d.started_at); })
.attr("y", 0)
Should I adjust "height" on the object? Or perhaps my event.transform in my zoom function?
Thank you
Upvotes: 1
Views: 281
Reputation: 102174
For either lines (actually paths), rectangles or circles, use just d3.event.translate.x
for translating the x position only, and use d3.event. translate.k
also for scaling the x position only:
selection.attr("transform",
"translate(" + d3.event.transform.x + ",0) scale(" + d3.event.transform.k + ",1)");
So, for restricting the zoom to the x coordinate only for all paths, rectangles and circles it will be:
function zoomed() {
svg.selectAll("path.line").attr("transform",
"translate(" + d3.event.transform.x + ",0) scale(" + d3.event.transform.k + ",1)");
svg.selectAll("g.anomrect").attr("transform",
"translate(" + d3.event.transform.x + ",0) scale(" + d3.event.transform.k + ",1)");
svg.selectAll("g.dot").attr("transform",
"translate(" + d3.event.transform.x + ",0) scale(" + d3.event.transform.k + ",1)");
gX.call(xAxis.scale(d3.event.transform.rescaleX(x)));
};
Notice that here I'm removing the y axis call.
As you mentioned in your question, if you want to restrict the zoom to just one selection, change just that respective selection (and keep the y axis call).
Here is the updated CodePen (restricting the zoom for all selections): https://codepen.io/anon/pen/djyyPQ?editors=0011
Upvotes: 1