简体   繁体   中英

D3 v4 ajust zoom to center

Is there an obvious d3 V4 equivalent to the V3 d3.behavior.zoom()

.center([width / 2, height / 2]) syntax.

(I've searched around, and most working examples of manual zooming etc run in V3... and the API docs don't mention it as best I can tell. )

I am trying to add manual zoomin/out buttons, using the example:

https://bl.ocks.org/mbostock/7ec977c95910dd026812 as a base, but with V4.

Edit

Harpal show me an example working in d3 v4, but i dont know how apply to my project.

So there is my script:

//-----------------------------------Variables ---------------------------------------------------------------------------
            //Alto y ancho
            var w = 500;
            var h = 500;
            var padding = 0;
            var coundata= 0;
            var maxx = 0.30
            var minx = -0.30
            var maxy = 6
            var miny = -6

//-----------------------------------CREAR GRAFICO SCATTER ----------------------------------------------------------------
            //Funciones de escala
            var xScale = d3.scaleLinear()
                                 .domain([minx, maxx])
                                 .range([padding, h]);

            var yScale = d3.scaleLinear()
                                 .domain([miny, maxy])
                                 .range([h, padding]);

            var rScale = d3.scaleLinear()
                                 .domain([0,5])
                                 .range([2, 6]);

            //Eje x
            var xAxis = d3.axisBottom()
                .scale(xScale);;

            //Eje y
            var yAxis = d3.axisLeft()
                .scale(yScale);

            //Crear el elemento svg
            var svg = d3.select("#linegraph")
                        .append("svg")
                        .attr("width", w)
                        .attr("height", h);

            //Colores
            grupo = svg.append("svg:g");

            var c2 = grupo.append("rect")
                .attr("width", (w/2) - padding)             
                .attr("height", (h/2)- padding)
                .attr("transform", "translate("+w/2+","+padding+")")
                .attr("fill", "rgba(0, 255, 0, 0.3)");

            var c1 = grupo.append("rect")
                .attr("width", (w/2) - padding)             
                .attr("height", (h/2)- padding)
                .attr("transform", "translate("+padding+","+padding+")")
                .attr("fill", "rgba(255, 255, 0, 0.3)");


            var c3 = grupo.append("rect")
                .attr("width", (w/2) - padding)             
                .attr("height", (h/2)- padding)
                .attr("transform", "translate("+padding+","+h/2+")")
                .attr("fill", "rgba(255, 0, 0, 0.3)");

            var c4 = grupo.append("rect")
                .attr("width", (w/2) - padding)             
                .attr("height", (h/2)- padding)
                .attr("transform", "translate("+w/2+","+h/2+")")
                .attr("fill", "rgba(255, 165, 0, 0.3)");


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

            //Añadimos el eje x
            var gX = svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(0," + (h/2) + ")")
                .call(xAxis);

            //Añadimos el eje y
            var gY = svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(" + (w/2)  + ",0)")
                .call(yAxis);

            nowData = []
            var grupo2 = svg.append("svg:g");


            //Creamos los puntos
            var datos = grupo2.selectAll("circle")
               .data(nowData)
               .enter()            
               .append("circle")                           
               .attr("cx", function(d) {
                    return xScale(d[0]);
               })
               .attr("cy", function(d) {
                    return yScale(d[1]);
               })
               .attr("r", function(d) {
                    return 5;
               })
                .append("svg:title") 
                    .text(function(d) {return "Valor x: "+d[0] +"\n Valor y :"+d[1]; })                     

               ;
            var grupoLineas = svg.append("svg:g");
//--------------------------------- ZOOM---------------------------------------------------------------------              
            var zoom = d3.zoom()                            
                // Don’t allow the zoomed area to be bigger than the viewport.
                .scaleExtent([1, Infinity])
                .translateExtent([[0, 0], [w, h]])
                .extent([[0, 0], [w, h]])
                .on("zoom", zoomed);                


            grupo.style("transform-origin","50% 50% 0");
            grupo2.style("transform-origin","50% 50% 0");
            grupoLineas.style("transform-origin","50% 50% 0");
            svg.style("transform-origin","50% 50% 0");
            gX.style("transform-origin","50% 50% 0");
            gY.style("transform-origin","50% 50% 0");

            svg.call(zoom);
            function zoomed() {         
                svg.attr("transform", d3.event.transform);
                gX.call(xAxis.scale(d3.event.transform.rescaleX(xScale)));
                gY.call(yAxis.scale(d3.event.transform.rescaleY(yScale)));                      
                grupo2.attr("transform",d3.event.transform);
                grupoLineas.attr("transform",d3.event.transform);
                grupo.attr("transform",d3.event.transform);         
            }   
            function resetted() {
              svg.transition()
                  .duration(750)
                  .call(zoom.transform, d3.zoomIdentity);
            }
            d3.select("#zoom_in")
                .on("click",function(){
                    zoom.scaleBy(svg, 2);
                })
            d3.select("#zoom_out")
                .on("click",function(){
                    zoom.scaleBy(svg, 0.5);
                })              
//---------------------------------------Funcion mostrarDatos ----------------------------------------------------------            
            function mostrarDatos(){
                nowData=[]
                grupo2.selectAll("circle")
                    .data(nowData)
                    .exit()
                    .remove()
                if($("#eae").prop('checked') == true)               
                {   
                    nowData.push(eaepunt1[coundata])                                    
                    grupo2.selectAll("circle")

                }               

                if($("#arab").prop('checked') == true)
                {
                    nowData.push(arabpunt1[coundata])                                                               

                }                                           
                console.log(nowData)

                grupo2.selectAll("circle")
                   .data(nowData)
                   .enter()            
                   .append("circle")                           
                   .attr("cx", function(d) {
                        return xScale(d[0]);
                   })
                   .attr("cy", function(d) {
                        return yScale(d[1]);
                   })
                   .attr("r", function(d) {
                        return 5;
                   })
                    .append("svg:title") 
                        .text(function(d) {return "Valor x: "+d[0] +"\n Valor y :"+d[1]; })                
                   ;
            }
            $("#eae").change(function()
            {
                mostrarDatos();
            });

            $("#arab").change(function()
            {
                mostrarDatos()
            }); 

I apply the ("transform-origin","50% 50% 0"); but it not works correctly

You can do it 2 things

  • First, apply zoom directly to center:

      var zoom = d3.zoom() // Don't allow the zoomed area to be bigger than the viewport. .scaleExtent([1, Infinity]) .translateExtent([[0, 0], [w, h]]) .extent([[0, 0], [w, h]]) .on("zoom", zoomed); grupopadre.style("transform-origin", "50% 50% 0"); svg.call(zoom); function zoomed() { grupopadre .style('transform', 'scale(' + d3.event.transform.k + ')'); } 
  • Second, center the graphic when you zoom out:

      var zoom = d3.zoom() // Don't allow the zoomed area to be bigger than the viewport. .scaleExtent([1, Infinity]) .translateExtent([[0, 0], [w, h]]) .extent([[0, 0], [w, h]]) .on("zoom", zoomed); grupopadre.style("transform-origin", "50% 50% 0"); svg.call(zoom); function zoomed() { grupopadre.attr("transform",d3.event.transform); } 

    You need create a group with all svg content in this.

Not sure if that answers your question, but here you can see similar example in V4: https://bl.ocks.org/mbostock/db6b4335bf1662b413e7968910104f0f

You can find detailed documentation on the zoom behavior in D3 API Docs for version 4 and I don't think there exist a more "obvious" way that is not documented: https://github.com/d3/d3/blob/master/API.md#zooming-d3-zoom

You could add transform-origin to a style attribute to the element on which you perform the zoom:

.style("transform-origin", "50% 50% 0")

EDIT

Working Plnkr here

I think it is just d3.zoom() now

var zoom = d3.zoom()
            // Don’t allow the zoomed area to be bigger than the viewport.
            .scaleExtent([1, Infinity])
            .translateExtent([[0, 0], [width, height]])
            .extent([[0, 0], [width, height]])
            .on("zoom", zoomed);

Here is the solution I found:

function zoomed() {
    var scale = d3.event.transform.k; 
    grupopadre.attr("transform", "translate(" + 0 + ")scale(" + scale + ")");
}

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