D3.js 使用不同的svg缩放两个折线图时,其中一个x轴无法放大

D3.js 使用不同的svg缩放两个折线图时,其中一个x轴无法放大,d3.js,D3.js,我尝试用不同的svg创建缩放两个折线图的可视化,并使用d3.csv函数读取每个数据。在本例中,我使用了相同的数据,因为我的目的是检查它是否可以成功缩放。最后,可以成功地放大和缩小数据线,但问题是第二个图表的x轴始终保持不变,即在放大时第二个x轴无法放大 var margin = {top: 20, right: 20, bottom: 50, left: 50}, width = 1000 - margin.left - margin.right, height = 500 -

我尝试用不同的svg创建缩放两个折线图的可视化,并使用d3.csv函数读取每个数据。在本例中,我使用了相同的数据,因为我的目的是检查它是否可以成功缩放。最后,可以成功地放大和缩小数据线,但问题是第二个图表的x轴始终保持不变,即在放大时第二个x轴无法放大

var margin = {top: 20, right: 20, bottom: 50, left: 50},
    width = 1000 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

var bisectDate = d3.bisector(function(d) { return d.dt; }).left,
    formatValue = d3.format(",");

    
var x = d3.scaleLinear()
          .range([0, width]);

var y = d3.scaleLinear()
          .range([height, 0]);
          
var y2 = d3.scaleLinear()
          .range([height, 0]);
          
var priceSeries = d3.line()
    .defined(function(d) { return d.price; })
    .x(function(d) { return x(d.dt); })
    .y(function(d) { return y(d.price); });

svg = d3.select('#chart')
    .append("svg:svg")
    .attr('width', width + margin.left + margin.right)
    .attr('height', height + margin.top + margin.bottom)
    .append("svg:g")
    .attr("id","group")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var focus = svg.append("g") 
               .style("display", "none")    

// Get the data
d3.csv("output5.csv", function(error, data) {
    if (error) throw error;
    
    // format the data
    data.forEach(function(d,i) {
        d.dt = d.total_sfn;
        d.price = d.nSNR;
        
    });

    // Scale the range of the data
    console.log("Date range: ", d3.extent(data, function(d) { return d.dt; }));
    console.log("Price range: ", d3.extent(data, function(d) { return +d.price; }));    
    x.domain([0, d3.max(data, function(d) { return +d.dt; })]);
    y.domain([-d3.max(data, function(d) { return +d.price; }), d3.max(data, function(d) { return +d.price; })]);
    
    var zoom = d3.zoom()
    .scaleExtent([0.75, 15000])
    .translateExtent([[-100000, -100000], [100000, 100000]])
    .on("zoom", zoomed);    
    
    var xAxis = d3.axisBottom(x)
        .ticks((width + 2) / (height + 2) * 5)
        .tickSize(-height)
        .tickPadding(10);
        
    var yAxis = d3.axisRight(y)
        .ticks(5)
        .tickSize(width)
        .tickPadding(- 20 - width);
    
    svg.append("text")             
      .attr("transform",
            "translate(" + (width/2) + " ," + (height + margin.top + 20) + ")")
      .style("font-size","12px")
      .style("font-family", "sans-serif")
      .style("text-anchor", "middle")
      .text("SFN");
      
    svg.append("text")
          .attr("transform", "rotate(-90)")
          .attr("y", 0 - margin.left/1.2)
          .attr("x",0 - (height / 2))
          .attr("dy", "1em")
          .style("font-size","12px")
          .style("text-anchor", "middle")
          .text("SNR");

    var view = svg.append("rect")
        .attr("class", "view")
        .attr("x", 0.5)
        .attr("y", 0.5)
        .attr("width", width - 1)
        .attr("height", height - 1);

    var gX = svg.append("g")
        .attr("class", "axis axis--x")
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis);

    var gY = svg.append("g")
        .attr("class", "axis axis--y")
        .call(yAxis);
        
    svg.append("defs").append("clipPath")
        .attr("id", "clip")
      .append("rect")
        .attr("width", width)
        .attr("height", height);
        
    var chartBody = svg.append("g")
        .attr("clip-path", "url(#clip)");
        
    focus.append("circle")
        .attr("class", "y")
        .style("fill", "none")
        .style("stroke", "steelblue")
        .attr("r", 6)
        .attr("clip-path", "url(#clip)");   
    
    focus.append("text")
        .attr("class", "x-axis")
        .attr("x", 30)
        .attr("y", 20);
        
    focus.append("text")
        .attr("class", "y-axis")
        .attr("x", 40)
        .attr("y", 15);
        
    focus.append("text")
        .attr("dy", ".35em")
        .attr("clip-path", "url(#clip)");
          
    chartBody.append("svg:path")
        .data([data])
        .attr("class", "line")
        .attr("d", priceSeries);
        
    svg.append("rect")
        .attr("id","rect1")
        .attr("width", width)
        .attr("height", height)
        .style("fill", "none")
        .style("pointer-events", "all")
        .on("mouseover", function() { focus.style("display", null); })
        .on("mouseout", function() { focus.style("display", "none"); })
        .on("mousemove", mousemove);
        
    svg.append("g")
          .attr("transform", "translate(0," + height + ")")
          .call(d3.axisBottom(x).ticks(0));
          
    svg.append("g")
      .call(d3.axisLeft(y).ticks(0));
     
    d3.select("#rect1").call(zoom);
    
    d3.select("button").on("click", resetted1);
    
    function mouseDate(scale) {
        var g = d3.select("#group")._groups[0][0]
        var x0 = scale.invert(d3.mouse(g)[0]),
        i = bisectDate(data, x0, 1),
        d0 = data[i - 1],
        d1 = data[i],
        d = x0 - d0.date > d1.date - x0 ? d1 : d0;
    return d;
    }
    
    function mousemove() {
        var transform = d3.zoomTransform(this);
        var xt = transform.rescaleX(x), yt = transform.rescaleY(y);
        d = mouseDate(xt);
        focus.select(".y")
            .attr('cx', function() {
                                    return transform.applyX(x(d.dt));
                                })
            .attr('cy', function() {
                                    return y(d.price);
                                }); 
                            

        
        
        focus.select("text")
             .text(Math.floor(d.dt))
             .attr('x', function() {
                                    return transform.applyX(x(d.dt))+10;
             })
             .attr('y', function() {
                                    return y(d.price)+5;
             });
        

    }
    
    function zoomed() {
      
      gX.call(xAxis.scale(d3.event.transform.rescaleX(x)));
      //gY.call(yAxis.scale(d3.event.transform.rescaleY(y)));
      var t = d3.event.transform, xt = t.rescaleX(x), yt = t.rescaleY(y)
      svg.select(".line")
         .attr("d",priceSeries.x(function(d) { return xt(d.dt);}));
      svg2.select(".line")
         .attr("d",priceSeries.x(function(d) { return xt(d.dt);}));
                            
        focus.select("circle.y")
             .classed("zoomed", true)
             .attr("id","one")
             .attr('cx', function() {return t.applyX(x(d.dt)); })
             .attr('cy', function() {return t.applyY(y(d.price)); });               
        focus.select("text")
             .text(d.price)
             .attr('x', function() { return t.applyX(x(d.dt))+10;})
             .attr('y',function() {return t.applyY(y(d.price)); });
    }
    
    function resetted1() {
      d3.select("#rect1")
          .call(zoom.transform, d3.zoomIdentity);

      
    }   
});

svg2 = d3.select('#chart2')
    .append("svg:svg")
    .attr('width', width + margin.left + margin.right)
    .attr('height', height + margin.top + margin.bottom)
    .append("svg:g")
    .attr("id","group")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var focus2 = svg.append("g") 
               .style("display", "none")    
d3.csv("output5.csv", function(error, data2) {
    if (error) throw error;
    
    // format the data
    data2.forEach(function(d,i) {
        d.dt = d.total_sfn;
        d.price = d.nSNR;
        
    });

    // Scale the range of the data
    console.log("Date range: ", d3.extent(data2, function(d) { return d.dt; }));
    console.log("Price range: ", d3.extent(data2, function(d) { return +d.price; }));   
    x.domain([0, d3.max(data2, function(d) { return +d.dt; })]);
    y.domain([-d3.max(data2, function(d) { return +d.price; }), d3.max(data2, function(d) { return +d.price; })]);
    
    var zoom = d3.zoom()
    .scaleExtent([0.75, 15000])
    .translateExtent([[-100000, -100000], [100000, 100000]])
    .on("zoom", zoomed);    
    
    var xAxis = d3.axisBottom(x)
        .ticks((width + 2) / (height + 2) * 5)
        .tickSize(-height)
        .tickPadding(10);
        
    var yAxis = d3.axisRight(y)
        .ticks(5)
        .tickSize(width)
        .tickPadding(- 20 - width);
    
    svg2.append("text")             
      .attr("transform",
            "translate(" + (width/2) + " ," + (height + margin.top + 20) + ")")
      .style("font-size","12px")
      .style("font-family", "sans-serif")
      .style("text-anchor", "middle")
      .text("SFN");
      
    svg2.append("text")
          .attr("transform", "rotate(-90)")
          .attr("y", 0 - margin.left/1.2)
          .attr("x",0 - (height / 2))
          .attr("dy", "1em")
          .style("font-size","12px")
          .style("text-anchor", "middle")
          .text("SNR");

    var view = svg2.append("rect")
        .attr("class", "view")
        .attr("x", 0.5)
        .attr("y", 0.5)
        .attr("width", width - 1)
        .attr("height", height - 1);

    var gX = svg2.append("g")
        .attr("class", "axis axis--x")
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis);

    var gY = svg2.append("g")
        .attr("class", "axis axis--y")
        .call(yAxis);
        
    svg2.append("defs").append("clipPath")
        .attr("id", "clip")
      .append("rect")
        .attr("width", width)
        .attr("height", height);
        
    var chartBody = svg2.append("g")
        .attr("clip-path", "url(#clip)");
        
    focus2.append("circle")
        .attr("class", "y")
        .style("fill", "none")
        .style("stroke", "steelblue")
        .attr("r", 6)
        .attr("clip-path", "url(#clip)");   
    
    focus2.append("text")
        .attr("class", "x-axis")
        .attr("x", 30)
        .attr("y", 20);
        
    focus2.append("text")
        .attr("class", "y-axis")
        .attr("x", 40)
        .attr("y", 15);
        
    focus2.append("text")
        .attr("dy", ".35em")
        .attr("clip-path", "url(#clip)");
          
    chartBody.append("svg2:path")
        .data([data2])
        .attr("class", "line")
        .attr("d", priceSeries);
        
    svg2.append("rect")
        .attr("id","rect2")
        .attr("width", width)
        .attr("height", height)
        .style("fill", "none")
        .style("pointer-events", "all")
        .on("mouseover", function() { focus2.style("display", null); })
        .on("mouseout", function() { focus2.style("display", "none"); })

        
    svg2.append("g")
          .attr("transform", "translate(0," + height + ")")
          .call(d3.axisBottom(x).ticks(0));
          
    svg2.append("g")
      .call(d3.axisLeft(y).ticks(0));
     
    //d3.select("#rect2").call(zoom);
    
    //d3.select("button").on("click", resetted2);
    
    function mouseDate(scale) {
        var g = d3.select("#group")._groups[0][0]
        var x0 = scale.invert(d3.mouse(g)[0]),
        i = bisectDate(data2, x0, 1),
        d0 = data2[i - 1],
        d1 = data2[i],
        d = x0 - d0.dt > d1.dt - x0 ? d1 : d0;
    return d;
    }
    
    function mousemove() {
        var transform = d3.zoomTransform(this);
        var xt = transform.rescaleX(x), yt = transform.rescaleY(y);
        d = mouseDate(xt);
        focus2.select(".y")
            .attr('cx', function() {
                                    return transform.applyX(x(d.dt));
                                })
            .attr('cy', function() {
                                    return y(d.price);
                                }); 
                            

        
        
        focus2.select("text")
             .text(Math.floor(d.dt))
             .attr('x', function() {
                                    return transform.applyX(x(d.dt))+10;
             })
             .attr('y', function() {
                                    return y(d.price)+5;
             });
        

    }
    
    function zoomed() {
      
      gX.call(xAxis.scale(d3.event.transform.rescaleX(x)));
      var t = d3.event.transform, xt = t.rescaleX(x), yt = t.rescaleY(y)
      svg2.select(".line")
         .attr("d",priceSeries.x(function(d) { return xt(d.dt);}));
      svg.select(".line")
         .attr("d",priceSeries.x(function(d) { return xt(d.dt);}));

        focus2.select("circle.y")
             .classed("zoomed", true)
             .attr("id","one")
             .attr('cx', function() {return t.applyX(x(d.dt)); })
             .attr('cy', function() {return t.applyY(y(d.price)); });               
        focus2.select("text")
             .text(d.price)
             .attr('x', function() { return t.applyX(x(d.dt))+10;})
             .attr('y',function() {return t.applyY(y(d.price)); });
    }
    
    function resetted2() {
      d3.select("#rect2").transition()
          .duration(750)
          .call(zoom.transform, d3.zoomIdentity);
      d3.select("#rect1").transition()
          .duration(750)
          .call(zoom.transform, d3.zoomIdentity);

      
    }
    
});

这是很多代码。请将其减少到a并确保其可运行。您可以将数据粘贴为JSON,或者像我粘贴一些CSV内容那样使用
d3.csvParse
,然后删除对
d3.CSV