简体   繁体   中英

Unable to understand d3js zoom functionality

The following SIMPLE :) code gives following error. Please help me what mistake I am making to ZOOM on onClick on the Circle ?

Similarly I will be very thankful if someone can give some idea that if i want to zoom to 3rd Circle DIRECTLY without clicking on it; what should I do ?

ERROR: Uncaught TypeError: Cannot read property 'apply' of undefined
    at qr.call (d3.min.js:2)
    at SVGCircleElement.clicked (index.html:52)
    at SVGCircleElement.<anonymous> (d3.min.js:2)

And here is the code.

    <!DOCTYPE html>
    <html>

    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="initial-scale=1,maximum-scale=1" />
        <title>Zoom & Pan</title>
        <link rel="stylesheet" type="text/css" href="styles.css" />
        <script type="text/javascript" src="d3.min.js"></script>

        <style type="text/css">

        </style>
    </head>

    <body>


        <script type="text/javascript">
            var width = 600, height = 350;
            var data = [
                { "r": 10, "cx": 100, "cy": 150 },
                { "r": 30, "cx": 200, "cy": 150 },
                { "r": 15, "cx": 300, "cy": 150 }

            ];
            var svg = d3.select("body").append("svg")
                .attr("width", width)
                .attr("height", height)
                .call( 
                        d3.zoom()
                        .scaleExtent([1, 7])
                        .on("zoom", zoom)
                );

            const g = svg.append("g");

            g.selectAll("circle")
                .data(data)
                .enter()
                .append("circle")
                //.attr("fill", function (d) { return d.color; })
                .attr("fill", (d, i) => d3.interpolateRainbow(i / 3))
                .on("click", clicked)
                .attr("r", function (d) { return d.r; })
                .attr("cx", function (d) { return d.cx; })
                .attr("cy", function (d) { return d.cy; });


            function clicked(d,i,nodes) {
                console.log(nodes);

                svg.transition().duration(750).call(
                    zoom.transform,
                    d3.zoomIdentity.translate(width / 2, height / 2).scale(40).translate(-d.cx, -d.cy),
                    d3.mouse(svg.node())
                );

            }

            function zoom() {
                g.attr("transform", d3.event.transform);
            }

        </script>

    </body>

    </html>

The issue is that zoom.transform is not a thing. You have created a function called zoom , if that is important then you'll need to create another variable called something else, eg zoomer, probably in window scope, like width and height :

var zoomer = d3.zoom();

Then in your click handler change zoom.transform to zoomer.transform :

function clicked(d,i,nodes) {
  console.log(nodes);

  svg.transition().duration(750).call(
    zoomer.transform, //change here
    d3.zoomIdentity.translate(width / 2, height / 2).scale(40).translate(-d.cx, -d.cy),
    d3.mouse(svg.node())
  );
}

If you don't need the zoom function, then delete that and create the zoom variable like the zoomer one above and don't change the click handler.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM