Search code examples
javascriptcssd3.jssvgzooming

d3js - Zoom linearGradient hoizontally; hiding the vertical scaling


I am building a d3js chart that plots some dots on a gradient scale of agree to disagree. I need it to be able to zoom and pan and I have all of that working except for a rectangle holding a linearGradient. The gradient zooms just as I need it, but it scales up both horizontally AND vertically, expanding past the original 20px height:

enter image description here

Or shrinking excessively:

enter image description here

I tried to use a clip path which is clearly not working, it seems that the clip path scales with the gradient. How can I clamp the rectangle to the axis and keep it the same size?

Here is my block

Thank you!!


Solution

  • There are two primary challenges from what I can see:

    • the rectangle filled with the gradient scales on the y axis as you note.
    • the clip path isn't working as intended.

    Let's drop the clip path, that'll make things a bit easier. Secondly, let's not scale the rectangle at all when we zoom (we can keep the translate that is applied though).


    Now that I've destroyed what we had, let's build it back up.

    Instead of scaling the rectangle with transform(scale()) let's modify its width directly. If d3.event.transform.k is the factor at which we were scaling (both x and y), let's just modify the width of the rectangle. Instead of:

    gradientScale
      .attr("transform","translate("+d3.event.transform.x+","+(height- spacer*3)+")scale("+d3.event.transform.k+")");
    

    Let's use:

    gradientScale
      .attr("transform", "translate( " +d3.event.transform.x+ " , " + (height - spacer*3) + ")")
      .attr("width", width * d3.event.transform.k);
    

    By removing the scaling, the above won't warp any coordinates, which won't lead to stretching of the y axis. It doesn't modify any y coordiantes, so the bar stays where it is height wise with the same height.

    It does modify the width - by the same amount we were scaling it before (the rectangle's width at k = 1 is width). This achieves the stretching of the scale as we zoom in. The x translate factor is unchanged.

    Here's a bl.ock of the modified code.

    My initial thought before looking closely was to try a completely different approach. So, for comparison, here's a completely different approach modifying the axis itself.