I am currently trying to render plot in React using D3. To integrate both of them , i have used the following link:
http://oli.me.uk/2015/09/09/d3-within-react-the-right-way/.
I have also tried the solutions provided in the link for making the chart responsive:
Resize svg when window is resized in d3.js
Although it works great in standalone code upon integrating it with React it starts omitting ticks . Working jsfiddle for the D3 alone: https://jsfiddle.net/adityap16/11edxrnq/1/
Code of Standalone D3 :
var data = [
{"mytime": "2015-12-01T11:10:00.000Z", "value": 64},
{"mytime": "2015-12-01T11:15:00.000Z", "value": 67},
{"mytime": "2015-12-01T11:20:00.000Z", "value": 70},
{"mytime": "2015-12-01T11:25:00.000Z", "value": 64},
{"mytime": "2015-12-01T11:30:00.000Z", "value": 72},
{"mytime": "2015-12-01T11:35:00.000Z", "value": 75},
{"mytime": "2015-12-01T11:40:00.000Z", "value": 71},
{"mytime": "2015-12-01T11:45:00.000Z", "value": 80}
];
var parseDate = d3.time.format("%Y-%m-%dT%H:%M:%S.%LZ").parse;
data.forEach(function(d) {
d.mytime = parseDate(d.mytime);
});
//var margin = { top: 30, right: 30, bottom: 40, left:50 },
var margin = { top: 30, right: 30, bottom: 40, left:50 },
height = 200,
width = 800;
var color = "green";
var xaxis_param = "mytime";
var yaxis_param = "value"
var params1 = {margin:margin,height:height,width:width, color: color, xaxis_param:xaxis_param, yaxis_param :yaxis_param};
draw_graph(data,params1);
function draw_graph(data,params){
//Get the margin
var xaxis_param = params.xaxis_param;
var yaxis_param = params.yaxis_param;
var color_code = params.color;
var margin = params.margin;
var height = params.height - margin.top - margin.bottom,
width = params.width - margin.left - margin.right;
var x_extent = d3.extent(data, function(d){
return d[xaxis_param]});
var y_extent = d3.extent(data, function(d){
return d[yaxis_param]});
var x_scale = d3.time.scale()
.domain(x_extent)
.range([0,width]);
var y_scale = d3.scale.linear()
.domain([0,y_extent[1]])
.range([height,0]);
//Line
var lineGen = d3.svg.line()
.x(function (d) {
return x_scale(d[xaxis_param]);
})
.y(function (d) {
return y_scale(d[yaxis_param]);
});
var myChart = d3.select('body')
.append("div")
.classed("svg-container", true)
.append('svg')
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("viewBox", "0 0 800 600")
//class to make it responsive
.classed("svg-content-responsive", true)
.attr('class','my-chart')
.style('background', '#E7E0CB')
.append('g')
.attr('transform', 'translate('+ margin.left +', '+ margin.top +')');
myChart
.append('svg:path')
.datum(data)
.attr('class', 'line')
.attr("d",lineGen)
.attr('stroke', color_code)
.attr('stroke-width', 1)
.attr('fill', 'none');
var legend = myChart.append("g")
.attr("class", "legend")
.attr("transform", "translate(" + 5 + "," + (height - 25) + ")")
legend.append("rect")
.style("fill", color_code)
.attr("width", 20)
.attr("height", 20);
legend.append("text")
.text(yaxis_param)
.attr("x", 25)
.attr("y", 12);
var vGuideScale = d3.scale.linear()
.domain([0,y_extent[1]])
.range([height, 0])
var vAxis = d3.svg.axis()
.scale(vGuideScale)
.orient('left')
.ticks(5)
var hAxis = d3.svg.axis()
.scale(x_scale)
.orient('bottom')
.ticks(d3.time.minute, 5);
myChart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(hAxis);
myChart.append("g")
.attr("class", "y axis")
.call(vAxis)
}
I might need to need to setState or something upon resize, that should trigger React to re-render with the new information but being new to React , i am not able to make it work.
Edit: I am still trying to edit but the problem seems to be the ticks on x axis and y axis when you shrink the window you are able to see the ticks but not in a full screen. Still trying to understand why?
Thanks!
So i was able to find the answer in one of the open issues in React on Github (react-d3 components). Attached is the link and a code snippet:
https://github.com/codesuki/react-d3-components/issues/9
Code:
let AreaGraph = React.createClass({
mixins: [React.addons.PureRenderMixin],
getInitialState() {
return {
parentWidth: 0
}
},
getDefaultProps() {
return {
width: '100%',
height: 300,
margin: { left: -1, top: 10, bottom: 0, right: 1 }
}
},
handleResize(e) {
let elem = this.getDOMNode();
let width = elem.offsetWidth;
this.setState({
parentWidth: width
});
},
componentDidMount() {
if(this.props.width === '100%') {
window.addEventListener('resize', this.handleResize);
}
this.handleResize();
},
componentWillUnmount() {
if(this.props.width === '100%') {
window.removeEventListener('resize', this.handleResize);
}
},
render() {
let { width, height, margin, xScale, yScale, xAxis, ...props } = this.props;
// Determine the right graph width to use if it's set to be responsive
if(width === '100%') {
width = this.state.parentWidth || 400;
}
// Set scale ranges
xScale && xScale.range([0, width - (margin.left + margin.right)]);
yScale && yScale.range([height - (margin.top + margin.bottom), 0]);
return (
<div className={"usage__cpu__graph "+props.className}>
<AreaChart
ref="chart"
width={width}
height={height}
margin={margin}
xScale={xScale}
yScale={yScale}
xAxis={xAxis}
{...props}
/>
</div>
);
}
})
Related
I am trying to create a scatterplot with a zooming. The following code I have used in my angular application and its working till a certain extent when I run it in my local server. However putting the same code in Stackblitz, the zooming is not working. I want to achieve a zooming where the zooming is limited to just the values on the graph. There should be no zooming of the axis accept the value changes in both the axis. Something exactly like : http://bl.ocks.org/peterssonjonas/4a0e7cb8d23231243e0e .
Here in the example, on zooming, only the values are zoomed and the axis values changed correspondingly. It doesn't zoom the whole graph plot area. How do I achieve it? Here is my Stackblitz code:
https://stackblitz.com/edit/angular-hu2thj
ANSWER :
Finally I figure out the graph for this problem in case of any future reference:
import { Component, OnInit, Input, ViewChild, ElementRef } from '#angular/core';
import * as d3 from 'd3';
#Component({
selector: 'app-scatterplot',
templateUrl: './scatterplot.component.html',
styleUrls: ['./scatterplot.component.css']
})
export class ScatterplotComponent implements OnInit {
#ViewChild('chart1') private chartContainer: ElementRef;
dataValue = [{ x: "67", y: "188", },
{ x: "200", y: "163" },
{ x: "254", y: "241" },
{ x: "175", y: "241" },
];
ngOnInit() {
this.graph();
}
graph() {
const element = this.chartContainer.nativeElement;
var svgWidth = 400;
var svgHeight = 400;
var margin = { top: 30, right: 40, bottom: 50, left: 60 };
var width = svgWidth - margin.left - margin.right;
var height = svgHeight - margin.top - margin.bottom;
var originalCircle = {
"cx": -150,
"cy": -15,
"r": 20
};
var svgViewport = d3.select(element)
.append('svg')
.attr('width', svgWidth)
.attr('height', svgHeight)
// create scale objects
var x = d3.scaleLinear()
.domain([1, 500])
.range([0, width]);
var y = d3.scaleLinear()
.domain([1, 500])
.range([height, 0]);
// create axis objects
var xAxis = d3.axisBottom(x);
var yAxis = d3.axisLeft(y);
// Zoom Function
var zoom = d3.zoom()
.on("zoom", zoomFunction);
// Inner Drawing Space
var innerSpace = svgViewport.append("g")
.attr("class", "inner_space")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(zoom);
// append some dummy data
var data = innerSpace.selectAll("circle")
.data(this.dataValue)
.enter().append("circle")
.attr("class", "dot")
.attr("cx", function (d) {
return x(d.x)
;
})
.attr("cy", function (d) {
return y(d.y);
})
.attr("r", 2);
// Draw Axis
var gX = innerSpace.append("g")
.attr("class", "axis")
.attr("transform", "translate(0, " + height + ")")
.call(xAxis);
var gY = innerSpace.append("g")
.attr("class", "axis axis--y")
.call(yAxis);
// append zoom area
var view = innerSpace.append("rect")
.attr("class", "zoom")
.attr("width", width)
.attr("height", height - 10)
.attr("fill", "transparent")
.attr("fill-opacity", 0.1)
.call(zoom)
function zoomFunction() {
// create new scale ojects based on event
var new_xScale = d3.event.transform.rescaleX(x)
var new_yScale = d3.event.transform.rescaleY(y)
console.log(d3.event.transform)
// update axes
gX.call(xAxis.scale(new_xScale));
gY.call(yAxis.scale(new_yScale));
// update circle
data.attr("transform", d3.event.transform)
};
}
}
The problem on stackblitz is that d3.event is null.
Try this to zoom the points in your local server.
You need to add a clip path and animate the axis, see the second example (heatmap)
var svg = d3.select(element)
.append("svg:svg")
.attr("width", w + left_padding)
.attr("height", h + top_padding);
var g = svg.append("g");
var zoom = d3.zoom().on("zoom", function () {
console.log("zoom", d3, d3.event);
g.attr("transform", d3.event.transform);
});
svg.call(zoom);
g.selectAll("circle")
.data(this.dataValue)
.enter().append("circle")
.attr("class", "dot")
.attr("cx", d => x(d.x) )
.attr("cy", d => y(d.y) )
.attr("r", 2);
I am quiet new to D3 and currently trying to create zooming functionality in my plots. I was able to get the zoom option working but not exactly how i want it to be. I only want zoom behaviour in horizontal (x axis) and no zooming behaviour in y axis. I also want to code panning in my horizontal (x axis) direction. I was also trying to hinge it to the x axis without disabling panning. I have tried a few ways but unable to do so.
Any help/tips would be awesome
JSFIDDLE LINK: https://jsfiddle.net/4sts8nfs/3/
Code:
var data = [{
"mytime": "2015-12-01T23:10:00.000Z",
"value": 64
}, {
"mytime": "2015-12-01T23:15:00.000Z",
"value": 67
}, {
"mytime": "2015-12-01T23:20:00.000Z",
"value": 70
}, {
"mytime": "2015-12-01T23:25:00.000Z",
"value": 64
}, {
"mytime": "2015-12-01T23:30:00.000Z",
"value": 72
}, {
"mytime": "2015-12-01T23:35:00.000Z",
"value": 75
}, {
"mytime": "2015-12-01T23:40:00.000Z",
"value": 71
}, {
"mytime": "2015-12-01T23:45:00.000Z",
"value": 80
}, {
"mytime": "2015-12-01T23:50:00.000Z",
"value": 83
}, {
"mytime": "2015-12-01T23:55:00.000Z",
"value": 86
}, {
"mytime": "2015-12-02T00:00:00.000Z",
"value": 80
}, {
"mytime": "2015-12-02T00:05:00.000Z",
"value": 85
}];
var parseDate = d3.time.format("%Y-%m-%dT%H:%M:%S.%LZ").parse;
data.forEach(function(d) {
d.mytime = parseDate(d.mytime);
});
//var margin = { top: 30, right: 30, bottom: 40, left:50 },
var margin = {
top: 30,
right: 30,
bottom: 40,
left: 50
},
height = 200,
width = 900;
var color = "green";
var xaxis_param = "mytime";
var yaxis_param = "value";
var params1 = {
margin: margin,
height: height,
width: width,
color: color,
xaxis_param: xaxis_param,
yaxis_param: yaxis_param
};
draw_graph(data, params1);
function draw_graph(data, params) {
var make_x_axis = function() {
return d3.svg.axis()
.scale(x_scale)
.orient("bottom")
.ticks(5);
};
var make_y_axis = function() {
return d3.svg.axis()
.scale(y_scale)
.orient("left")
.ticks(5);
};
//Get the margin
var xaxis_param = params.xaxis_param;
var yaxis_param = params.yaxis_param;
var color_code = params.color;
var margin = params.margin;
var height = params.height - margin.top - margin.bottom,
width = params.width - margin.left - margin.right;
var x_extent = d3.extent(data, function(d) {
return d[xaxis_param]
});
var y_extent = d3.extent(data, function(d) {
return d[yaxis_param]
});
var x_scale = d3.time.scale()
.domain(x_extent)
.range([0, width]);
var y_scale = d3.scale.linear()
.domain([0, y_extent[1]])
.range([height, 0]);
var zoom = d3.behavior.zoom()
.x(x_scale)
.y(y_scale)
.on("zoom", zoomed);
//Line
var line = d3.svg.line()
.defined(function(d) {
return d[yaxis_param];
})
.x(function(d) {
return x_scale(d[xaxis_param]);
})
.y(function(d) {
return y_scale(d[yaxis_param]);
});
var lineRef = d3.svg.line()
.x(function(d) {
return x_scale(d[xaxis_param]);
})
.y(function(d) {
return y_scale(20);
});
var myChart = d3.select('body').append('svg')
.attr('id', 'graph')
.style('background', '#E7E0CB')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')')
.call(zoom)
.on("mousedown.zoom", null);
myChart.append("svg:rect")
.attr("width", width)
.attr("height", height)
.attr("class", "plot");
var legend = myChart.append("g")
.attr("class", "legend")
.attr("transform", "translate(" + 5 + "," + (height - 25) + ")")
legend.append("rect")
.style("fill", color_code)
.attr("width", 20)
.attr("height", 20);
legend.append("text")
.text(yaxis_param)
.attr("x", 25)
.attr("y", 12);
var vAxis = d3.svg.axis()
.scale(y_scale)
.orient('left')
.ticks(5)
var hAxis = d3.svg.axis()
.scale(x_scale)
.orient('bottom')
.ticks(5);
var majorAxis = d3.svg.axis()
.scale(x_scale)
.orient('bottom')
.ticks(d3.time.day, 1)
.tickSize(-height)
.outerTickSize(0);
myChart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(hAxis);
myChart.append("g")
.attr("class", "x axis major")
.attr("transform", "translate(0," + height + ")")
.call(majorAxis);
myChart.append("g")
.attr("class", "y axis")
.call(vAxis);
var circlePoint = myChart.selectAll('circle')
.data(data)
.enter()
.append("circle");
var circleAttributes = circlePoint
.attr("cx", function (d) { return x_scale(d[xaxis_param]); })
.attr("cy", function (d) { return y_scale(d[yaxis_param]); })
.attr("r", 3)
.style("fill", "none")
.style("stroke", "red");
var clip = myChart.append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", height);
var chartBody = myChart.append("g")
.attr("clip-path", "url(#clip)");
chartBody.append("svg:path")
.datum(data)
.attr('class', 'line')
.attr("d", line)
.attr('stroke', color_code)
.attr('stroke-width', 1)
.attr('fill', 'none');
chartBody
.append('svg:path')
.datum(data)
.attr('class', 'line1')
.attr("d", lineRef)
.attr('stroke', 'blue')
.attr('stroke-width', 1)
.style("stroke-dasharray", ("3, 3"))
.attr('fill', 'none');
function zoomed() {
myChart.select(".x.axis").call(hAxis);
myChart.select(".y.axis").call(vAxis);
myChart.select(".x.axis.major").call(majorAxis);
myChart.select(".line")
.attr("class", "line")
.attr("d", line);
myChart.select(".line1")
.attr("class", "line1")
.attr("d", lineRef);
circlePoint
.attr("cx", function (d) { return x_scale(d[xaxis_param]); })
.attr("cy", function (d) { return y_scale(d[yaxis_param]); });
}
}
You only have to change the definition of your zoom behavior such that it will not update y_scale while zooming.
var zoom = d3.behavior.zoom()
.x(x_scale)
//.y(y_scale)
.on("zoom", zoomed);
I am quiet new to d3.js and currently working on plotting a time series with zoom capabilities. I was able to get the code working for zooming a single line on the graph but as soon as i add another line (reference line in dashes) that line remains stationary.
I tried a few variations in how i am trying to call the lines in my "zoomed()" function but to no avail .
Following is the link to jsfiddle as looking at the example might give you a better idea on what i mean:
https://jsfiddle.net/adityap16/x78zgwux/14/
Also attached is the code:
var data = [{
"mytime": "2015-12-01T23:10:00.000Z",
"value": 64
}, {
"mytime": "2015-12-01T23:15:00.000Z",
"value": 67
}, {
"mytime": "2015-12-01T23:20:00.000Z",
"value": 70
}, {
"mytime": "2015-12-01T23:25:00.000Z",
"value": 64
}, {
"mytime": "2015-12-01T23:30:00.000Z",
"value": 72
}, {
"mytime": "2015-12-01T23:35:00.000Z",
"value": 75
}, {
"mytime": "2015-12-01T23:40:00.000Z",
"value": 71
}, {
"mytime": "2015-12-01T23:45:00.000Z",
"value": 80
}, {
"mytime": "2015-12-01T23:50:00.000Z",
"value": 83
}, {
"mytime": "2015-12-01T23:55:00.000Z",
"value": 86
}, {
"mytime": "2015-12-02T00:00:00.000Z",
"value": 80
}, {
"mytime": "2015-12-02T00:05:00.000Z",
"value": 85
}];
var parseDate = d3.time.format("%Y-%m-%dT%H:%M:%S.%LZ").parse;
data.forEach(function(d) {
d.mytime = parseDate(d.mytime);
});
//var margin = { top: 30, right: 30, bottom: 40, left:50 },
var margin = {
top: 30,
right: 30,
bottom: 40,
left: 50
},
height = 200,
width = 900;
var color = "green";
var xaxis_param = "mytime";
var yaxis_param = "value";
var params1 = {
margin: margin,
height: height,
width: width,
color: color,
xaxis_param: xaxis_param,
yaxis_param: yaxis_param
};
draw_graph(data, params1);
function draw_graph(data, params) {
var make_x_axis = function() {
return d3.svg.axis()
.scale(x_scale)
.orient("bottom")
.ticks(5);
};
var make_y_axis = function() {
return d3.svg.axis()
.scale(y_scale)
.orient("left")
.ticks(5);
};
//Get the margin
var xaxis_param = params.xaxis_param;
var yaxis_param = params.yaxis_param;
var color_code = params.color;
var margin = params.margin;
var height = params.height - margin.top - margin.bottom,
width = params.width - margin.left - margin.right;
var x_extent = d3.extent(data, function(d) {
return d[xaxis_param]
});
var y_extent = d3.extent(data, function(d) {
return d[yaxis_param]
});
var x_scale = d3.time.scale()
.domain(x_extent)
.range([0, width]);
var y_scale = d3.scale.linear()
.domain([0, y_extent[1]])
.range([height, 0]);
var zoom = d3.behavior.zoom()
.x(x_scale)
.y(y_scale)
.on("zoom", zoomed);
//Line
var line = d3.svg.line()
.defined(function(d) {
return d[yaxis_param];
})
.x(function(d) {
return x_scale(d[xaxis_param]);
})
.y(function(d) {
return y_scale(d[yaxis_param]);
});
var lineRef = d3.svg.line()
.x(function(d) {
return x_scale(d[xaxis_param]);
})
.y(function(d) {
return y_scale(20);
});
var myChart = d3.select('body').append('svg')
.attr('id', 'graph')
.style('background', '#E7E0CB')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')')
.call(zoom);
myChart.append("svg:rect")
.attr("width", width)
.attr("height", height)
.attr("class", "plot");
var legend = myChart.append("g")
.attr("class", "legend")
.attr("transform", "translate(" + 5 + "," + (height - 25) + ")")
legend.append("rect")
.style("fill", color_code)
.attr("width", 20)
.attr("height", 20);
legend.append("text")
.text(yaxis_param)
.attr("x", 25)
.attr("y", 12);
var vAxis = d3.svg.axis()
.scale(y_scale)
.orient('left')
.ticks(5)
var hAxis = d3.svg.axis()
.scale(x_scale)
.orient('bottom')
.ticks(5);
var majorAxis = d3.svg.axis()
.scale(x_scale)
.orient('bottom')
.ticks(d3.time.day, 1)
.tickSize(-height)
.outerTickSize(0);
myChart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(hAxis);
myChart.append("g")
.attr("class", "x axis major")
.attr("transform", "translate(0," + height + ")")
.call(majorAxis);
myChart.append("g")
.attr("class", "y axis")
.call(vAxis);
var clip = myChart.append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", height);
var chartBody = myChart.append("g")
.attr("clip-path", "url(#clip)");
chartBody.append("svg:path")
.datum(data)
.attr('class', 'line')
.attr("d", line)
.attr('stroke', color_code)
.attr('stroke-width', 1)
.attr('fill', 'none');
chartBody
.append('svg:path')
.datum(data)
.attr('class', 'line')
.attr("d", lineRef)
.attr('stroke', 'blue')
.attr('stroke-width', 1)
.style("stroke-dasharray", ("3, 3"))
.attr('fill', 'none');
function zoomed() {
myChart.select(".x.axis").call(hAxis);
myChart.select(".y.axis").call(vAxis);
myChart.select(".x.axis.major").call(majorAxis);
myChart.select('path.line').attr('d', lineRef);
myChart.select('path.line').attr('d', line);
}
}
I was also wondering how to zoom in or out if instead of mouse roll over, i could just select that part of the data and that part zooms in which is kind of like context via brushing https://bl.ocks.org/mbostock/1667367
But i wanted to make it without the second graph.
Thanks!
I have been trying this for a couple of days but not able to find solution for it. I have a time series data which comes every 5 minutes and can extend for days. I am quiet new to D3 and Java Script. It took me some time to build it. Following is a link of the jsfiddle, i have been working on:
https://jsfiddle.net/adityap16/d61gtadm/2/
Code:
var data = [
{"mytime": "2015-12-01T11:10:00.000Z", "value": 64},
{"mytime": "2015-12-01T11:15:00.000Z", "value": 67},
{"mytime": "2015-12-01T11:20:00.000Z", "value": 70},
{"mytime": "2015-12-01T11:25:00.000Z", "value": 64},
{"mytime": "2015-12-01T11:30:00.000Z", "value": 72},
{"mytime": "2015-12-01T11:35:00.000Z", "value": 75},
{"mytime": "2015-12-01T11:40:00.000Z", "value": 71},
{"mytime": "2015-12-01T11:45:00.000Z", "value": 80}
];
var parseDate = d3.time.format("%Y-%m-%dT%H:%M:%S.%LZ").parse;
data.forEach(function(d) {
d.mytime = parseDate(d.mytime);
});
//var margin = { top: 30, right: 30, bottom: 40, left:50 },
var margin = { top: 30, right: 30, bottom: 40, left:50 },
height = 200,
width = 800;
var color = "green";
var xaxis_param = "mytime";
var yaxis_param = "value"
var params1 = {margin:margin,height:height,width:width, color: color, xaxis_param:xaxis_param, yaxis_param :yaxis_param};
draw_graph(data,params1);
function draw_graph(data,params){
//Get the margin
var xaxis_param = params.xaxis_param;
var yaxis_param = params.yaxis_param;
var color_code = params.color;
var margin = params.margin;
var height = params.height - margin.top - margin.bottom,
width = params.width - margin.left - margin.right;
console.log("1")
var x_extent = d3.extent(data, function(d){
return d[xaxis_param]});
console.log("2")
var y_extent = d3.extent(data, function(d){
return d[yaxis_param]});
var x_scale = d3.time.scale()
.domain(x_extent)
.range([0,width]);
console.log("3")
var y_scale = d3.scale.linear()
.domain([0,y_extent[1]])
.range([height,0]);
//Line
var lineGen = d3.svg.line()
.x(function (d) {
return x_scale(d[xaxis_param]);
})
.y(function (d) {
return y_scale(d[yaxis_param]);
});
var myChart = d3.select('body').append('svg')
.style('background', '#E7E0CB')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', 'translate('+ margin.left +', '+ margin.top +')');
myChart
.append('svg:path')
.datum(data)
.attr('class', 'line')
.attr("d",lineGen)
.attr('stroke', color_code)
.attr('stroke-width', 1)
.attr('fill', 'none');
var legend = myChart.append("g")
.attr("class", "legend")
.attr("transform", "translate(" + 5 + "," + (height - 25) + ")")
legend.append("rect")
.style("fill", color_code)
.attr("width", 20)
.attr("height", 20);
legend.append("text")
.text(yaxis_param)
.attr("x", 25)
.attr("y", 12);
var vGuideScale = d3.scale.linear()
.domain([0,y_extent[1]])
.range([height, 0])
var vAxis = d3.svg.axis()
.scale(vGuideScale)
.orient('left')
.ticks(5)
var hAxis = d3.svg.axis()
.scale(x_scale)
.orient('bottom')
.ticks(d3.time.minute, 5);
myChart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(hAxis);
myChart.append("g")
.attr("class", "y axis")
.call(vAxis)
}
I am currently stumped with two problems.
a.)I have to place vertical markers for end of each day. How to place vertical lines to show these transition (markers) from one day to another (just a simple black vertical line would do?
b.) Can we deal with missing data suppose i don't get data for a day, can i get blanks for that period of time and straight away plot the next day data. (This one is not that important)?
Here is a working jsfiddle: https://jsfiddle.net/kmandov/d61gtadm/3/
This is how you can achieve the desired results:
Problem a.) Vertical ticks for each day:
First, create a new major axis and set the tickSize to -height, so the ticks go all the way through your chart:
var majorAxis = d3.svg.axis()
.scale(x_scale)
.orient('bottom')
.ticks(d3.time.day, 1)
.tickSize(-height);
and then create the corresponding svg element:
myChart.append("g")
.attr("class", "x axis major")
.attr("transform", "translate(0," + height + ")")
.call(majorAxis);
Then remove the label for the major ticks(you don't want them to overlap):
.axis.major text {
display: none;
}
Here is a nice example by M. Bostock himself: http://bl.ocks.org/mbostock/4349486
Problem B.) Missing Data
Set .defined() on the line:
var lineGen = d3.svg.line()
.defined(function(d) { return d[yaxis_param]; })
.x(function (d) {
return x_scale(d[xaxis_param]);
})
.y(function (d) {
return y_scale(d[yaxis_param]);
});
Here is an example on how to deal with gaps in your data: http://bl.ocks.org/mbostock/3035090
I am trying to make a line chart in d3, with time on x-axis. I am using json data in variable. I used d3.time.format() function to format the time, but it gives me above error. I am learning d3 so please help. my code is :
<div id="viz"></div>
<script>
var width = 640;
var height = 480;
var margin = {top: 30, right: 20, bottom: 30, left: 50},
width = 600 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().domain([height, 0]);
var xAxis = d3.svg.axis().scale(x).orient("bottom");
var yAxis = d3.svg.axis().scale(y).orient("left");
var data = [
{ "at": "2014-11-18T07:29:03.859Z", "value": 0.553292},
{ "at": "2014-11-18T07:28:53.859Z", "value": 0.563292},
{ "at": "2014-11-18T07:28:43.859Z", "value": 0.573292},
{ "at": "2014-11-18T07:28:33.859Z", "value": 0.583292},
{ "at": "2014-11-18T07:28:13.859Z", "value": 0.553292},
{ "at": "2014-11-18T07:28:03.859Z", "value": 0.563292}];
var line = d3.svg.line()
.x(function(d, i) { return x(d.x_axis); })
.y(function(d, i) { return y(d.y_axis); })
.interpolate("linear");
var vis = d3.select("#viz")
.append("svg:svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g").attr("transform","translate(" + margin.left + "," + margin.top + ")");
data.forEach(function(d) {
d.xAxis = d3.time.format("%d-%b-%y").parse(d.xAxis);
d.yAxis = +d.value;
});
x.domain(d3.extent(data, function(d) { return d.x_axis; }));
y.domain(d3.extent(data, function(d) { return d.y_axis; }));
vis.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
vis.append("g")
.attr("class", "y axis")
.call(yAxis);
vis.append("svg:path")
.datum(data)
.attr("class", "line")
.attr("d", line);
There are several issues in your code so I have created a new one below with some comments on the changes.
<style>
/* You need some styling for your line */
.line{
stroke:steelblue;
fill:none
}
</style>
<script>
var width = 640;
var height = 480;
var margin = {top: 30, right: 20, bottom: 30, left: 50},
width = 600 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
var x = d3.time.scale().range([0, width]);
// You had a mistake filling the domain structure of your scale.
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 data = [
{ "at": "2014-11-18T07:29:03.859Z", "value": 0.553292},
{ "at": "2014-11-18T07:28:53.859Z", "value": 0.563292},
{ "at": "2014-11-18T07:28:43.859Z", "value": 0.573292},
{ "at": "2014-11-18T07:28:33.859Z", "value": 0.583292},
{ "at": "2014-11-18T07:28:13.859Z", "value": 0.553292},
{ "at": "2014-11-18T07:28:03.859Z", "value": 0.563292}];
//You were using non existing variables
var line = d3.svg.line()
.x(function(d) { return x(d.xAxis); })
.y(function(d) { return y(d.yAxis); })
.interpolate("linear");
var vis = d3.select("#viz")
.append("svg:svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g").attr("transform","translate(" + margin.left + "," + margin.top + ")");
//You are using ISO format, use the correct time parser
var iso = d3.time.format.utc("%Y-%m-%dT%H:%M:%S.%LZ");
data.forEach(function(d) {
d.xAxis = iso.parse(d.at); //You were parsing a non existing variable
d.yAxis = parseFloat(d.value); //You were parsing a non existing variable
});
console.log(data);
//The variables for the domain were not correct
x.domain(d3.extent(data, function(d) { return d.xAxis; }));
y.domain(d3.extent(data, function(d) { return d.yAxis; }));
vis.append("g").attr("class", "x axis").attr("transform", "translate(0," + height + ")").call(xAxis);
vis.append("g").attr("class", "y axis").call(yAxis);
vis.append("svg:path").datum(data).attr("class", "line").attr("d", line);
</script>
Let me know if this helps
Here's a fiddle which shows what I think you're after: http://jsfiddle.net/henbox/n9s542w0/1/
There were a couple of changes to make.
Firstly, there's some inconsistency about how you use d.y_axis vs d.yAxis (same with x) to set \ refer to the new elements you add to the data set which you want to plot. I've set these keys to d.y_axis and d.x_axis.
Next:
d.xAxis = d3.time.format("%d-%b-%y").parse(d.xAxis);
Your format here should refer to the input format, rather than the output, and you should be parsing d.at rather than d.xAxis (see this answer for more), so you should have:
d.x_axis = d3.time.format("%Y-%m-%dT%H:%M:%S.%LZ").parse(d.at);
Thirdly, when you append the line you should handle the data differently. Change:
vis.append("svg:path")
.datum(data)
.attr("class", "line")
.attr("d", line);
to
vis.append("svg:path")
.attr("class", "line")
.attr("d", line(data));
As per this similar example
And finally, you were setting the y domain twice but never setting the range. The line:
var y = d3.scale.linear().domain([height, 0]);
should read
var y = d3.scale.linear().range([height, 0]);