Zoomable treemap in D3 v4
Asked Answered
C

2

8

I'm trying to add zoom behaviour to my treemap in D3 v4 based on these examples: 1 and 2. It's built with HTML elements, rather than SVG and I have made it responsive by using percentage instead of pixel units.

It works great so far but now I'd like to zoom in to individual cells with a click until the last child has been reached. Then the click would go back to the root of the tree.

Here's my code so far: http://codepen.io/znak/pen/qapRkQ

I'm struggling with the zoom function that works in V4 and it's all over the place:

function zoom(d) {

    console.log('clicked: ' + d.data.name);

    x.domain([d.x0, d.x1]);
    y.domain([d.y0, d.y1]);

    var t = d3.transition()
        .duration(800)
        .ease(d3.easeCubicOut);

    chart
        .merge(cell)
        .transition(t)
        .style("left", function(d) { return x(d.x0) + "%"; })
        .style("top", function(d) { return y(d.y0) + "%"; })
        .style("width", function(d) { return x(d.x1 - d.x0) + "%"; })
        .style("height", function(d) { return y(d.y1 - d.y0) + "%"; });

    node = d; //?
    d3.event.stopPropagation(); //?
}

How do I update and transition elements with D3 v4?

Thanks for any hints!

Carcinomatosis answered 25/10, 2016 at 13:3 Comment(5)
Cool visualization!Pollaiuolo
d3.cubicOut is not a valid easing function, your code throws an exception.Simian
Doh! Thanks! It started transitioning but still far from perfect.Carcinomatosis
Did you acheive this yet ?Equilibrist
Nope. Couldn't get any help with this so far.Carcinomatosis
C
0

After a long break I've noticed the mistake – wrongly placed parentheses here:

.style("width", function(d) { return x(d.x1 - d.x0) + "%"; })
.style("height", function(d) { return y(d.y1 - d.y0) + "%"; });

It should be:

.style("width", function(d) { return x(d.x1) - x(d.x0) + "%"; })
.style("height", function(d) { return y(d.y1) - y(d.y0) + "%"; });

Now the zoom functions properly.

DEMO

Carcinomatosis answered 12/6, 2018 at 10:4 Comment(0)
K
0

Your problem isn't the zoom functionality, but the level-1 elements are in front of level-2 elements so when you click on it it's trying to zoom to the same level-1 element.

I think the easiest solution would be to assign a class with or style the level-1 element with pointer-events: none when it's zoomed. This makes it impossible to click on and therefore when the user clicks it falls through to the child, which will then activate the zoom.

Just be sure to remove the class or style when you reset the tree!

pointer-events is supported in all major browsers (Chrome, FF, IE11+) except Opera Mini. See browser compatibility on caniuse.com. If you need to support IE less than 11 or Opera Mini, you could manipulate the z-index or hide the parent.

Essentially, the parent is blocking the children from being selected, so if you resolve that you should be good!

Kelle answered 11/11, 2016 at 23:53 Comment(1)
Yes, the order/visibility of elements needs sorting out but if you try clicking different cells at the only clickable depth only first cell appears to zoom correctly and others produce a mess. To me it has something to do with passing the recalculated x,y values on the selection in transform function in the wrong way but I run out of ideas.Carcinomatosis
C
0

After a long break I've noticed the mistake – wrongly placed parentheses here:

.style("width", function(d) { return x(d.x1 - d.x0) + "%"; })
.style("height", function(d) { return y(d.y1 - d.y0) + "%"; });

It should be:

.style("width", function(d) { return x(d.x1) - x(d.x0) + "%"; })
.style("height", function(d) { return y(d.y1) - y(d.y0) + "%"; });

Now the zoom functions properly.

DEMO

Carcinomatosis answered 12/6, 2018 at 10:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.