I'm new to D3 and doing a project with student data from my college. I was following some tutorials to create a multi-line chart and I can't figure out what happened to my SVG. I set my height and width but it displays wired on screen. Here is my code:
<body>
<p>Students' Major by Gender.</p>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script>
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var MARGINS = {top: 50, right: 20, bottom: 50, left: 50},
WIDTH = 1500 - MARGINS.left - MARGINS.right,
HEIGHT = 800 - MARGINS.top - MARGINS.bottom;
var xScale = d3.scale.linear().range([0, WIDTH]),
yScale = d3.scale.linear().range([HEIGHT, 0]),
xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom").ticks(5),
yAxis = d3.svg.axis()
.scale(yScale)
.orient("left").ticks(5);
var svg = d3.select("body")
.append("svg")
.attr("WIDTH", WIDTH + MARGINS.left + MARGINS.right)
.attr("HEIGHT", HEIGHT + MARGINS.top + MARGINS.bottom)
.append("g")
.attr("transform", "translate(" + MARGINS.left + "," + MARGINS.top + ")");
var colorScale = ["#FF0000", "#0000FF"];
var color = d3.scale.ordinal().range(colorScale);
d3.json("data/majors/major_ARCH.json", function(data) {
data.forEach(function(d) {
d.Year = +d.Year;
d.Gndr = d.Gndr;
d.Count = +d.Count;
});
function sortByDateAscending(a, b) {
//Years will be cast to numbers automagically:
return a.Year - b.Year;
}
data = data.sort(sortByDateAscending);
console.log(data);
var dataNest = d3.nest()
.key(function(d) { return d.Gndr; })
.entries(data);
var lSpace = WIDTH/dataNest.length;
var GenderLine = d3.svg.line()
.x(function(d) {
return xScale(d.Year);
})
.y(function(d) {
return yScale(d.Count);
})
xScale.domain([d3.min(data, function(d) {
return d.Year;
}), d3.max(data, function(d) {
return d.Year;
})]);
yScale.domain([d3.min(data, function(d) {
return d.Count;
}), d3.max(data, function(d) {
return d.Count;
})]);
dataNest.forEach(function(d, i) {
svg.append("path")
.attr('d', GenderLine(d.values, xScale, yScale))
.attr('stroke', function() {
return d.color = color(d.key);
})
.attr('stroke-width', 2)
.attr('id', 'line_' + d.key)
.attr('fill', 'none');
svg.append("text")
.attr("x", (lSpace / 2) + i * lSpace)
.attr("y", HEIGHT)
.style("fill", "black")
.attr("class", "legend")
.on('click', function() {
var active = d.active ? false : true;
var opacity = active ? 0 : 1;
d3.select("#line_" + d.key).style("opacity", opacity);
d.active = active;
})
.attr("stroke", function() {
return d.color = color(d.key);
})
.text(d.key);
})
svg.selectAll("dot")
.data(data)
.enter()
.append("circle")
.attr("r", 5)
.attr("cx", function(d) { return xScale(d.Year); })
.attr("cy", function(d) { return yScale(d.Count); })
.on("mouseover", function(d) {
div.transition()
.duration(200)
.style("opacity", .9)
div.html(d.Year + "<br/>" +d.Count)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
});
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + HEIGHT + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
});
</script>
CSS:
.axis path {
fill: none;
stroke: #777;
shape-rendering: crispEdges;
}
.axis text {
font-family: Lato;
font-size: 13px;
}
/* Legend */
.legend {
font-size: 14px;
font-weight: bold;
}
/*Tooltip*/
div.tooltip {
position: absolute;
text-align: center;
width: 60px;
height: 28px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
I tried to follow a post (Resize svg when window is resized in d3.js) to create a responsive svg but it was not working...
The two tutorials that I used to create my chart are:
http://bl.ocks.org/d3noob/a22c42db65eb00d4e369
https://code.tutsplus.com/tutorials/building-a-multi-line-chart-using-d3js-part-2--cms-22973
I want to make my svg responsive, and know the problems with my code. Thanks!
I want ticks to come above shaded region in graph, i have tried transparency but it will not work.
Due to some constraint i cannot change the way i am coloring green region, but its like this-> Shade area below above line with green, then area below bottom line as white(same as chart background color)
Now due to this, ticks are hiding behind, is there a way i can place them above? or redraw new ticks in shaded region?
Click here for image of graph
renderGraph: function(){
// Data notice the structure
//************************************************************
var data = [
[{'x':1,'y':7},{'x':2,'y':7},{'x':3,'y':7},{'x':4,'y':7},{'x':4.5,'y':8.1},{'x':6.3,'y':8.1},{'x':6.8,'y':7},{'x':8,'y':7},{'x':9,'y':8},{'x':10,'y':8}],
[{'x':1,'y':9},{'x':2,'y':8},{'x':3,'y':11},{'x':4,'y':10},{'x':5,'y':10},{'x':6,'y':9},{'x':7,'y':10},{'x':8,'y':10},{'x':9,'y':11},{'x':10,'y':10}],
[{'x':1,'y':9.5},{'x':2,'y':9},{'x':3,'y':10.5},{'x':4,'y':9},{'x':5,'y':10},{'x':6,'y':9},{'x':7,'y':11},{'x':8,'y':10},{'x':9,'y':11},{'x':10,'y':11}],
[{'x':1,'y':8},{'x':2,'y':8},{'x':3,'y':8},{'x':4,'y':8},{'x':5,'y':10},{'x':6,'y':10},{'x':7,'y':8},{'x':8,'y':8},{'x':9,'y':9},{'x':10,'y':9}],
[{'x':1,'y':10},{'x':2,'y':10},{'x':3,'y':10},{'x':4,'y':11},{'x':5,'y':11},{'x':6.5,'y':11},{'x':7,'y':10},{'x':8,'y':10},{'x':9,'y':11},{'x':10,'y':11}]
];
var dataAboveLine = [{'x':1,'y':10},{'x':2,'y':10},{'x':3,'y':10},{'x':4,'y':11},{'x':5,'y':11},{'x':6.5,'y':11},{'x':7,'y':10},{'x':8,'y':10},{'x':9,'y':11},{'x':10,'y':11}];
var dataBelowLine = [{'x':1,'y':7},{'x':2,'y':7},{'x':3,'y':7},{'x':4,'y':7},{'x':4.5,'y':8.1},{'x':6.3,'y':8.1},{'x':6.8,'y':7},{'x':8,'y':7},{'x':9,'y':8},{'x':10,'y':8}];
var colors = [
'steelblue',
'RGB(0,93,135)',
'RGB(226,0,26)',
'RGB(142,166,78)'
]
var lineType = [
'0 1', //5 0
'5 0',
'5 0',
'8 5'
]
//************************************************************
// Create Margins and Axis and hook our zoom function
//************************************************************
var margin = {top: 20, right: 30, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.linear()
.domain([0, 12])
.range([0, width]);
var y = d3.scale.linear()
.domain([-1, 16])
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
//.tickSize(-height)
.tickPadding(10)
.tickSubdivide(true)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.tickPadding(10)
.tickSize(-width)
.tickSubdivide(true)
.orient("left");
var area = d3.svg.area()
.x(function(d) { return x(d.x); })
.y0(height)
.y1(function(d) { return y(d.y); });
var zoom = d3.behavior.zoom()
.x(x)
.y(y)
.scaleExtent([1, 3])
.on("zoom", zoomed);
var vertical = d3.select("#chartHolder")
.append("div")
.attr("clip-path", "url(#clip)")
.attr("class", "remove")
.style("position", "absolute")
.style("z-index", "19")
.style("width", "1px")
.style("height", "450px")
// .style("top", "39px")
.style("top", "46px")
.style("bottom", "1px")
.style("left", "8px")
.style("background", "#000");
var horizontal = d3.select("#chartHolder")
.append("div")
.attr("clip-path", "url(#clip)")
.attr("class", "remove")
.style("position", "absolute")
.style("z-index", "19")
.style("width", "881px")
.style("height", "1px")
.style("top", "47px")
.style("bottom", "1px")
.style("left", "57px")
.style("background", "#000");
//************************************************************
// Generate our SVG object
//************************************************************
var svg = d3.select("#chartHolder").append("svg")
.call(zoom)
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("class", "svgClass")
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
// svg.append("g")
// .attr("class", "x axis")
// .append("text")
// .attr("class", "axis-label")
// .attr("y", 500)
// .attr("x", 400)
// .text('new');
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('Hours');
svg.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
svg.append("path")
.datum(dataAboveLine)
.attr("class", "areaAbove")
.attr("d", area)
.attr("clip-path", "url(#clip)");
svg.append("path")
.datum(dataBelowLine)
.attr("class", "areaBelow")
.attr("d", area)
.attr("clip-path", "url(#clip)");
//************************************************************
// Create D3 line object and draw data on our SVG object
//************************************************************
var line = d3.svg.line()
.interpolate("linear")
.x(function(d) { return x(d.x); })
.y(function(d) { return y(d.y); });
svg.selectAll('.line')
.data(data)
.enter()
.append("path")
.attr("class", "line")
.attr("clip-path", "url(#clip)")
.attr('stroke', function(d,i){
return colors[i%colors.length];
})
.style("stroke-dasharray", function(d,i){
return lineType[i%lineType.length];
})
.attr("d", line)
.attr("stroke-width","3px");
// Define the div for the tooltip
var div = d3.select("#chartHolder").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
//************************************************************
// Draw points on SVG object based on the data given
//************************************************************
var points = svg.selectAll('.dots')
.data(data)
.enter()
.append("g")
.attr("class", "dots")
.attr("clip-path", "url(#clip)");
points.selectAll('.dot')
.data(function(d, index){
var a = [];
d.forEach(function(point,i){
a.push({'index': index, 'point': point});
});
return a;
})
.enter()
.append('circle')
.on("click", function(d){click(d)})
.attr('class','dot')
.attr("r", 3.5)
.attr('fill', function(d,i){
return colors[d.index%colors.length];
})
.attr('fill-opacity', function(d,i){
if(d.index==0||d.index==4||d.index==3){
return '0';
}
})
.attr("transform", function(d) {
return "translate(" + x(d.point.x) + "," + y(d.point.y) + ")"; }
)
.on("mouseover", function(d) {
div.transition()
// .duration(200)
.style("opacity", .9);
div .html("X:"+d.point.x + "<br/>" +"Y:"+ d.point.y)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
div.transition()
// .duration(500)
.style("opacity", 0);
});
function click(d){
alert(JSON.stringify(d.point));
}
//************************************************************
// Zoom specific updates
//************************************************************
function zoomed() {
svg.select(".areaAbove").call(area);
svg.select(".x.axis").call(xAxis);
svg.select(".y.axis").call(yAxis);
svg.selectAll('path.line').attr('d', line);
svg.select('.areaAbove').attr('d', area);
svg.select('.areaBelow').attr('d', area);
points.selectAll('circle').attr("transform", function(d) {
return "translate(" + x(d.point.x) + "," + y(d.point.y) + ")"; }
);
}
var txtCycle = d3.select("#chartHolder").append("p")
.append("text")
.attr("class", "yaxis-label")
.attr("y", 463)
.attr("x", 400)
.text('Number of cycles');
var slider = d3.select("#chartHolder").append("p").append("input")
.datum({})
.attr("type", "range")
.attr("class","slider")
.attr("value", zoom.scaleExtent()[0])
.attr("min", zoom.scaleExtent()[0])
.attr("max", zoom.scaleExtent()[1])
.attr("step", (zoom.scaleExtent()[1] - zoom.scaleExtent()[0]) / 100)
.on("input", slided);
var svgimg = document.createElementNS('http://www.w3.org/2000/svg','image');
svgimg.setAttributeNS(null,'height','22');
svgimg.setAttributeNS(null,'width','350');
svgimg.setAttributeNS('http://www.w3.org/1999/xlink','href', 'xaxis.PNG');
svgimg.setAttributeNS(null,'x','580');
svgimg.setAttributeNS(null,'y','450');
svgimg.setAttributeNS(null, 'visibility', 'visible');
$('svg').append(svgimg);
function slided(d){
zoom.scale(d3.select(this).property("value"))
.event(svg);
}
//for crosshairs
d3.select("#chartHolder")
.on("mousemove", function(){
coord = d3.mouse(this);
mousex = coord[0];
mousey=coord[1];
// vertical.style("left", mousex+ "px" );
// horizontal.style("top", mousey +"px")
if((mousex+6)>935){
mousex=929;
}
if((mousex+6)<59){
mousex=53;
}
if((mousey+6)>495){
mousey=489;
}
if((mousey+6)<44){
mousey=39;
}
vertical.style("left", mousex+6+ "px" );
horizontal.style("top", mousey+6 +"px");
})
.on("mouseover", function(){
coord = d3.mouse(this);
mousex = coord[0];
mousey=coord[1];
if((mousex+6)>930){
mousex=924;
}
if((mousex+6)<51){
mousex=45;
}
if((mousey+6)<39){
mousey=33;
}
if((mousey+6)>487){
mousey=481;
}
// vertical.style("left", mousex + "px");
// horizontal.style("top", mousey +"px")});
vertical.style("left", mousex +6+ "px");
horizontal.style("top", mousey +6+"px")});
// add cross hairs and floating value on axis
/*
var chart = d3.select("svg");
var focusText = chart.append("g")
.attr("class","focus")
.style("display", "none");
focusText.append("text").attr({"x": 9, "dy": "0.35em"});
var focus = chart.append("g")
.attr("class","focus")
.style("display", "none");
//focus.append("text").attr({"x": 9, "dy": "0.35em"});
// horizontal crosshair
focus.append("line")
.attr({
"x1": -width,
"y1": 0,
"x2": width,
"y2": 0
});
// vertical crosshair
focus.append("line")
.attr({
"x1": 0,
"y1": -height,
"x2": 0,
"y2": height
});
chart.append("rect")
.attr({"class": "overlay" , "width": width , "height": height})
.on({
"mouseover": function() { focus.style("display", null); focusText.style("display", null); },
"mouseout": function() { focus.style("display", "none"); focusText.style("display", "none"); },
"mousemove": mousemove
});
function mousemove() {
var x0 = xScale.invert(d3.mouse(this)[0]),
i = bisectDate(sample2, x0, 1),
d0 = sample2[i-1],
d1 = sample2[i],
d = x0 - d0.date > d1.date - x0 ? d1 : d0;
focus.attr("transform", "translate(" + (d3.mouse(this)[0]) + "," + yScale(d.close) + ")");
focusText.attr("transform", "translate(" + (width-margin.right) + "," + yScale(d.close) + ")");
focusText.select("text").text("$" + d.close);
} */
//
}
renderGraph();
.sapUiBody{
background-color: white;
background-image: none;
}
.grid .tick {
stroke: lightgrey;
opacity: 0.7;
shape-rendering: crispEdges;
}
.grid path {
stroke-width: 0;
}
.axis path {
fill: none;
stroke: #bbb;
shape-rendering: crispEdges;
}
.axis text {
fill: #555;
}
.axis line {
stroke: #e7e7e7;
shape-rendering: crispEdges;
}
.axis .axis-label {
font-size: 14px;
}
.yaxis-label{
left: 448px;
position: absolute;
display: block;
}
.line {
fill: none;
stroke-width: 2.0px;
}
.dot {
/* consider the stroke-with the mouse detect radius? */
stroke: transparent;
stroke-width: 10px;
cursor: pointer;
}
div.tooltip {
position: absolute;
text-align: center;
width: 60px;
height: 28px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
.areaBelow {
fill: white;
stroke-width: 0;
}
.areaAbove {
fill: RGB(142,166,78);
stroke-width: 0;
opacity: 0.34;
}
.dot:hover {
stroke: rgba(68, 127, 255, 0.3);
}
.slider{
width: 300px;
}
<html>
<head>
<script src="http://d3js.org/d3.v3.min.js"></script>
</head>
<body class="sapUiBody" role="application">
<div id="content"></div>
</body>
</html>
I want show and hide a graph with the same button in d3.js.
I use d3.js to create this graph. I don't know if I have use a addlistener o something like that.
The d3.js code is as follows:
<style>
#wrapper
{
min-width:960px;
margin-left:auto;
margin-right:auto;
}
#top
{
width: 100%;
height: 40px;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.dot {
stroke: #000;
}
div.tooltip {
position: absolute;
text-align: center;
width: 60px;
height: 28px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
/* pointer-events: none; This line needs to be removed */
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 1300 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.linear()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category10();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var div = d3.select("body")
.append("div") // declare the tooltip div
.attr("class", "tooltip") // apply the 'tooltip' class
.style("opacity", 0);
var svg = (d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"));
d3.json("/projects/chart/data", function (error, data) {
if (error)
throw error;
data.forEach(function (d) {
d.sepalLength = +d.sepalLength;
d.sepalWidth = +d.sepalWidth;
});
x.domain(d3.extent(data, function (d) {
return d.sepalWidth;
})).nice();
y.domain(d3.extent(data, function (d) {
return d.sepalLength;
})).nice();
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("class", "label")
.attr("x", width)
.attr("y", -6)
.style("text-anchor", "end")
.text("Sepal Width (cm)");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("class", "label")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Sepal Length (cm)")
svg.selectAll(".dot")
.data(data)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 3.5)
.attr("cx", function (d) {
return x(d.sepalWidth);
})
.attr("cy", function (d) {
return y(d.sepalLength);
})
.style("fill", function (d) {
return color(d.species);
})
.on("mouseover", function (d) {
div.transition()
.duration(500)
.style("opacity", 0);
div.transition()
.duration(200)
.style("opacity", .9);
div.html(
'<a href= "http://homestead.app/process/'+d.sepalWidth+'">' + // The first <a> tag
d.sepalWidth +
"</a>" + // closing </a> tag
"<br/>" + d.sepalLength)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
});
var legend = svg.selectAll(".legend")
.data(color.domain())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function (d, i) {
return "translate(0," + i * 20 + ")";
});
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function (d) {
return d;
});
});
</script>
I want to use the same button if it's possible.
Quick example of what could work :
HTML :
<button onclick='toggleGraph()'> </button>
JavaScript :
var showGraph = true;
function toggleGraph(){
var graph = d3.select('#graph'); //i recommend giving the graph an ID
if(showGraph){ //check bool
graph.style('visibility', 'hidden'); //hide graph
showGraph = false; //toggle bool
} else {
graph.style('visibility', 'visible'); //show graph
showGraph = true; //toggle bool
}
}
I'm using code similar to this one, and actually plugged in this code to see if I get the same error and I do. This is the code:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 12px Arial;
}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;
}
.legend {
font-size: 16px;
font-weight: bold;
text-anchor: start;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 30, right: 40, bottom: 70, left: 50},
width = 600 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var parseDate = d3.time.format("%d-%b-%y").parse;
var x = d3.time.scale().range([0, width]);
var y0 = d3.scale.linear().range([height, 0]);
var y1 = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);
var yAxisLeft = d3.svg.axis().scale(y0)
.orient("left").ticks(5);
var yAxisRight = d3.svg.axis().scale(y1)
.orient("right").ticks(5);
var valueline = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y0(d.close); });
var valueline2 = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y1(d.open); });
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
var data = [
{"date":"9-Apr-12","close":436,"open":9.04},
{"date":"7-Apr-12","close":221,"open":4.02},
{"date":"5-Apr-12","close":113,"open":9.02},
{"date":"4-Apr-12","close":64,"open":32.05},
{"date":"3-Apr-12","close":29,"open":46.03},
{"date":"2-Apr-12","close":18,"open":51.03}
];
// Get the data
data.forEach(function(d) {
d.date = parseDate(d.date);
d.close = +d.close;
d.open = +d.open;
});
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.date; }));
y0.domain([0, d3.max(data, function(d) {
return Math.max(d.close); })]);
y1.domain([0, d3.max(data, function(d) {
return Math.max(d.open); })]);
svg.append("path")
.attr("class", "line")
.attr("id", "blueLine")
.attr("d", valueline(data));
svg.append("path")
.attr("class", "line")
.style("stroke", "red")
.attr("id", "redLine")
.attr("d", valueline2(data));
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// edit the Y Axis Left
svg.append("g")
.attr("class", "y axis")
.style("fill", "steelblue")
.attr("id", "blueAxis")
.call(yAxisLeft);
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + width + " ,0)")
.style("fill", "red")
.attr("id", "redAxis")
.call(yAxisRight);
// Add the blue line title
svg.append("text")
.attr("x", 0)
.attr("y", height + margin.top + 10)
.attr("class", "legend")
.style("fill", "steelblue")
.on("click", function(){
// Determine if current line is visible
var active = blueLine.active ? false : true,
newOpacity = active ? 0 : 1;
// Hide or show the elements
d3.select("#blueLine").style("opacity", newOpacity);
d3.select("#blueAxis").style("opacity", newOpacity);
// Update whether or not the elements are active
blueLine.active = active;
})
.text("Blue Line");
// Add the red line title
svg.append("text")
.attr("x", 0)
.attr("y", height + margin.top + 30)
.attr("class", "legend")
.style("fill", "red")
.on("click", function(){
// Determine if current line is visible
var active = redLine.active ? false : true ,
newOpacity = active ? 0 : 1;
// Hide or show the elements
d3.select("#redLine").style("opacity", newOpacity);
d3.select("#redAxis").style("opacity", newOpacity);
// Update whether or not the elements are active
redLine.active = active;
})
.text("Red Line");
</script>
</body>
I'm getting errors saying that 'blueline' and 'redline' are not defined.
Where do I define those?
I've looked at similar code where the html, css, and js are separated into their own files which is how I've done it also, and other than what I see in the code above I don't find those variables used anyplace else or defined beyond what is there.
I made a plunk with the code you have there and everything works just fine. Let me explain a little of what is going on though.
Instead of using HTML that is already there, D3 will often generate its own (in fact it has to generate its own to do the visualizations). You see this with statements like the following:
svg.append("path")
.attr("class", "line")
.attr("id", "blueLine")
.attr("d", valueline(data));
D3 just created a path element and appended it to the svg element it created earlier. It gives this particular element an id of blueLine which it uses later to apply styles. It did not exist in any HTML prior to this script running. D3 created it.
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,
after the zooms, the line would become one which used data for both line and rotated.
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;
}
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)
});
Plunker