d3.js带缩放的多线图:线错误

d3.js Multi-line graph with zoom : line error

本文关键字:错误 js 缩放 d3      更新时间:2023-09-26

这是我的"多线图4:Toggle"版本http://bl.ocks.org/d3noob/e99a762017060ce81c76但我遇到了一些问题,请帮忙。

最初的图形是正确的,

  • 缩放后,该线将变为同时使用线和旋转数据的线

我认为是缩放后的功能做得不对,当我使用"d.value"时,浏览器会说"d.is not define"

以下是代码:

// https://github.com/mbostock/d3/wiki/Ordinal-Scales#category10
var colors = d3.scale.category10(); 
var margin = {top: 20, right: 30, bottom: 80, left: 85},
    width = 900 - margin.left - margin.right,
    height = 570 - margin.top - margin.bottom;
// Kind of defining the length and the directions of the axis    
var x = d3.scale.linear()
    .range([0, width]); 
// Since the origin is on the left corner, the y axis of the svg system points down 
var y = d3.scale.linear()
    .range([height, 0]); 
    
var xAxis = d3.svg.axis()
    .scale(x)
    .tickSize(-height) 
    .tickPadding(10)   // Distance between axis and tick note 
    .tickSubdivide(true)
    .tickFormat(d3.format(".0"))    
    .orient("bottom");  
    
var yAxis = d3.svg.axis()
    .scale(y)
    .tickPadding(10)
    .tickSize(-width)
    .tickSubdivide(true)
    .tickFormat(d3.format(".3e")) // https://github.com/mbostock/d3/wiki/Formatting#d3_format  
    .orient("left");
var valueline = d3.svg.line()
    .x(function(d) { return x(d.samples); })
    .y(function(d) { return y(d.measurements); });
var zoom = d3.behavior.zoom()
    .x(x)
    .y(y)
    .scaleExtent([0.1, 50])
    .on("zoom", zoomed);
// Adding svg canvas
var svg = d3.select("body").append("svg")
    .call(zoom)
    .attr("width", width + margin.left + margin.right )
    .attr("height", height + margin.top + margin.bottom )
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Get the data
data=[{"SAMPLES":"1","MEASUREMENTS":"2","ID":"ch1"},{"SAMPLES":"2","MEASUREMENTS":"3","ID":"ch1"},{"SAMPLES":"1","MEASUREMENTS":"4","ID":"ch2"},{"SAMPLES":"3","MEASUREMENTS":"5","ID":"ch1"},{"SAMPLES":"2","MEASUREMENTS":"6","ID":"ch2"}];
data.forEach(function(d) {
    d.samples = +d.SAMPLES;
    d.measurements = +d.MEASUREMENTS;
});
console.log(data);
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.samples; }));
y.domain([0, d3.max(data, function(d) { return d.measurements; })]);
// Creating X axis
svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);
    
// Drawing notations
svg.append("g")
        .attr("class", "x axis")
    .append("text")
        .attr("class", "axis-label")
        .attr("x", (width - margin.left)/2)
        .attr("y", height + margin.top + 45)
        .text('Samples'); 
svg.append("g")
    .attr("class", "y axis")
    .call(yAxis);
 
svg.append("g")
        .attr("class", "y axis")
    .append("text")
        .attr("class", "axis-label")
        .attr("transform", "rotate(-90)")
        .attr("y", (-margin.left) + 10)
        .attr("x", -height/2)
        .text('Volts');
svg.append("clipPath")
    .attr("id", "clip")
    .append("rect")
    .attr("width", width)
    .attr("height", height);
// Nest the entries by channel id (ID)
var dataNest = d3.nest()
    .key(function(d) {return d.ID;})
    .entries(data);
// set the colour scale    
var color = d3.scale.category10();
// Auto spacing for the legend
legendSpace = width/dataNest.length;
// Loop through each IDs / key to draw the lines and the legend labels
dataNest.forEach(function(d,i) {
    
    svg.append("path")
        .attr("class", "line")
        .attr("clip-path", "url(#clip)")
        .style("stroke", function() { // Add the colours dynamically
            return d.color = color(d.key); 
        })
        .attr("id", 'tag'+d.key.replace(/'s+/g, '')) // assign ID
        .attr("d", valueline(d.values))
        .style("stroke", function(){return d.color = color(d.key);});
    // Adding legends
    svg.append("text")
        // Setting coordinates and classes
        .attr("x", (legendSpace/2)+i*legendSpace) 
        .attr("y", height + (margin.bottom/2)+ 5)
        .attr("class", "legend")
        // Setting colors
        .style("fill",function(){
            return d.color = color(d.key);
        })
        // Setting 'click' events
        .on("click", function(){
            
            // Determine if current line is visible
            var active = d.active ? false : true,
            newOpacity = active ? 0 : 1;
            
            // Hide or show the elements based on the ID
            d3.select("#tag"+d.key.replace(/'s+/g, ''))
            .transition().duration(600)
            .style("opacity", newOpacity);
            // Update whether or not the elements are active
            d.active = active;
        })
        .text(function() {
            if (d.key == '28-00043b6ef8ff') {return "Inlet";}
            if (d.key == '28-00043e9049ff') {return "Ambient";}
            if (d.key == '28-00043e8defff') {return "Outlet";}
            else {return d.key;}
        })
})
// Zoom specific updates
function zoomed() {
  
    svg.select(".x.axis")
        .transition().duration(500)
        .call(xAxis);
    svg.select(".y.axis")
        .transition().duration(500)
        .call(yAxis);
    svg.selectAll('path.line')
        .transition().duration(500)
        .attr('d', valueline(data));
}
body {
	font: 12px Arial;
	margin: 50px;
}
.axis path {
    fill: none;
    stroke: #bbb;
    stroke-width: 2;
    shape-rendering: crispEdges;
}
.axis text {
    fill: #555;
}
 
.axis line {
    fill: none;
    stroke-width: 1;    
    stroke: #e7e7e7;
    shape-rendering: crispEdges;
}
 
.axis .axis-label {
    font-size: 14px;
}
 
path {
    stroke: steelblue;
    stroke-width: 2;
    fill: none;
}
.legend {
    font-size: 16px;
    font-weight: bold;
    text-anchor: middle;
}

您需要将路径绑定到数据,以便在缩放时使用正确的路径数据调用valueLine。添加新路径时使用d3 dataenter函数:

// choose all .line objects and append a path which is not already binded 
// by  comparing its data to the current key
svg.selectAll(".line").data([d], function (d) {
  return d.key;
})
.enter().append("path")
.attr("class", "line")

然后在缩放时,通过使用路径的正确值调用valueLine来更改d属性路径:

svg.selectAll('path.line')
    .transition().duration(500)
    .attr('d', function(d) {
     return valueline(d.values)
      });

Plunker