I'm trying to run an application for data visualization, I'm using D3.js, my code works but when I change the selected option, the graph change but go down and it goes down every change.
I have no idea where the problem is.
That's my code :
<!DOCTYPE html>
<html>
<head>
<title> Graphique </title>
<script src="http://d3js.org/d3.v4.min.js" charset="utf-8"></script>
<script src="https://d3js.org/d3-selection-multi.v1.min.js"></script>
</head>
<body>
<FORM>
<SELECT id="Nb" size="1" onchange="Changement()">
<option>Selection</option>
<option>NbCopie</option>
<option>NbTache</option>
<option>NbCopieBW</option>
<option>NbCopieCouleur</option>
<option>MtTotal</option>
</SELECT>
</FORM>
<div id="chart"></div>
<svg width="960" height="500"></svg>
<script>
function Changement() {
d3.selectAll("svg > *").remove();
d3.json("Data.json", function(error, data) {
var Nb = data.map(function(d) {
var x = document.getElementById('Nb');
var i = x.selectedIndex;
var text = x.options[i].text;
if (text == "NbCopie")
return d.NbCopie;
else if (text == "NbTache")
return d.NbTache;
else if (text == "NbCopieBW")
return d.NbCopieBW;
else if (text == " NbCopieCouleur")
return d.NbCopieCouleur;
else if (text == "MtTotal")
return d.MtTotal;
});
var maxNb = d3.max(Nb);
var svg = d3.select("svg"),
margin = {
top: 30,
right: 30,
bottom: 40,
left: 50
},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
var animateDuration = 700;
var animateDelay = 30;
var tooltip = d3.select('body').append('div')
.style('position', 'absolute')
.style('background', '#f4f4f4')
.style('padding', '5 15px')
.style('border', '1px #333 solid')
.style('border-raduis', '5px')
.style('opacity', '0')
var yScale = d3.scaleLinear()
.domain([0, maxNb])
.range([0, height])
var xScale = d3.scaleBand()
.domain(d3.range(0, Nb.length))
.range([0, width])
var colors = d3.scaleLinear()
.domain([0, Nb.length])
.range(['#0080FF', '#FF3333'])
var myChart = d3.select('#chart').append('svg')
.attr('width', width + margin.right + margin.left)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
.style('background', '#f4f4f4')
.selectAll('rect')
.data(Nb)
.enter().append('rect')
.style('fill', function(d, i) {
return colors(i);
})
.attr('width', xScale.bandwidth())
.attr('x', function(d, i) {
return xScale(i)
})
.attr('height', 0)
.attr('y', height)
.on('mouseover', function(d) {
tooltip.transition()
.style('opacity', 1)
tooltip.html(d)
.style('left', (d3.event.pageX) + 'px')
.style('top', (d3.event.pageY + 'px'))
d3.select(this).style('opacity', 0.5)
})
.on('mouseout', function(d) {
tooltip.transition()
.style('opacity', 0)
d3.select(this).style('opacity', 1)
})
myChart.transition()
.attr('height', function(d) {
return yScale(d);
})
.attr('y', function(d) {
return height - yScale(d);
})
.duration(animateDuration)
.delay(function(d, i) {
return i * animateDelay
})
.duration(1000)
.ease(d3.easeElastic)
var vScale = d3.scaleLinear()
.domain([0, maxNb])
.range([height, 0])
var vAxis = d3.axisLeft()
.scale(vScale)
.ticks(5)
.tickPadding(5)
var vGuide = d3.select('svg')
.append('g')
vAxis(vGuide)
vGuide.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
vGuide.selectAll('path')
.style('fill', 'none')
.style('stroke', '#000')
vGuide.selectAll('line')
.style('stroke', '#000')
var hScale = d3.scaleTime()
.domain(d3.extent(data, function(d) {
var parseDate = d3.timeParse("%Y%m%d");
Date_Id = parseDate(d.Date_Id);
return Date_Id;
}))
.range([0, width - 150])
var hAxis = d3.axisBottom()
.scale(hScale)
.ticks(d3.timeMonth)
var hGuide = d3.select('svg')
.append('g')
.attr("class", "axis axis--x")
.attr("transform", "translate(" + margin.left + "," + (height + margin.top) + ")")
.call(hAxis);
});
};
</script>
And here a screenshot of my problem:
first attempt
enter image description here
second attempt
enter image description here
and here is an extract of my JSON file
[{
"ConsoPhot_Id": "10148",
"idLotImport": 390,
"Date_Id": 20170201,
"Orga_Id": "203938",
"NbTache": 153,
"NbCopie": 798,
"NbCopieBW": 488,
"NbCopieCouleur": 310,
"MtTotal": 13.69
},
{
"ConsoPhot_Id": "10602",
"idLotImport": 391,
"Date_Id": 20161201,
"Orga_Id": "203938",
"NbTache": 153,
"NbCopie": 909,
"NbCopieBW": 779,
"NbCopieCouleur": 130,
"MtTotal": 7.93
},
{
"ConsoPhot_Id": "10905",
"idLotImport": 392,
"Date_Id": 20161101,
"Orga_Id": "203938",
"NbTache": 115,
"NbCopie": 515,
"NbCopieBW": 409,
"NbCopieCouleur": 106,
"MtTotal": 5.6
},
Don't append a new SVG every time you choose an option.
Thus, instead of:
var myChart = d3.select('#chart').append('svg')
.attr('width', width + margin.right + margin.left)
.attr('height', height + margin.top + margin.bottom)
.append('g')
//etc...
Simply do:
var myChart = svg.append('g')
//etc...
Here is a plunker with that change only, using the small JSON sample you provided: https://plnkr.co/edit/PMnNI4hoBz3Q2k5fQTp5?p=preview
PS: As I said in my comment, this code right now has a lot of problems, the main one being the fact that you're erasing everything inside the SVG just to paint it again, and the second one the fact that you are loading the same JSON every time you choose an option. That being said, you should reconsider a major refactor in this code. Have in mind that here I'm only answering the problem stated in your question.
Related
Hi everyone please help me below is my code. so actually I getting all bar color as black what my requirement is to generate bar color dynamically with different value different color gradient don't need space in between bar just need to plot bar chart with different color on basis of data I am providing**
var chartdata = [10, 21, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120,
135, 150, 165, 180, 200, 220, 240, 270, 300, 330, 370, 410
];
var margin = {
top: 30,
right: 10,
bottom: 30,
left: 50
}
var height = 400 - margin.top - margin.bottom,
width = 720 - margin.left - margin.right,
barWidth = 40,
barOffset = 20;
var dynamicColor;
var yScale = d3.scaleLinear()
.domain([0, d3.max(chartdata)])
.range([0, height])
var xScale = d3.scaleBand()
.domain(d3.range(0, chartdata.length))
.range([0, width])
var colors = d3.scaleLinear()
.domain([0, chartdata.length * .33, chartdata.length * .66, chartdata.length])
.range(['#d6e9c6', '#bce8f1', '#faebcc', '#ebccd1'])
var awesome = d3.select('#bar-chart').append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.style('background', '#bce8f1')
.append('g')
.attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')')
.selectAll('rect').data(chartdata)
.enter().append('rect')
.attr('width', xScale.bandwidth())
.attr('x', function(data, i) {
return xScale(i);
})
.attr('height', 0)
.attr('y', height)
.on('mouseover', function(data) {
dynamicColor = this.style.fill;
d3.select(this)
.style('fill', '#3c763d')
})
.on('mouseout', function(data) {
d3.select(this)
.style('fill', dynamicColor)
})
awesome.transition()
.attr('height', function(data) {
return yScale(data);
})
.attr('y', function(data) {
return height - yScale(data);
})
.delay(function(data, i) {
return i * 20;
})
.duration(2000)
.ease(d3.easeElastic)
var verticalGuideScale = d3.scaleLinear()
.domain([0, d3.max(chartdata)])
.range([height, 0])
var vAxis = d3.axisLeft(verticalGuideScale)
.ticks(10)
var verticalGuide = d3.select('svg').append('g')
vAxis(verticalGuide)
verticalGuide.attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')')
verticalGuide.selectAll('path')
.styles({
fill: 'none',
stroke: "#3c763d"
})
verticalGuide.selectAll('line')
.styles({
stroke: "#3c763d"
})
var hAxis = d3.axisBottom(xScale)
.ticks(chartdata.size)
var horizontalGuide = d3.select('svg').append('g')
hAxis(horizontalGuide)
horizontalGuide.attr('transform', 'translate(' + margin.left + ', ' + (height + margin.top) + ')')
horizontalGuide.selectAll('path')
.styles({
fill: 'none',
stroke: "#3c763d"
})
horizontalGuide.selectAll('line')
.styles({
stroke: "#3c763d"
});
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-selection-multi.v1.min.js"></script>
<div class="someclass">
<h2>barchart</h2>
<div id="bar-chart">
</div>
</div>
Hi try with below code
var chartdata = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120,
135, 150, 165, 180, 200, 220, 240, 270, 300, 330, 370, 410
];
var margin = {
top: 30,
right: 10,
bottom: 30,
left: 50
}
var height = 400 - margin.top - margin.bottom,
width = 720 - margin.left - margin.right,
barWidth = 40,
barOffset = 20;
var dynamicColor;
var yScale = d3.scaleLinear()
.domain([0, d3.max(chartdata)])
.range([0, height])
var xScale = d3.scaleBand()
.domain(d3.range(0, chartdata.length))
.range([0, width])
var colors = d3.scaleLinear()
.domain([0, chartdata.length * .33, chartdata.length * .66, chartdata.length])
.range(['#d6e9c6', '#bce8f1', '#faebcc', '#ebccd1'])
var awesome = d3.select('#bar-chart').append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.style('background', '#bce8f1')
.append('g')
.attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')')
.selectAll('rect').data(chartdata)
.enter().append('rect')
.styles({
'fill': function(data, i) {
return colors(i);
},
'stroke': '#31708f',
'stroke-width': '1'
})
.attr('width', xScale.bandwidth())
.attr('x', function(data, i) {
return xScale(i);
})
.attr('height', 0)
.attr('y', height)
.on('mouseover', function(data) {
dynamicColor = this.style.fill;
d3.select(this)
.style('fill', '#3c763d')
})
.on('mouseout', function(data) {
d3.select(this)
.style('fill', dynamicColor)
})
awesome.transition()
.attr('height', function(data) {
return yScale(data);
})
.attr('y', function(data) {
return height - yScale(data);
})
.delay(function(data, i) {
return i * 20;
})
.duration(2000)
.ease(d3.easeElastic)
var verticalGuideScale = d3.scaleLinear()
.domain([0, d3.max(chartdata)])
.range([height, 0])
var vAxis = d3.axisLeft(verticalGuideScale)
.ticks(10)
var verticalGuide = d3.select('svg').append('g')
vAxis(verticalGuide)
verticalGuide.attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')')
verticalGuide.selectAll('path')
.styles({
fill: 'none',
stroke: "#3c763d"
})
verticalGuide.selectAll('line')
.styles({
stroke: "#3c763d"
})
var hAxis = d3.axisBottom(xScale)
.ticks(chartdata.size)
var horizontalGuide = d3.select('svg').append('g')
hAxis(horizontalGuide)
horizontalGuide.attr('transform', 'translate(' + margin.left + ', ' + (height + margin.top) + ')')
horizontalGuide.selectAll('path')
.styles({
fill: 'none',
stroke: "#3c763d"
})
horizontalGuide.selectAll('line')
.styles({
stroke: "#3c763d"
});
i just added
.styles({
'fill': function(data, i) {
return colors(i);
},
'stroke': '#31708f',
'stroke-width': '1'
})
I have been following the block that uses hexagonal binning of random points with the normal distribution but instead trying to tailor it to the exponential distribution.
The code runs, but the output seems to show a mirror along the x-axis. That is, the points are all clustered along the upper-left instead of lower-left. I've been playing with the transform function but can't quite get it. What am I missing? JSFiddle
<!DOCTYPE html>
<style>
.hexagon {
stroke: #000;
stroke-width: 0.5px;
}
</style>
<svg width="500" height="200"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-hexbin.v0.2.min.js"></script>
<script>
var svg = d3.select("svg"),
margin = {top: 20, right: 20, bottom: 30, left: 40},
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 randomX = d3.randomExponential(1 / 30),
randomY = d3.randomExponential(1 / 30),
points = d3.range(2000).map(function() { return [randomX(), randomY()]; });
var color = d3.scaleSequential(d3.interpolateLab("white", "steelblue"))
.domain([0, 20]);
var hexbin = d3.hexbin()
.radius(5)
.extent([[0, 0], [width, height]]);
var x = d3.scaleLinear()
.domain([0, width])
.range([0, width]);
var y = d3.scaleLinear()
.domain([0, height])
.range([height, 0]);
g.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
g.append("g")
.attr("class", "hexagon")
.attr("clip-path", "url(#clip)")
.selectAll("path")
.data(hexbin(points))
.enter().append("path")
.attr("d", hexbin.hexagon())
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
.attr("fill", function(d) { return color(d.length); });
</script>
You set your scales, but you never use them:
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
})
Solution: use your scales:
.attr("transform", function(d) {
return "translate(" + x(d.x) + "," + y(d.y) + ")";
//scales here --------^--------------^
})
Here is your code with that change:
var svg = d3.select("svg"),
margin = {
top: 20,
right: 20,
bottom: 30,
left: 40
},
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 randomX = d3.randomExponential(1 / 30),
randomY = d3.randomExponential(1 / 30),
points = d3.range(2000).map(function() {
return [randomX(), randomY()];
});
var color = d3.scaleSequential(d3.interpolateLab("white", "steelblue"))
.domain([0, 20]);
var hexbin = d3.hexbin()
.radius(5)
.extent([
[0, 0],
[width, height]
]);
var x = d3.scaleLinear()
.domain([0, width])
.range([0, width]);
var y = d3.scaleLinear()
.domain([0, height])
.range([height, 0]);
g.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
g.append("g")
.attr("class", "hexagon")
.attr("clip-path", "url(#clip)")
.selectAll("path")
.data(hexbin(points))
.enter().append("path")
.attr("d", hexbin.hexagon())
.attr("transform", function(d) {
return "translate(" + x(d.x) + "," + y(d.y) + ")";
})
.attr("fill", function(d) {
return color(d.length);
});
.hexagon {
stroke: #000;
stroke-width: 0.5px;
}
<svg width="500" height="200"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-hexbin.v0.2.min.js"></script>
I'm working on d3.js v4 and im trying to load external data from data.tsv file but its not loading, here is my code:
var bardata = [];
d3.tsv('data.tsv', function(){
for (key in data){
bardata.push(data[key].year.value)
}
var margin = {top:30, right:30, bottom:40, left:50}
var height = 400 - margin.top - margin.bottom,
width = 400 - margin.left - margin.right,
barWidth = 50,
barOffset = 5;
var tempColor;
var yScale = d3.scaleLinear()
.domain([0, d3.max(bardata)])
.range([0, height]);
var xScale = d3.scaleBand()
.domain(d3.range(0, bardata.length))
.padding(0.1)
.range([0, width]);
var tooltip = d3.select('body').append('div')
.style('position', 'absolute')
.style('padding', '0 10px')
.style('background', 'white')
.style('opacity', 0)
var myChart = d3.select('#chart').append('svg')
.style('background', '#E7E0CB')
.attr('width', width + margin.right + margin.left)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', 'translate('+ margin.left +', '+ margin.top +')')
.style('background', '#C9D7D6')
.selectAll('rect').data(bardata)
.enter().append('rect')
.style('fill', '#C61C6F')
.attr('width', xScale.bandwidth())
.attr('x', function(d, i) {
return xScale(i);
})
.attr('height', 0)
.attr('y', height)
.on('mouseover', function(d){
d3.select(this)
.style('opacity', 0.5)
})
.on('mouseleave', function(d){
d3.select(this)
.style('opacity', 1)
})
.on('mouseover', function(d){
tooltip.transition()
.style('opacity', 0.9)
tooltip.html(d)
.style('left', (d3.event.pageX - 35) + 'px')
.style('top', (d3.event.pageY - 30) + 'px')
tempColor = this.style.fill;
d3.select(this)
.style('opacity', 0.5)
.style('fill', 'yellow')
})
.on('mouseleave', function(d){
tempColor = this.style.fill;
d3.select(this)
.style('opacity', 1)
.style('fill', '#C61C6F')
})
myChart.transition()
.attr('height', function(d){
return yScale(d);
})
.attr('y', function(d){
return height - yScale(d);
})
.delay(function(d, i){
return i * 20;
})
.duration(1000)
.ease(d3.easeElastic)
var vGuideScale = d3.scaleLinear()
.domain([0, d3.max(bardata)])
.range([0, height]);
var vAxis = d3.axisLeft(vGuideScale).ticks(10)
var vGuide = d3.select('svg').append('g')
vAxis(vGuide)
vGuide.attr('transform', 'translate('+ margin.left +', '+ margin.top +')')
var hAxis = d3.axisBottom(xScale).tickValues(xScale.domain().filter(function(d,i){
return !(i % (bardata.length/5))
}))
var hGuide = d3.select('svg').append('g')
hAxis(hGuide)
hGuide.attr('transform', 'translate('+ margin.left +', '+ (height + margin.top) +')')
});
<!DOCTYPE html>
<html>
<head>
<title>Bar Chart</title>
<meta charset="8-UTF">
<link rel="stylesheet" src="css/style.css"> </head>
<body>
<div class="container">
<h2>Bar Chart</h2>
<div id="chart"></div>
</div>
<script src="js/d3.min.js"></script>
<script src="js/main.js"></script>
</body>
</html>
and here is the data in my tsv file
year value
2010 23,499,201
2011 22,544,175
2012 24,061,655
2013 23,413,369
2014 27,144,494
2015 26,812,665
2016 30,377,832
its has no errors but nothing appears on the chart
The way you're trying to create your bar chart right now, getting rid of the nice array of objects d3.tsv creates for you and relying in a simple array of numbers, is not the adequate let alone the most convenient way to do it. For any seasoned D3 coder, it makes little sense. However, it's not my place giving lectures here.
That being said, I'll address only the current problems:
d3.tsv needs a parameter in the callback:
d3.tsv('data.tsv', function(data){
//parameter here -------------^
Don't put comma in your numbers. This is not accepted in any programming language I'm aware of:
23,499,201 ---> 23499201
Remember, as I said in your last question, to avoid the columns property:
for (key in data) {
if (key != "columns") bardata.push(data[key].value)
}
Convert the strings to numbers:
bardata.push(+data[key].value)
All together, this is your working code:
var data = d3.tsvParse(d3.select("#tsv").text());
var bardata = [];
for (key in data){
if(key != "columns") bardata.push(+data[key].value)
}
var margin = {top:30, right:30, bottom:40, left:50}
var height = 400 - margin.top - margin.bottom,
width = 400 - margin.left - margin.right,
barWidth = 50,
barOffset = 5;
var tempColor;
var yScale = d3.scaleLinear()
.domain([0, d3.max(bardata)])
.range([0, height]);
var xScale = d3.scaleBand()
.domain(d3.range(0, bardata.length))
.padding(0.1)
.range([0, width]);
var tooltip = d3.select('body').append('div')
.style('position', 'absolute')
.style('padding', '0 10px')
.style('background', 'white')
.style('opacity', 0)
var myChart = d3.select('body').append('svg')
.style('background', '#E7E0CB')
.attr('width', width + margin.right + margin.left)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', 'translate('+ margin.left +', '+ margin.top +')')
.style('background', '#C9D7D6')
.selectAll('rect').data(bardata)
.enter().append('rect')
.style('fill', '#C61C6F')
.attr('width', xScale.bandwidth())
.attr('x', function(d, i) {
return xScale(i);
})
.attr('height', 0)
.attr('y', height)
.on('mouseover', function(d){
d3.select(this)
.style('opacity', 0.5)
})
.on('mouseleave', function(d){
d3.select(this)
.style('opacity', 1)
})
.on('mouseover', function(d){
tooltip.transition()
.style('opacity', 0.9)
tooltip.html(d)
.style('left', (d3.event.pageX - 35) + 'px')
.style('top', (d3.event.pageY - 30) + 'px')
tempColor = this.style.fill;
d3.select(this)
.style('opacity', 0.5)
.style('fill', 'yellow')
})
.on('mouseleave', function(d){
tempColor = this.style.fill;
d3.select(this)
.style('opacity', 1)
.style('fill', '#C61C6F')
})
myChart.transition()
.attr('height', function(d){
return yScale(d);
})
.attr('y', function(d){
return height - yScale(d);
})
.delay(function(d, i){
return i * 20;
})
.duration(1000)
.ease(d3.easeElastic)
var vGuideScale = d3.scaleLinear()
.domain([0, d3.max(bardata)])
.range([0, height]);
var vAxis = d3.axisLeft(vGuideScale).ticks(10)
var vGuide = d3.select('svg').append('g')
vAxis(vGuide)
vGuide.attr('transform', 'translate('+ margin.left +', '+ margin.top +')')
var hAxis = d3.axisBottom(xScale).tickValues(xScale.domain().filter(function(d,i){
return !(i % (bardata.length/5))
}))
var hGuide = d3.select('svg').append('g')
hAxis(hGuide)
hGuide.attr('transform', 'translate('+ margin.left +', '+ (height + margin.top) +')')
pre{
display: none;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<pre id="tsv">year value
2010 23499201
2011 22544175
2012 24061655
2013 23413369
2014 27144494
2015 26812665
2016 30377832
</pre>
Again: I'm using a <pre> element to store the data. Don't simply copy/paste my snippet, as you did last time.
I am beginner in D3 and don't know a lot about it.
I am currently trying to plot a 2D line on a graph using D3. I have been successfully able to plot the line, add axis , and even add zoom capabilities to the plot.
I am stuck in making the line hinged to y axis such that you can't just click on it and move it left or right (Currently if you would run the jsfiddle you could click on it and move the plotted line). I would still want to zoom in or out . But it should remain hinged to the y axis. Please let me know if this clarifies my issue.
Thanks!
Link to JS fiddle:
https://jsfiddle.net/adityap16/4sts8nfs/2/
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 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);
}
}
Add this .on("mousedown.zoom", null) to disable panning:
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);//disable panning
working code here
I am new D3 and i am trying to draw multiple plots based on incoming data. Here i have tried plotting one of them and will add 4 more like these on the same page.
Following is my code so far:
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 margin = { top: 30, right: 30, bottom: 40, left:50 };
var height = 200 - margin.top - margin.bottom,
width = 800 - margin.left - margin.right;
console.log("1")
var parseDate = d3.time.format("%Y-%m-%dT%H:%M:%S.%LZ").parse;
data.forEach(function(d) {
d.mytime = parseDate(d.mytime);
});
var x_extent = d3.extent(data, function(d){
return d.mytime});
console.log("2")
var y_extent = d3.extent(data, function(d){
return d.value});
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) {
console.log(d.date)
return x_scale(d.mytime);
})
.y(function (d) {
return y_scale(d.value);
});
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 +')')
.append('svg:path')
.datum(data)
.attr('class', 'line')
.attr("d",lineGen)
.attr("data-legend","pulse")
.attr('stroke', 'green')
.attr('stroke-width', 0.5)
.attr('fill', 'none');
var vGuideScale = d3.scale.linear()
.domain([0,y_extent[1]])
.range([height, 0])
var vAxis = d3.svg.axis()
.scale(vGuideScale)
.orient('left')
// .tickFormat("") //For removing values
.ticks(5)
var vGuide = d3.select('svg').append('g')
vAxis(vGuide)
vGuide.attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')')
vGuide.selectAll('path')
.style({ fill: 'none', stroke: "#000"})
vGuide.selectAll('line')
.style({ stroke: "#000"})
console.log("4")
d3.select('svg').append('g')
.append("text")
.attr("transform", "rotate(-90)")
.attr("y",6)
.attr("x",-50)
.attr("dy", ".51em")
.attr("font-size", "10px")
.style("text-anchor", "end")
.attr("fill", "green")
.text("Value");
console.log("5")
var hAxis = d3.svg.axis()
.scale(x_scale)
.orient('bottom')
.ticks(d3.time.minute, 5);
var hGuide = d3.select('svg').append('g')
hAxis(hGuide)
hGuide.attr('transform', 'translate(' + margin.left + ', ' + (height + margin.top) + ')')
hGuide.selectAll('path')
.style({ fill: 'none', stroke: "#000"})
hGuide.selectAll('line')
.style({ stroke: "#000"})
I have few doubts regarding formatting of the code:
How to add legend to the code when i tried the following link but i am getting error on using the call function
http://bl.ocks.org/ZJONSSON/3918369
How to reduce reduce tick size on y axis?
Thanks
The answer here is to use css to control the style of your components (including font sizes). For instance, for all fonts in your SVG tag:
svg {
font: 10px sans-serif;
}
Second, building a legend can be pretty simple:
var legend = myChart.append("g")
.attr("class", "legend")
.attr("transform", "translate(" + 5 + "," + (height - 25) + ")")
legend.append("rect")
.style("fill", "green")
.attr("width", 20)
.attr("height", 20);
legend.append("text")
.text("My Awesome Legend Item")
.attr("x", 25)
.attr("y", 12);
Full code sample:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3#3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
<style>
svg {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<script>
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 margin = {
top: 30,
right: 30,
bottom: 40,
left: 50
};
var height = 200 - margin.top - margin.bottom,
width = 800 - margin.left - margin.right;
console.log("1")
var parseDate = d3.time.format("%Y-%m-%dT%H:%M:%S.%LZ").parse;
data.forEach(function(d) {
d.mytime = parseDate(d.mytime);
});
var x_extent = d3.extent(data, function(d) {
return d.mytime
});
console.log("2")
var y_extent = d3.extent(data, function(d) {
return d.value
});
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) {
console.log(d.date)
return x_scale(d.mytime);
})
.y(function(d) {
return y_scale(d.value);
});
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("data-legend", "pulse")
.attr('stroke', 'green')
.attr('stroke-width', 0.5)
.attr('fill', 'none');
var legend = myChart.append("g")
.attr("class", "legend")
.attr("transform", "translate(" + 5 + "," + (height - 25) + ")")
legend.append("rect")
.style("fill", "green")
.attr("width", 20)
.attr("height", 20);
legend.append("text")
.text("My Awesome Legend Item")
.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')
// .tickFormat("") //For removing values
.ticks(5)
var vGuide = d3.select('svg').append('g').attr("class", "y axis")
vAxis(vGuide)
vGuide.attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')')
console.log("4")
d3.select('svg').append('g')
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("x", -50)
.attr("dy", ".51em")
.attr("font-size", "10px")
.style("text-anchor", "end")
.attr("fill", "green")
.text("Value");
console.log("5")
var hAxis = d3.svg.axis()
.scale(x_scale)
.orient('bottom')
.ticks(d3.time.minute, 5);
var hGuide = d3.select('svg').append('g').attr("class", "x axis")
hAxis(hGuide)
hGuide.attr('transform', 'translate(' + margin.left + ', ' + (height + margin.top) + ')')
</script>
</body>
</html>
You can control the length of the ticks via the tickSize setter
Like this:
var axis = d3.svg.axis()
.scale(scale)
.orient("right")
.ticks(2)
.tickSize(10)
.tickFormat(formatPercent);
and then:
svg.append("g")
.attr("class", "y axis")
.call(axis);