Reputation: 23
It is my version of "Multi-line graph 4: Toggle" from http://bl.ocks.org/d3noob/e99a762017060ce81c76 but I ran into some problems pls help.
At first the initial graph is correct,
I think it is the zoomed functions is not doing right, when I used "d.value" the browser would say "d. is not define"
Here are the codes:
// 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;
}
Upvotes: 0
Views: 894
Reputation: 5825
You need to bind your paths to your data, so you can call valueLine
with the correct data for the path when zooming.
Use d3 data
and enter
functions when adding a new path:
// 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")
Then when you zoom, change the d
attribute path by calling valueLine
with the path's correct values:
svg.selectAll('path.line')
.transition().duration(500)
.attr('d', function(d) {
return valueline(d.values)
});
Upvotes: 2