Draw Line chart with positive & negative values - javascript

I am trying to draw a Dovish & Hawkish line chart diagram.
Example:
However, it's throwing an error.
I took the example from a bar chart, that draws the bars with a positive and negative value. Then I have used the code only related to draw the xScale/yScale and the lines for xAxis/yAxis.
JSFiddle can be found here.

The problem here is that you are using an ordinal scale for the x axis:
var x = d3.scale.ordinal()
.domain(d3.range(data.length))
Which has this domain:
[0, 1, 2, 3, 4, 5, 6, 7]
However, you're passing the datum to the line generator:
var line = d3.svg.line()
.x(function(d) { return x(d);})
//datum here -------------^
Instead of that, pass the index of the datum:
var line = d3.svg.line()
.x(function(d, i) { return x(i);})
//index here ----------------^
Here is your updated code:
var data = [-0.1, -0.5, -0.32, 0.2, 1, 0.5, -0.3, -1.0];
var margin = {
top: 30,
right: 10,
bottom: 10,
left: 30
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var y0 = Math.max(Math.abs(d3.min(data)), Math.abs(d3.max(data)));
var y = d3.scale.linear()
.domain([-y0, y0])
.range([height, 0])
.nice();
var x = d3.scale.ordinal()
.domain(d3.range(data.length))
.rangeRoundBands([0, width], .2);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
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 line = d3.svg.line()
.x(function(d, i) {
return x(i);
})
.y(function(d) {
return y(d);
});
var dataSum = d3.sum(data, function(d) {
return d;
});
svg.append("g")
.attr("class", "x axis")
.call(yAxis);
svg.append("g")
.attr("class", "y axis")
.append("line")
.attr("y1", y(0))
.attr("y2", y(0))
.attr("x1", 0)
.attr("x2", width);
svg.append("path")
.data([data])
.attr("class", "line")
.attr("d", line);
.axis text {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.line{
fill: none;
stroke: blue;
stroke-width: 2px;
}
.tick text{
font-size: 12px;
}
.tick line{
opacity: 0.2;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
PS: You don't need that awkward line in the middle of the chart. You can create a proper axis:
var data = [-0.1, -0.5, -0.32, 0.2, 1, 0.5, -0.3, -1.0];
var margin = {
top: 30,
right: 10,
bottom: 10,
left: 30
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var y0 = Math.max(Math.abs(d3.min(data)), Math.abs(d3.max(data)));
var y = d3.scale.linear()
.domain([-y0, y0])
.range([height, 0])
.nice();
var x = d3.scale.ordinal()
.domain(d3.range(data.length))
.rangeRoundBands([0, width], .2);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
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 line = d3.svg.line()
.x(function(d, i) {
return x(i);
})
.y(function(d) {
return y(d);
});
var dataSum = d3.sum(data, function(d) {
return d;
});
svg.append("g")
.attr("class", "x axis")
.call(yAxis);
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(0," + y(0) + ")")
.call(xAxis)
svg.append("path")
.data([data])
.attr("class", "line")
.attr("d", line);
.axis text {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.line {
fill: none;
stroke: blue;
stroke-width: 2px;
}
.tick text {
font-size: 12px;
}
.tick line {
opacity: 0.2;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

Related

D3 can't draw two brushes together

so I am trying to make something where the user can drag and create two equal sized brushes in a line chart, the problem is that brush disappears after I try to draw the second one. I have tried to create separate attr and seperate brush call but still can't do it.
this is my code https://jsfiddle.net/f0gxs41t/
any help?
<!DOCTYPE html>
<html>
<head>
<svg width="960" height="400"></svg>
<meta charset="utf-8">
<title>
line chart with drag and drop
</title>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
<script src="./line_graph.js"></script>
<link rel="stylesheet" type= "text/css" href="./style.css">
</head>
<body>
</body>
</html>
js file :
var data=[1,5,2,7,4,7,8,9,5,3,6,8,2,3,5,9,8,5]
var svg=d3.select("svg")
var margin={top:100,bottom:50,left:100,right:0},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var x_extent=d3.extent(data,function(d,i){return i})
var y_extent=d3.extent(data,function(d,i){return d})
x=d3.scale.linear()
.range([0,width])
.domain(x_extent)
y=d3.scale.linear()
.range([height,0])
.domain(y_extent)
var line=d3.svg.line()
.x(function(d,i){ return x(i)})
.y(function(d,i){return y(d)})
var xAxis = d3.svg.axis().scale(x)
.orient("bottom");
var yAxis = d3.svg.axis().scale(y)
.orient("left");
// g.append("g")
// .append("text")
// .attr("fill", "#000")
// .attr("transform","rotate(-90)")
// .attr("y",-35)
// .attr("dy","0.71em")
// .attr("text-anchor","end")
// .text("break something")
g.append("path")
.attr("class","line")
.datum(data)
.attr("d",line)
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate("+margin.left+"," + (height+margin.top) + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate("+margin.left+ ","+margin.top+")")
.call(yAxis);
var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// if (brush.empty()!==true){
//
// }
var brushes = [];
var parent_brush=d3.svg.brush()
.x(x)
.on("brushend",brushed)
var brush1=d3.svg.brush()
.x(x)
.on("brushend",brushed)
function brushed(){
if (parent_brush.empty()==true){
console.log(parent_brush,"empty")
}
else {
brush_width=parent_brush.extent()[1]-parent_brush.extent()[0]
console.log(parent_brush,"not empty")
}
}
svg.append("g")
.attr("class","parent")
.call(parent_brush)
.selectAll("rect")
.attr("x",margin.left)
.attr("y",margin.top)
.attr("height",height)
.style("fill","orange")
.style("fill-opacity",".2")
svg.append("g")
.attr("class","child")
.call(brush1)
.selectAll("rect")
.attr("x",margin.left)
.attr("y",margin.top)
.attr("height",height)
.style("fill","orange")
.style("fill-opacity",".2")
css file:
.axis path,
.axis line {
fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;
}
.hover-line {
stroke: #6F257F;
stroke-width: 2px;
stroke-dasharray: 3,3;
}
.area {
fill: lightsteelblue;
}
.line{
fill:none;
stroke:brown;
stroke-linejoin:round;
stroke-linecap:round;
stroke-width:1.5
}
.focus circle {
fill: none;
stroke: steelblue;
}
.brush {
fill: grey;
pointer-events: all;
fill-opacity:0.3;
}
.resize {
fill: grey;
pointer-events: all;
fill-opacity:0.7;
}
consider using d3.js v4...
Child brush is created in the parent brush "end" event handler, where we also need to disable new parent brush selections.
var parent_brush = d3.brushX()
.extent([
[margin.left, margin.top],
[margin.left + width, margin.top + height]
])
.on("end", brushedParent);
var child_brush;
svg.append("g")
.attr("class", "parent")
.call(parent_brush);
function brushedParent() {
// remove new brush selection capture area
svg.select('.parent .overlay').remove();
if (!child_brush) {
child_brush = d3.brushX()
.extent([
[margin.left, margin.top],
[margin.left + width, margin.top + height]
])
.on("end", brushedChild);
svg.append("g")
.attr("class", "child")
.call(child_brush);
}
}
function brushedChild() {
// remove new brush selection capture area
svg.select('.child .overlay').remove();
child_selection = d3.brushSelection(svg.select('.child').node());
var parent_selection = d3.brushSelection(svg.select('.parent').node());
var parent_width = parent_selection[1] - parent_selection[0];
var resized_child = [child_selection[0], child_selection[0] + parent_width];
child_brush.on("end", null);
child_brush.move(svg.select('.child'), resized_child);
}
Here is the working code snippet:
var data = [1, 5, 2, 7, 4, 7, 8, 9, 5, 3, 6, 8, 2, 3, 5, 9, 8, 5]
var svg = d3.select("svg")
var margin = {
top: 100,
bottom: 50,
left: 100,
right: 0
},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var x_extent = d3.extent(data, function(d, i) {
return i
})
var y_extent = d3.extent(data, function(d, i) {
return d
})
x = d3.scaleLinear()
.range([0, width])
.domain(x_extent)
y = d3.scaleLinear()
.range([height, 0])
.domain(y_extent)
var line = d3.line()
.x(function(d, i) {
return x(i)
})
.y(function(d, i) {
return y(d)
})
var xAxis = d3.axisBottom(x);
var yAxis = d3.axisLeft(y);
g.append("path")
.attr("class", "line")
.datum(data)
.attr("d", line)
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(" + margin.left + "," + (height + margin.top) + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(yAxis);
var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var brushes = [];
var parent_brush = d3.brushX()
.extent([
[margin.left, margin.top],
[margin.left + width, margin.top + height]
])
.on("end", brushedParent);
var child_brush;
svg.append("g")
.attr("class", "parent")
.call(parent_brush);
function brushedParent() {
// remove new brush selection capture area
svg.select('.parent .overlay').remove();
if (!child_brush) {
child_brush = d3.brushX()
.extent([
[margin.left, margin.top],
[margin.left + width, margin.top + height]
])
.on("end", brushedChild);
svg.append("g")
.attr("class", "child")
.call(child_brush);
}
}
function brushedChild() {
// remove new brush selection capture area
svg.select('.child .overlay').remove();
child_selection = d3.brushSelection(svg.select('.child').node());
var parent_selection = d3.brushSelection(svg.select('.parent').node());
var parent_width = parent_selection[1] - parent_selection[0];
var resized_child = [child_selection[0], child_selection[0] + parent_width];
child_brush.on("end", null);
child_brush.move(svg.select('.child'), resized_child);
}
.axis path,
.axis line {
fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;
}
.hover-line {
stroke: #6F257F;
stroke-width: 2px;
stroke-dasharray: 3, 3;
}
.area {
fill: lightsteelblue;
}
.line {
fill: none;
stroke: brown;
stroke-linejoin: round;
stroke-linecap: round;
stroke-width: 1.5
}
.focus circle {
fill: none;
stroke: steelblue;
}
.brush {
fill: grey;
pointer-events: all;
fill-opacity: 0.3;
}
.resize {
fill: grey;
pointer-events: all;
fill-opacity: 0.7;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="960" height="400"></svg>

Error in creating Line D3.js Chart

Js line Chart and i am able to draw chart.While i am using json data I am getting:
Error: Cannot read property 'length' of null(…)
My function is like. i am getting error while parsing data. I am getting json response correctly, but I am enable to draw a chart. Can anyone tell me what is wrong i am doing?
var margin = { top: 30, right: 20, bottom: 30, left: 50 },
width = 600 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
// Parse the date / time
var parseDate = d3.time.format("%d-%b-%y").parse;
// Set the ranges
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(20);
// Define the line
var valueline = d3.svg.line()
.x(function (d) { return x(d.dategraph); })
.y(function (d) { return y(d.assetcount); });
// Adds the svg canvas
var svg = d3.select("linegrapg")
.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 dataset = [{"dategraph":"16-Nov-16","assetcount":299},{"dategraph":"19-Nov-16","assetcount":0},
{"dategraph":"08-Nov-16","assetcount":18},{"dategraph":"14-Nov-16","assetcount":10},
{"dategraph":"17-Nov-16","assetcount":2},{"dategraph":"18-Nov-16","assetcount":0}]
data = JSON.parse(dataset.d);
data.forEach(function (d) {
d.Letter = parseDate(d.dategraph);
d.Freq = +d.assetcount;
});
// Scale the range of the data
x.domain(d3.extent(data, function (d) { return d.Letter; }));
y.domain([0, d3.max(data, function (d) { return d.Freq; })]);
// Add the valueline path.
svg.append("path")
.attr("class", "line")
.attr("d", valueline(data));
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
}
}
Based on your question, the code runs by commenting out the JSON.parse function call and the two trailing curly braces. The data variable is already an array of objects so there is no need to de-serialize it (from a string type). Other than that, I wasn't able to reproduce the error you were getting. Have a look at the code snippet below.
var margin = {
top: 30,
right: 20,
bottom: 30,
left: 50
},
width = 600 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
// Parse the date / time
var parseDate = d3.time.format("%d-%b-%y").parse;
// Set the ranges
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(20);
// Define the line
var valueline = d3.svg.line()
.x(function(d) {
return x(d.dategraph);
})
.y(function(d) {
return y(d.assetcount);
});
// Adds the svg canvas
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 = [{
"dategraph": "16-Nov-16",
"assetcount": 299
}, {
"dategraph": "19-Nov-16",
"assetcount": 0
}, {
"dategraph": "08-Nov-16",
"assetcount": 18
}, {
"dategraph": "14-Nov-16",
"assetcount": 10
}, {
"dategraph": "17-Nov-16",
"assetcount": 2
}, {
"dategraph": "18-Nov-16",
"assetcount": 0
}];
//var data = JSON.parse(dataset);
data.forEach(function(d) {
d.Letter = parseDate(d.dategraph);
d.Freq = +d.assetcount;
});
// Scale the range of the data
x.domain(d3.extent(data, function(d) {
return d.Letter;
}));
y.domain([0, d3.max(data, function(d) {
return d.Freq;
})]);
// Add the valueline path.
svg.append("path")
.attr("class", "line")
.attr("d", valueline(data));
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
<script src="https://d3js.org/d3.v3.min.js"></script>
My Working Example with tooltip
<!DOCTYPE html>
<meta charset="utf-8">
<style> /* set the CSS */
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;
}
div.tip {
position: absolute;
text-align: center;
width: auto;
height: auto;
padding: 2px;
font: 12px sans-serif;
background: black;
border: 0px;
border-radius: 8px;
pointer-events: none;
color:white;
border-radius: 8px 8px 8px 8px;
}
</style>
<body>
<!-- load the d3.js library -->
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
// Set the dimensions of the canvas / graph
var margin = {top: 30, right: 20, bottom: 30, left: 50},
width = 600 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
// Parse the date / time
var parseDate = d3.time.format("%d-%b-%y").parse;
var formatTime = d3.time.format("%e %B");
// Set the ranges
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
// Define the line
var valueline = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.close); });
// Define the div for the tooltip
var div = d3.select("body").append("div")
.attr("class", "tip")
.style("opacity", 0);
// Adds the svg canvas
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 + ")");
// Get the data
var data = [
{"date":"08-Nov-16","close":299},
{"date":"09-Nov-16","close":10},
{"date":"10-Nov-16","close":18},
{"date":"11-Nov-16","close":10},
{"date":"12-Nov-16","close":2},
{"date":"13-Nov-16","close":50}];
data.forEach(function(d) {
d.date = parseDate(d.date);
d.close = +d.close;
});
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.close; })]);
// Add the valueline path.
svg.append("path")
.attr("class", "line")
.attr("d", valueline(data));
// Add the scatterplot
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 5)
.attr("cx", function(d) { return x(d.date); })
.attr("cy", function(d) { return y(d.close); })
.on("mouseover", function(d) {
div.transition()
.duration(200)
.style("opacity", .9);
div .html(formatTime(d.date) + "<br/>" + d.close)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
});
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
</script>
</body>

Ignore the fill of the 2 last data

i have a question, how i can draw the chart but the las 2 arrays from data ignore the fill from css.
Here i have the code:
<html>
<head>
<title></title>
<script src="d3.min.js"></script>
<style>
body {
font: 10px sans-serif;
}
.grid path {
stroke-width: 0;
}
.axis path {
fill: #E0E0E0;
stroke: #bbb;
shape-rendering: crispEdges;
}
.axis text {
fill: #000;
}
.axis line {
stroke: #e7e7e7;
shape-rendering: crispEdges;
}
.axis .axis-label {
font-size: 10px;
}
.line {
stroke-width: 1;
}
</style>
</head>
<body>
<script>
var data = [
//VERD
[{'x':15000,'y':0}, {'x':15000,'y':130},{'x':40000,'y':130},{'x':40000,'y':0},
{'x':60000,'y':0},{'x':60000,'y':130},{'x':70000,'y':130},{'x':70000,'y':0},],
// GRIS PARADA
[{'x':40000,'y':0}, {'x':40000,'y':130}, {'x':60000,'y':130},{'x':60000,'y':0}],
//TARONJA TRABAJO
[{'x':16000,'y':40},{'x':16000,'y':80}, {'x':37000,'y':80}, {'x':37000,'y':40}],
//BLAU RALENTI
[{'x':17000,'y':0},{'x':17000,'y':40},{'x':35000,'y':40},{'x':35000,'y':0} ],
//LINEA VELOCITAT
[{'x':10000,'y':0},{'x':12000,'y':80}, {'x':15000,'y':70}, {'x':17000,'y':80},{'x':19000,'y':100},
{'x':20000,'y':55}, {'x':27000,'y':85}, {'x':33000,'y':65}, {'x':37000,'y':25}, {'x':40000,'y':65}, {'x':45000,'y':77},
{'x':50000,'y':47}, {'x':55000,'y':88}, {'x':59000,'y':25}, {'x':66000,'y':0}],
//LINEA TEMPERATURA
[{'x':10000,'y':0},{'x':12000,'y':20}, {'x':15000,'y':15}, {'x':17000,'y':18},{'x':19000,'y':17},
{'x':20000,'y':15}, {'x':27000,'y':19}, {'x':33000,'y':12}, {'x':37000,'y':21}, {'x':40000,'y':23}, {'x':45000,'y':15},
{'x':50000,'y':18}, {'x':55000,'y':19}, {'x':59000,'y':21}, {'x':66000,'y':20}]
];
var colors = [
'green',
'gray',
'orange',
'blue',
'red'
]
var margin = {top: 5, right: 30, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 200 - margin.top - margin.bottom;
var x = d3.scale.linear()
.domain([0, 86400])
.range([0, width]);
var y = d3.scale.linear()
.domain([0, 140])
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.ticks(10)
.tickSize(-height)
.tickPadding(10)
.tickSubdivide(true)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.ticks(5)
.tickPadding(10)
.tickSize(-width)
.tickSubdivide(true)
.orient("left");
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 + ")");
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", "y axis")
.append("text")
.attr("class", "axis-label")
.attr("transform", "rotate(-90)")
.attr("y", (-margin.left) + 10)
.attr("x", -height/2)
.text('KM/H');
svg.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
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('fill', function(d,i){
return colors[i%colors.length];
})
.attr("d", line);
</script>
</body>
</html>
And here the actual result:
Actual
And i need this result:
I need this
How i can did to show the last lines without the fill?
Really thx guys.
When you want <path> to be line, use stroke property instead of fill in SVG. And you should control specific data by index at attr callback functions.
svg.selectAll('.line')
.data(data)
.enter()
.append("path")
.attr("class", "line")
.attr("clip-path", "url(#clip)")
.attr('fill', function(d, i) {
return i < 4 ? colors[i % colors.length] : 'none';
})
.attr('stroke', function (d, i) {
return i >= 4 ? colors[i % colors.length] : 'none';
})
.attr("d", line);
Take a look solved fiddle:
https://jsfiddle.net/fe6jvrka/

How to change color of the dots in D3.js to reflect data on y scale?

I am starting with the d3.js and have decided to build a weather graph but the points (or nodes?) do not change color as they should i.e. not by temperature (position on y scale) but according to their position on x scale? What am I doing wrong?
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 2.5px;
}
.dot {
fill: steelblue;
stroke: steelblue;
stroke-width: 1.5px;
}
</style>
<body>
<script src="d3/d3.min.js" charset="utf-8"></script>
<script>
var tooltip = d3.select('body').append('div')
.style('position','absolute')
var data = [
[new Date(1961, 0, 1), 6.3],
[new Date(2014, 0, 1), 9.4]
];
var margin = {top: 20, right: 30, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var tooltip = d3.select('body').append('div')
.style('position', 'absolute')
.style('padding', '0 10px')
var colors = d3.scale.linear()
.domain([5, 20])
.range(['#000000','#ffffff'])
var x = d3.time.scale()
.domain([new Date(1960, 0, 1), new Date(2015, 0, 1)])
.range([0, width]);
var y = d3.scale.linear()
.domain([5, 10])
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.interpolate("monotone")
.x(function(d) { return x(d[0]); })
.y(function(d) { return y(d[1]); });
var svg = d3.select("body").append("svg")
.datum(data)
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.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)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Teplota (ºC)");
svg.append("path")
.attr("class", "line")
.attr("d", line);
svg.selectAll(".dot")
.data(data)
.enter().append("circle")
.style('stroke', function(d,i) {
return colors(i);
})
.style('fill', function(d,i) {
return colors(i);
})
.attr("class", "dot")
.attr("cx", line.x())
.attr("cy", line.y())
.attr("r", 1.5)
.on("mouseover", function(d) {
tooltip.html(d[1] + 'ºC')
.style('left', (d3.event.pageX - 35) + 'px')
.style('top', (d3.event.pageY - 30) + 'px')
.style('font-size', '15px')
});
</script>
Your dots are currently being colored by the array index of your data. Doing it this way will color your dots based on their time series (the x axis).
In order to color your circles based on temperature set the call to colors function like so. This will reference the second data point in current array iteration (the temperature).
svg.selectAll(".dot")
.data(data)
.enter().append("circle")
.style('stroke', function(d,i) {
return colors(d[1]);
})
.style('fill', function(d,i) {
return colors(d[1]);
})

Insert minutes and hour on d3.js timeseries plot

I'm using this snippet to understand how d3.js works.
I changed this line of code -> var parseDate = d3.time.format('%H-%M-%e-%b-%y').parse;
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
</style>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script>
var margin = {top: 20, right: 20, bottom: 30, left: 50},
width = 1000 - margin.left - margin.right,
height = 600 - margin.top - margin.bottom;
var parseDate = d3.time.format('%H-%M-%e-%b-%y').parse;
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.close); });
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.tsv("data/plottingData/first.tsv", function(error, data) {
if (error) throw error;
data.forEach(function(d) {
d.date = parseDate(d.date);
d.close = +d.close;
});
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain(d3.extent(data, function(d) { return d.close; }));
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("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
});
</script>
because the file is formatted in this way:
11-30-1-May-12 582.13
10-30-1-Apr-12 382.13
9-30-1-Mar-12 482.13
...
but I'm continuing to view only day-month into x-Axis.
what's wrong?
thanks in advance.
You are parsing the date in correct format, but on X-axis you did not provide the format, on which you want to show date. So just use "xAxis.tickFormat(parseDate)" in your code. Example is here:
d3.svg.axis()
.scale(x)
.orient("bottom").tickFormat(d3.time.format('%H-%M-%e-%b-%y'));

Categories

Resources