D3: scale.domain is not a function - d3.js

I'm totally newbie with D3.js and I've got a problem which returns me the message: "scale.domain is not a function".
I have made a component to build a Scatter Plot Graphic. In it's code there is no any call to the instrucction "scale.domain".
Here is the code:
import React, {Component} from "react";
import {Determinator, MultiLang} from "react-multi-language";
import * as d3 from "d3";
class ScatterPlotGraphics extends Component{
/**
* Some of the props received are mandatory and others not. Between mandatory properties we've got:
* idContainer: Name of the id container. This number must be unique for the web page where we draw the graphic
* lang: language of presentation of text
* data: Array of json objects with the information needed to build the graphic
* total_points: Total points of a team which are needed to make some calculus
*
* #param {*} props
*/
constructor(props){
super();
this.props = props;
this.state = {
loaded: true,
margin: {
top: 20,
right: 20,
bottom: 30,
left: 40
},
width: 560,
height: 360
};
}
componentDidMount(){
let canvas = this.setCanvas();
let axis = this.setAxes();
this.setAxesToCanvas(canvas, axis);
this.setPointsToCanvas(canvas, this.state.data);
}
setAxes(){
let xRange = [0, this.state.width];
let yRange = [this.state.height, 0];
let xAxis = d3.axisBottom(xRange).tickFormat(function(d) { return d.p2_p; });
let yAxis = d3.axisLeft(yRange).tickFormat(function (d) { return d.p3_p; });
return {"xAxis" : xAxis, "yAxis" : yAxis};
}
setAxesToCanvas(canvas, axis){
//Add x-axis to the canvas
canvas.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0, " + this.state.height + ")") //move axis to the bottom of canvas
.call(axis.xAxis)
.append("text")
.append("class", "label")
.attr("x", this.state.width)
.attr("y", -6)
.style("text-anchor", "end") //right-justify text
.text("%2P");
//Add y-axis to the canvas
canvas.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("class", "label")
.attr("tranform", "rotate(-90)") //Although axis is rotated, text is not
.attr("y", 15)
.style("text-anchor", "end")
.text("%3P");
}
setCanvas(){
let margin = this.state.margin;
// Add the visualization svg canvas to the container <div>
let svg = d3.select("#scatterplot").style("background-color", "#091E36");
svg.attr("height", this.state.height);
svg.attr("width", this.state.width);
svg.style("color", "#FFFFFF");
svg.append("p").text("Hola, cómo estamos?");
return svg;
//return canvas;
}
setPointsToCanvas(canvas, data){
canvas.selectAll(".dot")
.data(data)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 5.5) //Radius size, could map to another dimension
.attr("cx", function(d) { return xScale(d.p2_p); }) //x position
.attr("cy", function(d) { return yScale(d.p3_p); }) //y position
.style("fill", "green");
}
render(){
return(
<div>
{
(this.state.loaded) ?
<div id="scatterplot"></div>
:
<h5>
<Determinator>
{{
es: "Cargando datos ...",
en: "Loading data ..."
}}
</Determinator>
</h5>
}
<MultiLang lang = {this.props.lang} />
</div>
);
};
};
module.exports.ScatterPlotGraphics = ScatterPlotGraphics;
When I try to access to the webpage which contains this component I've got this error in the console:
If I deploy the error line "TypeError: scale.domain is not a function", we can see that there is a reference in line 51 of the code.
If we check the code, we can see that in 51 line there is no any reference to "scale.domain"
How is that possible? What am I doing wrong?
Edit I:
I have modified the function setAxes, being like this:
setAxes(data){
let xRange = [0, this.state.width];
let yRange = [this.state.height, 0];
let xScale = d3.scaleLinear()
.domain([ d3.min(data, function(d) { return d.p2_p; }) - 1,
d3.max(data, function(d) { return d.p2_p; }) + 1 ])
.range(xRange);
let yScale = d3.scaleLinear()
.domain([ d3.min(data, function(d) { return d.p3_p; }) - 1,
d3.max(data, function(d) { return d.p3_p; }) + 1 ])
.range(yRange); // flip order because y-axis origin is upper LEFT
let xAxis = d3.axisBottom(xScale).tickFormat(function(d) { return d.p2_p; });
let yAxis = d3.axisLeft(yScale).tickFormat(function (d) { return d.p3_p; });
return {"xAxis" : xAxis, "yAxis" : yAxis, "xScale" : xScale, "yScale" : yScale};
}
But now, the problem is that I've got the error "values is undefined" and I don't know why that happend :(

Related

How to draw vertical line on mouse over displaying data with d3.js

How to append a vertical line to a graph and display on a tooltip the data focused?
Something like this:
TASK:
Add line indicator and tooltip
Append an invisible div to the vis container, set its class to "tooltip" and use the index.css to define necessary styles (e.g. position)
Append an indicator line to the viewport
Append a rectangle and set its class to "interaction-rect" (see index.css). We will use this rectangle to capture the mouse-events
Whenever there is a mousemove, update the tooltip to show the correct dates and values
Whenever the mouse leaves the viewport, make the indicator and tooltip disappear
CODE:
/* Retrieve the node of the div element declared within the index.html by its identifier */
var visContainerNode = d3.select("#vis-container");
// Specify margins such that the visualization is clearly visible and no elements are invisible due to the svg border
var margins = {
top: 20,
right: 25,
bottom: 20,
left: 50
};
// Specify the width and height of the svg as well as the width height of the viewport of the visualization.
var width = 1200;
var height = 800;
var gapY = 50;
var focusAreaHeight = 600 - margins.top;
var contextAreaHeight = 200 - margins.bottom - gapY;
var visWidth = width - margins.left - margins.right;
var visHeight = focusAreaHeight + contextAreaHeight;
/* Appending an svg element to the vis-container, set its width and height (in pixels), and add it to the vis-container */
var svg = visContainerNode.append("svg").attr("width", width).attr("height", height);
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", visWidth)
.attr("height", visHeight);
// Adding a group element to the svg to realize the margin by translating the group.
var viewport = svg.append("g").attr("transform", "translate(" + margins.left + "," + margins.top + ")");
var dateParser = d3.timeParse('%m %Y');
var dateFormat = d3.timeFormat('%m / %Y');
var curve = d3.curveMonotoneX;
// We use the d3.dsv method, which uses the fetchAPI internally, to retrieve the data
d3.dsv(";", "pr_1991_2015.csv", function (d) {
return {
date: dateParser(d.Month + " " + d.Year),
rain: parseFloat(d.pr),
temperature: parseFloat(d.tas)
};
}).then(function (data) {
console.log("Raw Data:", data);
// Init Scales
var xFocus = d3.scaleTime().domain(d3.extent(data, function (d) {
return d.date;
})).range([0, visWidth]);
var yRainFocus = d3.scaleLinear().domain([0, d3.max(data.map(function (d) {
return d.rain
}))]).range([focusAreaHeight, 0]);
var yTempFocus = d3.scaleLinear().domain(d3.extent(data.map(function (d) {
return d.temperature
}))).range([focusAreaHeight, 0]);
// In order to organize our code, we add one group for the focus visualization (the large lien chart)
var focusVis = viewport.append("g");
// Initialize a line generator for each line
var rainLine = d3.line()
.x(function (d) {
return xFocus(d.date);
})
.y(function (d) {
return yRainFocus(d.rain);
})
.curve(curve);
var tempLine = d3.line()
.x(function (d) {
return xFocus(d.date);
})
.y(function (d) {
return yTempFocus(d.temperature);
})
.curve(curve);
// Append two path elements
focusVis.append("path")
.datum(data)
.attr("class", "line line-rain")
.attr("d", rainLine);
focusVis.append("path")
.datum(data)
.attr("class", "line line-temp")
.attr("d", tempLine);
// Lets add some axis
var axisG = focusVis.append("g");
var xAxisFocus = d3.axisBottom(xFocus);
axisG.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + focusAreaHeight + ")")
.call(xAxisFocus);
axisG.append("g")
.attr("class", "y axis")
.call(d3.axisLeft(yTempFocus));
axisG.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + visWidth + ", 0)")
.call(d3.axisRight(yRainFocus));
// Append three text elements to the axisG group and label the axes respectively
axisG.append("text").text("Temperature").attr("x", -50).attr("y", -5).attr("fill", "red");
axisG.append("text").text("Rain").attr("x", visWidth - 10).attr("y", -5).attr("fill", "blue");
axisG.append("text").text("Years").attr("x", visWidth / 2).attr("y", focusAreaHeight - 10);
// Create the context visualization (small line chart) directly below the focus vis
// Init scales since range differs
var xContext = d3.scaleTime().domain(d3.extent(data, function (d) {
return d.date;
})).range([0, visWidth]);
var yContextRain = d3.scaleLinear().domain([0, d3.max(data.map(function (d) {
return d.rain
}))]).range([contextAreaHeight, 0]);
var yContexttemp = d3.scaleLinear().domain(d3.extent(data.map(function (d) {
return d.temperature
}))).range([contextAreaHeight, 0]);
// To organize our code, we add one group for the context visualization
var contextVis = viewport.append("g").attr("transform", "translate(0," + (focusAreaHeight + gapY) + ")");
var xAxisContext = d3.axisBottom(xContext);
contextVis.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + contextAreaHeight + ")")
.call(xAxisContext);
// Init two line generators
var rainLineContext = d3.line()
.x(function (d) {
return xContext(d.date);
})
.y(function (d) {
return yContextRain(d.rain);
})
.curve(curve);
var tempLineContext = d3.line()
.x(function (d) {
return xContext(d.date);
})
.y(function (d) {
return yContexttemp(d.temperature);
})
.curve(curve);
// Add the two lines for rain and temperature
contextVis.append("path")
.datum(data)
.attr("class", "line line-rain")
.attr("d", rainLineContext);
contextVis.append("path")
.datum(data)
.attr("class", "line line-temp")
.attr("d", tempLineContext);
/*
* Add Interactive Features here
*/
/*
TASK: Add the brush using the d3.brush function, define the extent and the necessary event functions
Append a new group element and apply the brush on it using the "call" function
During the brush and on brush end you want to make sure that the lines are redrawn correctly by setting their "d" attribute
*/
//
var brush = d3.brushX()
.extent([[-10, -10], [width+10, height+10]])
.on("brush end", brushed);
var zoom = d3.zoom()
.scaleExtent([1, Infinity])
.translateExtent([[0, 0], [width, height]])
.extent([[0, 0], [width, height]])
.on("zoom", zoomed);
contextVis.append("g")
.attr("class", "brush")
.call(brush)
.call(brush.move, xContext.range());
function brushed() {
if (d3.event || d3.event.selection)
var s = d3.event.selection || xContext.range();
xFocus.domain(s.map(xContext.invert, xContext));
focusVis.select(".line-rain").attr("d", rainLine);
focusVis.select(".line-temp").attr("d", tempLine);
focusVis.select(".x axis").call(xAxisFocus);
focusVis.select(".zoom").call(zoom.transform, d3.zoomIdentity
.scale(visWidth / (s[1] - s[0]))
.translate(-s[0], 0));
}
function zoomed() {
if (d3.event || d3.event.selection)
var t = d3.event.transform;
xFocus.domain(t.rescaleX(xContext).domain());
focusVis.select(".line-rain").attr("d", rainLine);
focusVis.select(".line-temp").attr("d", tempLine);
axisG.select(".x axis").call(xAxisFocus);
contextVis.select(".brush").call(brush.move, xContext.range().map(t.invertX, t));
}
})

D3JS makes date duplicates

I have this d3js code:
var tooltip = tooltipd3();
var svg = d3.select("svg#svg-day"),
margin = {
top: 20,
right: 30,
bottom: 30,
left: 25,
padding: 15
},
width = 700 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
// parse the periodo / time
var parseTime = d3.timeParse("%Y-%m-%d");
// set the ranges
var x = d3.scaleTime().range([0, width - margin.padding]);
var y = d3.scaleLinear().range([height, 0]);
// define the area
var area = d3.area()
.x(function(d) {
return x(d.periodo) + (margin.left + margin.padding);
})
.y0(height)
.y1(function(d) {
return y(d.guadagno);
});
// define the line
var valueline = d3.line()
.x(function(d) {
return x(d.periodo) + (margin.left + margin.padding);
})
.y(function(d) {
return y(d.guadagno);
});
var div = d3.select("svg#svg-day")
.append("div") // declare the tooltip div
.attr("class", "tooltip") // apply the 'tooltip' class
.style("opacity", 0);
// get the data
d3.csv(base_url() + 'graph/getStatementsDaily/', function(error, data) {
if (error) throw error;
$('.graph-loading').hide();
// format the data
data.forEach(function(d) {
d.periodo = parseTime(d.periodo)
d.guadagno = +d.guadagno;
});
// scale the range of the data
x.domain(d3.extent(data, function(d) {
return d.periodo;
}));
y.domain([0, d3.max(data, function(d) {
return d.guadagno + ((d.guadagno / 100) * 10); // 10% in più sulla scala numerica
})]);
// add the area
svg.append("path")
.data([data])
.attr("class", "area")
.attr("d", area);
// add the valueline path.
svg.append("path")
.data([data])
.attr("class", "line")
.attr("d", valueline);
// Add the scatterplot
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 3)
.attr("cx", function(d) {
return x(d.periodo) + (margin.left + margin.padding);
})
.attr("cy", function(d) {
return y(d.guadagno);
})
.on('mouseover', function(d) {
var html = '<h5>' + d.guadagno + ' €</h5>';
tooltip.mouseover(html); // pass html content
})
.on('mousemove', tooltip.mousemove)
.on('mouseout', tooltip.mouseout);
// add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(" + (margin.left + margin.padding) + "," + (height) + ")")
//HERE IS THE DATES CODE
.call(d3.axisBottom(x).tickFormat(d3.timeFormat("%d/%m")))
// add the Y Axis
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate (" + (margin.left + margin.padding) + " 0)")
.call(d3.axisLeft(y));
});
The dates care coming from a CSV file that has this format:
periodo,guadagno
2017-05-08,0.0
2017-05-09,0.5385
2017-05-10,0.0
2017-05-11,0.0
2017-05-12,0.0
2017-05-13,0.5680
2017-05-14,0.0
2017-05-15,0.0
The result is fine with lots of dates, but with 7 dates I get duplicates as you can see here:
Why is this?? And how do I fix it?
This is something that bothers a lot of people new to D3: the ticks in the axis, specially when using a time scale, are automatically generated. In your case, given the date interval in your domain, it coincidentally ended up creating two ticks for each day. But pay attention to this: those ticks represent different times (hours) in the same day (you can see that if you remove the tickFormat in the axis generator).
Let's see your code generating the x axis:
var svg = d3.select("svg");
var data = d3.csvParse(d3.select("#csv").text());
var parseTime = d3.timeParse("%Y-%m-%d");
data.forEach(function(d) {
d.periodo = parseTime(d.periodo)
});
var x = d3.scaleTime()
.range([20, 480])
.domain(d3.extent(data, function(d) {
return d.periodo;
}));
var axis = d3.axisBottom(x).tickFormat(d3.timeFormat("%d/%m"))(svg.append("g").attr("transform", "translate(0,50)"));
pre {
display: none;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500"></svg>
<pre id="csv">periodo,guadagno
2017-05-08,0.0
2017-05-09,0.5385
2017-05-10,0.0
2017-05-11,0.0
2017-05-12,0.0
2017-05-13,0.5680
2017-05-14,0.0
2017-05-15,0.0</pre>
As you can see, there are two ticks for each day (remember, for different hours).
Let's show that this is a coincidence: This is the same code, but changing the last date for 2017-05-20:
var svg = d3.select("svg");
var data = d3.csvParse(d3.select("#csv").text());
var parseTime = d3.timeParse("%Y-%m-%d");
data.forEach(function(d) {
d.periodo = parseTime(d.periodo)
});
var x = d3.scaleTime()
.range([20, 480])
.domain(d3.extent(data, function(d) {
return d.periodo;
}));
var axis = d3.axisBottom(x).tickFormat(d3.timeFormat("%d/%m"))(svg.append("g").attr("transform", "translate(0,50)"));
pre {
display: none;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500"></svg>
<pre id="csv">periodo,guadagno
2017-05-08,0.0
2017-05-09,0.5385
2017-05-10,0.0
2017-05-11,0.0
2017-05-12,0.0
2017-05-13,0.5680
2017-05-14,0.0
2017-05-20,0.0</pre>
Back to your code.
The solution is quite simple: using intervals. Let's set the interval for each tick:
d3.axisBottom(x).ticks(d3.timeDay)
Here is the same code with that change only:
var svg = d3.select("svg");
var data = d3.csvParse(d3.select("#csv").text());
var parseTime = d3.timeParse("%Y-%m-%d");
data.forEach(function(d) {
d.periodo = parseTime(d.periodo)
});
var x = d3.scaleTime()
.range([20, 480])
.domain(d3.extent(data, function(d) {
return d.periodo;
}));
var axis = d3.axisBottom(x).tickFormat(d3.timeFormat("%d/%m")).ticks(d3.timeDay)(svg.append("g").attr("transform", "translate(0,50)"));
pre {
display: none;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500"></svg>
<pre id="csv">periodo,guadagno
2017-05-08,0.0
2017-05-09,0.5385
2017-05-10,0.0
2017-05-11,0.0
2017-05-12,0.0
2017-05-13,0.5680
2017-05-14,0.0
2017-05-15,0.0</pre>

D3.js How to hide/show line when click select options?

I tried to use D3.js to draw lines when you click on different checkbox. It will get data of that option. Here is an example I used D3 multi-series line chart with tooltips and legend. I have got the specific data object that is corresponding the checkbox I choose. Howevery, I don't know how to draw it on svg. Please help me and I will appreciate you so much.
I also find a website "www.cotrino.com/starpaths/" that shows the final effect I want to implement.
My D3 effect
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.axis--x path {
display: none;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
</style>
<script src="http://d3js.org/d3.v4.js"></script>
<body>
<svg width="1000" height="500"></svg>
<div id="disease_list"></div>
</body>
<script>
var svg = d3.select("svg"),
margin = {top: 20, right: 80, bottom: 30, left: 50},
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 + ")");
//make a clip path for the graph
var clip = svg.append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", height);
var parseTime = d3.timeParse("%Y-%m");
var x = d3.scaleTime().range([0, width]),
y = d3.scaleLinear().range([height, 0]);
var line = d3.line()
.curve(d3.curveBasis)
.x(function(d) { console.log(d.date); return x(d.date); })
.y(function(d) { console.log(d.date); return y(d.count); });
var color = d3.scaleOrdinal(d3.schemeCategory20);
d3.csv("./top10highestNormalize.csv", type, function(error, data) {
if (error) throw error;
var diseases = data.columns.slice(1).map(function(id) {
return {
id: id,
values: data.map(function(d) {
return {date: d.date, count: d[id]};
})
};
});
console.log(diseases);
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([
d3.min(diseases, function(c) { return d3.min(c.values, function(d) { return d.count; }); }),
d3.max(diseases, function(c) { return d3.max(c.values, function(d) { return d.count; }); })
]);
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y))
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "0.71em")
.attr("fill", "#000")
.text("Count");
/*
var disease = g.selectAll(".disease")
.data(diseases)
.enter().append("g")
.attr("class", "disease");
*/
// Create the shape selectors
var selector = d3.select("#disease_list").append("select");
labels = selector.selectAll("option")
.data(diseases)
.enter()
.append("option")
.attr("value",function(d,i) {return i;})
.text(function(d) {return d.id;});
var menu = d3.select("#disease_list select")
.on("change", redraw);
// var series = menu.property("value");
//console.log(series);
// all the meat goes in the redraw function
function redraw() {
console.log("redraw start");
// get value from menu selection
// the option values are set in HTML and correspond
//to the [type] value we used to nest the data
var series = menu.property("value");
console.log(series);
// only retrieve data from the selected series, using the nest we just created
var adata = diseases[series];
console.log(adata);
}
});
function type(d, _, columns) {
d.date = parseTime(d.date);
for (var i = 1, n = columns.length, c; i < n; ++i) d[c = columns[i]] = +d[c];
return d;
}
</script>
top10highestNormalize.csv
date,disseminated sclerosis,sclerosis,gestural tics,venereal disease,bite,cot death,venereal disease,cardiovascular disease,diseases vascular,pruritis,pus,cystic fibrosis,fibroses
2010-04,0,0,0,0,0,0,0,0,0,0,0,0,0
2010-05,0,0,0.06898023,0.068783069,0.085790885,0.065761258,0.068783069,0,0,0.001204094,0.023051592,0,0
2010-06,0.076923077,0.076923077,0.190584554,0.199972867,0.201072386,0.171789373,0.199972867,0.071428571,0.071428571,0.004816376,0.031284303,0.2,0.2
2010-07,0.230769231,0.230769231,0.221590101,0.224664225,0.225201072,0.235167977,0.224664225,0.214285714,0.285714286,0.00602047,0.038419319,0,0
2010-08,0.538461538,0.538461538,0.174797326,0.182471849,0.174262735,0.192041935,0.182471849,0.071428571,0.071428571,0.003612282,0.023051592,0,0
2010-09,0.230769231,0.230769231,0.287725786,0.277845611,0.252010724,0.259471051,0.277845611,0,0,0.004214329,0.046652031,0,0
2010-10,0.076923077,0.076923077,0.295406059,0.299416633,0.285969616,0.265665952,0.299416633,0,0.071428571,0.007224564,0.03402854,0.066666667,0.066666667
2010-11,0.153846154,0.153846154,0.284027877,0.279337946,0.261840929,0.276149631,0.279337946,0,0,0.006622517,0.050493963,0,0
2010-12,0.153846154,0.153846154,0.271511876,0.237552571,0.213583557,0.237312366,0.237552571,0.142857143,0.142857143,0.004214329,0.035126235,0,0
2011-01,0.076923077,0.076923077,0.306642014,0.312440646,0.28150134,0.305694544,0.312440646,0.142857143,0.142857143,0.006622517,0.046103183,0,0.066666667
2011-02,0.076923077,0.076923077,0.288721377,0.262243929,0.219839142,0.25899452,0.262243929,0.142857143,0.142857143,0.007224564,0.038968167,0,0.066666667
2011-03,0.076923077,0.076923077,0.271654103,0.255324922,0.253798034,0.266857279,0.255324922,0.071428571,0.071428571,0.007224564,0.051591658,0,0
2011-04,0.461538462,0.461538462,0.291423695,0.252068919,0.235031278,0.284250655,0.252068919,0,0,0.009030704,0.045005488,0,0
2011-05,0.153846154,0.153846154,0.448158157,0.380681047,0.351206434,0.439123183,0.380681047,0,0,0.011438892,0.079582876,0.333333333,0.4
2011-06,0.153846154,0.153846154,0.498079932,0.437661104,0.391420912,0.424827258,0.437661104,0.142857143,0.142857143,0.009632751,0.063117453,0,0.066666667
2011-07,0,0,0.410467928,0.424094424,0.419124218,0.379080295,0.424094424,0,0.071428571,0.009030704,0.061470911,1,1
2011-08,0.076923077,0.076923077,0.268382876,0.262922263,0.238605898,0.267810341,0.262922263,0.214285714,0.214285714,0.002408188,0.038968167,0,0
2011-09,0.230769231,0.230769231,0.510027023,0.469949803,0.470956211,0.444841553,0.469949803,0,0,0.014449127,0.075740944,0.133333333,0.2
2011-10,0.076923077,0.076923077,0.462380885,0.434540768,0.431635389,0.417679295,0.434540768,0.142857143,0.142857143,0.006622517,0.073545554,0,0.066666667
2011-11,0.153846154,0.153846154,0.519698478,0.457061457,0.415549598,0.443888492,0.457061457,0.142857143,0.142857143,0.01384708,0.06805708,0.2,0.2
2011-12,1,1,0.382449154,0.35002035,0.319928508,0.315701692,0.35002035,0,0,0.002408188,0.060373216,0,0
2012-01,0.461538462,0.461538462,0.492390841,0.45312712,0.409294013,0.45389564,0.45312712,0.571428571,0.571428571,0.007224564,0.060373216,0,0
2012-02,0.076923077,0.076923077,0.382875836,0.375932709,0.350312779,0.369073147,0.375932709,0.071428571,0.071428571,0.003612282,0.049945115,0.066666667,0.066666667
2012-03,0.923076923,1,1,0.922127255,1,0.871098404,0.922127255,0.5,0.5,0.01384708,0.171789243,0,0.066666667
2012-04,0.230769231,0.307692308,0.699331532,0.676977344,0.63360143,0.645699309,0.676977344,0.142857143,0.142857143,0.012040939,0.092206367,0.133333333,0.133333333
2012-05,0.846153846,0.846153846,0.801735173,0.752408086,0.776586238,0.7436264,0.752408086,0.785714286,0.785714286,0.016857315,0.131723381,0.466666667,0.466666667
2012-06,0.384615385,0.461538462,0.730479306,0.732193732,0.625558534,0.657850846,0.732193732,0,0,0.011438892,0.118002195,0.6,0.666666667
2012-07,0.384615385,0.384615385,0.751386716,0.738434405,0.71849866,0.714081487,0.738434405,0.285714286,0.285714286,0.009030704,0.126783754,0.2,0.2
2012-08,0.384615385,0.461538462,0.700327123,0.643467643,0.619302949,0.646890636,0.643467643,0.285714286,0.285714286,0.012642986,0.150933041,0.2,0.266666667
2012-09,0.076923077,0.230769231,0.72137676,0.701804368,0.63538874,0.70455087,0.701804368,0.214285714,0.214285714,0.011438892,0.130076839,0.066666667,0.066666667
2012-10,0.230769231,0.230769231,0.846252311,0.863112196,0.796246649,0.825827972,0.863112196,0.071428571,0.071428571,0.036724865,0.127881449,0.333333333,0.333333333
2012-11,0.692307692,0.692307692,0.895605177,1,0.798927614,0.909935668,1,0.214285714,0.357142857,0.012642986,0.143798024,0,0.133333333
2012-12,0.923076923,1,0.795903854,0.803283137,0.683646113,0.827257565,0.803283137,0.142857143,0.142857143,0.008428657,0.104829857,0.6,0.6
2013-01,0.230769231,0.384615385,0.92106386,0.964862298,0.848078642,0.944007624,0.964862298,0.285714286,0.357142857,0.015653221,0.146542261,0.533333333,0.733333333
2013-02,0.153846154,0.307692308,0.830322856,0.872880206,0.798927614,0.755777937,0.872880206,0.142857143,0.142857143,0.010234798,0.110318332,0,0.066666667
2013-03,0.230769231,0.230769231,0.927037406,0.944105277,0.885612154,0.953061711,0.944105277,0.142857143,0.142857143,0.009632751,0.131174533,0,0.133333333
2013-04,0.384615385,0.384615385,0.796046082,0.775471442,0.671134942,0.715749345,0.775471442,0,0,0.012040939,0.12349067,0.133333333,0.133333333
2013-05,0.923076923,1,0.824633765,0.844254511,0.742627346,0.843697879,0.844254511,0.142857143,0.142857143,0.015653221,0.149286498,0,0
2013-06,0.307692308,0.307692308,0.884369222,0.949667616,0.865951743,1,0.949667616,0.071428571,0.071428571,0.020469597,0.135016465,0.466666667,0.466666667
2013-07,0.461538462,0.461538462,0.864172948,0.935829602,0.843610366,0.939480581,0.935829602,0.071428571,0.071428571,0.015051174,0.128979144,0.066666667,0.2
2013-08,0.153846154,0.153846154,0.670886076,0.738163071,0.753351206,0.821300929,0.738163071,0.071428571,0.214285714,0.012642986,0.098243688,0,0
2013-09,0.230769231,0.230769231,0.876262267,0.861484195,0.744414656,0.996426019,0.861484195,0,0,0.024081878,0.144895719,0.066666667,0.066666667
2013-10,0.615384615,0.615384615,0.917508178,0.885361552,0.806970509,0.841315225,0.885361552,0.642857143,0.642857143,0.030704395,0.115806806,0.2,0.4
2013-11,0,0.076923077,0.857061584,0.903540904,0.791778374,0.845127472,0.903540904,0.5,0.5,0.012642986,0.093852909,0,0
2013-12,0.230769231,0.230769231,0.704878396,0.719169719,0.584450402,0.81915654,0.719169719,0.285714286,0.5,0.015653221,0.108122942,0,0
2014-01,0.461538462,0.461538462,0.900014223,0.856328856,0.717605004,0.98903979,0.856328856,0.357142857,0.5,0.030102348,0.137211855,0,0.066666667
2014-02,0,0,0.707865169,0.703296703,0.63717605,0.796997856,0.703296703,1,1,0.012642986,0.097145993,0,0
2014-03,0.230769231,0.230769231,0.815531219,0.800434134,0.7256479,0.786275911,0.800434134,0.714285714,0.714285714,0.009632751,0.099341383,0.533333333,0.6
2014-04,0.153846154,0.153846154,0.756506898,0.790259124,0.615728329,0.778174887,0.790259124,0,0,0.011438892,0.12349067,0,0
2014-05,0.461538462,0.461538462,0.85990613,0.767331434,0.705987489,0.78008101,0.767331434,0.142857143,0.285714286,0.014449127,0.13611416,0.066666667,0.133333333
2014-06,0.076923077,0.153846154,0.670886076,0.713064713,0.615728329,0.735763641,0.713064713,0.285714286,0.285714286,0.010836845,0.102634468,0,0
2014-07,0.076923077,0.076923077,0.672592803,0.801655135,0.621090259,0.680009531,0.801655135,0.071428571,0.071428571,0.007224564,0.103183315,0,0
2014-08,0.384615385,0.461538462,0.487270659,0.58377425,0.486148347,0.575887539,0.58377425,0.071428571,0.071428571,0.005418423,0.079582876,0,0.133333333
2014-09,0,0.076923077,0.715545442,0.678062678,0.669347632,0.705980462,0.678062678,0,0,0.01384708,0.103183315,0,0.066666667
2014-10,0.230769231,0.307692308,0.742995306,0.723511057,0.630920465,0.679294734,0.723511057,0,0,0.016857315,0.1064764,0,0
2014-11,0,0,0.672735031,0.623388957,0.583556747,0.64927329,0.623388957,0,0,0.004816376,0.115806806,0.066666667,0.066666667
2014-12,0.307692308,0.384615385,0.591096572,0.55704789,0.478999106,0.491303312,0.55704789,0.285714286,0.428571429,0.003010235,0.074643249,0,0
2015-01,0.076923077,0.153846154,0.659223439,0.561117894,0.531724754,0.605432452,0.561117894,0.071428571,0.071428571,0.007224564,0.094401756,0.133333333,0.133333333
2015-02,0.230769231,0.307692308,0.61840421,0.564780898,0.512064343,0.585656421,0.564780898,0.071428571,0.071428571,0.007224564,0.096597146,0,0
2015-03,0,0,0.770302944,0.677927011,0.599642538,0.675482487,0.677927011,0.071428571,0.071428571,0.009632751,0.111964874,0.066666667,0.2
2015-04,0.076923077,0.076923077,0.706016214,0.61687695,0.731903485,0.563497736,0.61687695,0.071428571,0.071428571,0.008428657,0.097145993,0,0
2015-05,0,0.076923077,0.655383303,0.614027947,0.55406613,0.6154396,0.614027947,0.071428571,0.071428571,0.012642986,0.099341383,0,0
2015-06,0,0.076923077,0.564357844,0.540632207,0.527256479,0.598284489,0.540632207,0.142857143,0.142857143,0.00602047,0.091657519,0,0
2015-07,0.076923077,0.076923077,0.486417295,0.525301859,0.511170688,0.566356922,0.525301859,0,0,0.015653221,0.08726674,0.066666667,0.066666667
2015-08,0.230769231,0.230769231,0.408476746,0.386379053,0.320822163,0.465094115,0.386379053,0,0,0.003010235,0.056531284,0,0
2015-09,0.538461538,0.538461538,0.870999858,0.792701126,0.747095621,0.883964737,0.792701126,0,0,0.013245033,0.156421515,0,0
2015-10,0.153846154,0.153846154,0.469492249,0.435490435,0.320822163,0.51227067,0.435490435,0,0,0.174593618,0.221734358,0,0
2015-11,0.153846154,0.153846154,0.322998151,0.309455976,0.273458445,0.346676197,0.309455976,0,0,0.462974112,0.481888035,0.133333333,0.133333333
2015-12,0.076923077,0.076923077,0.342767743,0.309320309,0.27971403,0.384798666,0.309320309,0,0,0.464780253,0.482436883,0.066666667,0.066666667
2016-01,0.307692308,0.384615385,0.415872564,0.349477683,0.358355675,0.442458899,0.349477683,0,0,0.559903672,0.581229418,0.066666667,0.066666667
2016-02,0,0,0.445455838,0.403744404,0.316353887,0.457469621,0.403744404,0,0,0.54846478,0.568605928,0.066666667,0.066666667
2016-03,0,0,0.471198976,0.400352734,0.317247542,0.508220157,0.400352734,0.142857143,0.142857143,0.604455148,0.628430296,0,0
2016-04,0,0,0.582989617,0.570343237,0.575513852,0.603764594,0.570343237,0.214285714,0.214285714,1,1,0,0
You need to create your line variable:
var myLine = svg.append("path");
And then, inside redraw(), changing it according to the option selected:
myLine.datum(adata.values)
.attr("d", line);
Here is a demo plunker: https://plnkr.co/edit/YjGO9TLDBXj13JQuO5bm?p=preview
PS: I changed your x-scale range:
var x = d3.scaleTime().range([margin.left, width]);
And also added a call to redraw() when the code runs for the first time.

Dots are not appending to right graph?

I am having a problem with my code where the circle nodes that I have created do not seem to be appending themselves to the graph. The debugger isn't pulling up any errors, so it seems like it's a logic issue.
Here's what is looks like:
(dot)
|
|
|
|
|
| <--(where dot should be)
|
__________________________________________
^
|
graph
And here's my code:
<script>
var slider = $("#myRange").val();;
var xtwo;
var xone;
var xzero;
var firstx = -1;
var firsty = 1;
var secondx = 2;
var secondy = 4;
var lineData = [];
var nodes = [];
//updates coefficients
function updateXs() {
xtwo = (75 - slider) / 50;
xone = (slider - 25) / 50;
xzero = (slider - 25) / 25;
}
//gets corresponding y from x and coefficients
function getY(xval) {
return (xval * xval * xtwo + xval * xone + xzero);
}
function displayVals() {
document.getElementById("demo").innerHTML = slider + " " + xtwo + " " + xone + " " + xzero + " " + lineData;
}
function updateLineData() {
//resets and fills points
lineData = [];
for (i = (firstx - 1); i < (secondx + 2); i++) {
lineData.push({
x: i,
y: getY(i)
});
}
}
//makes dots for static points
function makeDots(xvalue, xvalue2) {
nodes = [{
x: xvalue,
y: getY(xvalue)
}, {
x: xvalue2,
y: getY(xvalue2)
}]
}
function makeLine() {}
$(document).ready(function() {
updateXs();
updateLineData();
displayVals();
var vis = d3.select('#visual'),
WIDTH = 1000,
HEIGHT = 500,
MARGINS = {
top: 20,
right: 20,
bottom: 20,
left: 50
},
xRange = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]).domain([d3.min(lineData, function(d) {
return d.x;
}), d3.max(lineData, function(d) {
return d.x;
})]),
yRange = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([d3.min(lineData, function(d) {
return d.y;
}), d3.max(lineData, function(d) {
return d.y;
})]),
xAxis = d3.svg.axis()
.scale(xRange)
.tickSize(5)
.tickSubdivide(true),
yAxis = d3.svg.axis()
.scale(yRange)
.tickSize(5)
.orient("left")
.tickSubdivide(true);
vis.append("svg:g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (HEIGHT - MARGINS.bottom) + ")")
.call(xAxis);
vis.append("svg:g")
.attr("class", "y axis")
.attr("transform", "translate(" + (MARGINS.left) + ",0)")
.call(yAxis);
var lineFunc = d3.svg.line()
.x(function(d) {
return xRange(d.x);
})
.y(function(d) {
return yRange(d.y);
})
.interpolate('basis');
vis.append("svg:path")
.attr("d", lineFunc(lineData))
.attr("stroke", "blue")
.attr("stroke-width", 2)
.attr("fill", "none");
makeDots(firstx, secondx);
//puts in dots
vis.selectAll("circle.nodes")
.data(nodes)
.enter()
.append("circle")
.attr("cx", function(d) {
console.log(d.x)
return 200;
})
.attr("cy", function(d) {
return d.y;
})
.attr("r", "10px")
.attr("fill", "black")
//updates when slider changes
$("#myRange").change(function() {
slider = $("#myRange").val();
updateXs();
updateLineData();
displayVals();
});
});
</script>
Please help and thanks in advance. Also, I was wondering if I could get some tips on how to make the line move using the .change function
You haven't applied your scale function to your dots:
vis.selectAll(".nodes")
.data(nodes)
.enter().append("circle")
.attr("class", "nodes")
.attr("cx", function (d) {
return xRange(d.x); //<-- convert from user space to pixel space
})
.attr("cy", function (d) {
return yRange(d.y); //<-- convert from user space to pixel space
});
To make your line update, you need to select it and change the d attribute:
d3.select(".myLine") //<-- select it by some unique class
.attr("d", lineFunc(lineData)); //<-- update the d attribute
To get a smooth curve without interpolation, just supply more points. See udpated fiddle.
Fiddle here.

How to start and stop animation of a D3 bubble chart

I am trying to replicate the health & wealth nations chart.
http://bost.ocks.org/mike/nations/:
When i click start the animation of the chart works which works perfectly and if i click stop the animation stops. However if i click the start next time, it is starting from the beginning instead from where i stopped? how do i animate from the place where i left?
Following is the code:
<h1>The Wealth & Health of Nations</h1>
<p id="chart"></p>
<input type="submit" value="Start" onclick=start();>
<input type="submit" value="Stop" onclick=stop();>
<script src="http://d3js.org/d3.v2.js?2.8.1"></script>
<script>
// Various accessors that specify the four dimensions of data to visualize.
function x(d) { return d.income; }
function y(d) { return d.lifeExpectancy; }
function radius(d) { return d.population; }
function color(d) { return d.region; }
function key(d) { return d.name; }
// Chart dimensions.
var margin = {top: 29.5, right: 29.5, bottom: 29.5, left: 59.5},
width = 960 - margin.right,
height = 500 - margin.top - margin.bottom;
// Various scales. These domains make assumptions of data, naturally.
var xScale = d3.scale.log().domain([300, 1e5]).range([0, width]),
yScale = d3.scale.linear().domain([10, 85]).range([height, 0]),
radiusScale = d3.scale.sqrt().domain([0, 5e8]).range([0, 40]),
colorScale = d3.scale.category10();
// The x & y axes.
var xAxis = d3.svg.axis().orient("bottom").scale(xScale).ticks(12, d3.format(",d")),
yAxis = d3.svg.axis().scale(yScale).orient("left");
// Create the SVG container and set the origin.
var svg = d3.select("#chart").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 + ")");
// 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);
// Add an x-axis label.
svg.append("text")
.attr("class", "x label")
.attr("text-anchor", "end")
.attr("x", width)
.attr("y", height - 6)
.text("income per capita, inflation-adjusted (dollars)");
// Add a y-axis label.
svg.append("text")
.attr("class", "y label")
.attr("text-anchor", "end")
.attr("y", 6)
.attr("dy", ".75em")
.attr("transform", "rotate(-90)")
.text("life expectancy (years)");
// Add the year label; the value is set on transition.
var label = svg.append("text")
.attr("class", "year label")
.attr("text-anchor", "end")
.attr("y", height - 24)
.attr("x", width)
.text(2000);
function start()
{
//alert("Start Clicked");
// Load the data.
d3.json("nations_new.json", function(nations) {
// A bisector since many nation's data is sparsely-defined.
var bisect = d3.bisector(function(d) { return d[0]; });
// Add a dot per nation. Initialize the data at 2000, and set the colors.
var dot = svg.append("g")
.attr("class", "dots")
.selectAll(".dot")
.data(interpolateData(2000))
.enter().append("circle")
.attr("class", "dot")
.style("fill", function(d) { return colorScale(color(d)); })
.call(position)
.sort(order);
// Add a title.
dot.append("title")
.text(function(d) { return d.name; });
// Add an overlay for the year label.
var box = label.node().getBBox();
var overlay = svg.append("rect")
.attr("class", "overlay")
.attr("x", box.x)
.attr("y", box.y)
.attr("width", box.width)
.attr("height", box.height);
//.on("mouseover", enableInteraction);
// Start a transition that interpolates the data based on year.
svg.transition()
.duration(30000)
.ease("linear")
.tween("year", tweenYear)
.each("end", enableInteraction);
// Positions the dots based on data.
function position(dot) {
dot .attr("cx", function(d) { return xScale(x(d)); })
.attr("cy", function(d) { return yScale(y(d)); })
.attr("r", function(d) { return radiusScale(radius(d)); });
}
// Defines a sort order so that the smallest dots are drawn on top.
function order(a, b) {
return radius(b) - radius(a);
}
// After the transition finishes, you can mouseover to change the year.
function enableInteraction() {
var yearScale = d3.scale.linear()
.domain([2000, 2009])
.range([box.x + 10, box.x + box.width - 10])
.clamp(true);
// Cancel the current transition, if any.
svg.transition().duration(0);
overlay
.on("mouseover", mouseover)
.on("mouseout", mouseout)
.on("mousemove", mousemove)
.on("touchmove", mousemove);
function mouseover() {
label.classed("active", true);
}
function mouseout() {
label.classed("active", false);
}
function mousemove() {
displayYear(yearScale.invert(d3.mouse(this)[0]));
}
}
// Tweens the entire chart by first tweening the year, and then the data.
// For the interpolated data, the dots and label are redrawn.
function tweenYear() {
var year = d3.interpolateNumber(2000, 2009);
return function(t) { displayYear(year(t)); };
}
// Updates the display to show the specified year.
function displayYear(year) {
dot.data(interpolateData(year), key).call(position).sort(order);
label.text(Math.round(year));
}
// Interpolates the dataset for the given (fractional) year.
function interpolateData(year) {
return nations.map(function(d) {
return {
name: d.name,
region: d.region,
income: interpolateValues(d.income, year),
population: interpolateValues(d.population, year),
lifeExpectancy: interpolateValues(d.lifeExpectancy, year)
};
});
}
// Finds (and possibly interpolates) the value for the specified year.
function interpolateValues(values, year) {
var i = bisect.left(values, year, 0, values.length - 1),
a = values[i];
if (i > 0) {
var b = values[i - 1],
t = (year - a[0]) / (b[0] - a[0]);
return a[1] * (1 - t) + b[1] * t;
}
return a[1];
}
});
}
function stop()
{
//alert("stop Clicked");
svg.transition().duration(0);
}
the json file is :
[
{
"name":"Angola",
"region":"Sub-Saharan Africa",
"income":[[2000,2446.65],[2001,2479.69],[2002,2773.29],[2003,2785.39],[2004,3007.11],[2005,3533],[2006,4069.56],[2007,4755.46],[2008,5228.74],[2009,5055.59]],
"population":[[2000,10442812],[2001,10623424],[2002,10866106],[2003,11186202],[2004,11521432],[2005,11827315],[2006,12127071],[2007,12420476],[2008,12707546]],
"lifeExpectancy":[[2000,43.56],[2001,43.86],[2002,44.22],[2003,44.61],[2004,45.05],[2005,45.52],[2006,46.02],[2007,46.54],[2008,47.06],[2009,47.58]]
},
{
"name":"china",
"region":"East Asia & Pacific",
"income":[[2000,12446.65],[2001,12479.69],[2002,12773.29],[2003,12785.39],[2004,12007.11],[2005,12533],[2006,12069.56],[2007,12755.46],[2008,12228.74],[2009,12055.59]],
"population":[[2000,31542812],[2001,31623424],[2002,31866106],[2003,32186202],[2004,31521432],[2005,31827315],[2006,32127071],[2007,32420476],[2008,32707546]],
"lifeExpectancy":[[2000,53.56],[2001,63.86],[2002,64.22],[2003,64.61],[2004,76.05],[2005,66.52],[2006,86.02],[2007,87.54],[2008,89.06],[2009,68.58]]
},
{
"name":"India",
"region":"South Asia",
"income":[[2000,22446.65],[2001,22479.69],[2002,22773.29],[2003,22785.39],[2004,22007.11],[2005,22533],[2006,22069.56],[2007,22755.46],[2008,22228.74],[2009,22055.59]],
"population":[[2000,41542812],[2001,41623424],[2002,41866106],[2003,42186202],[2004,41521432],[2005,41827315],[2006,42127071],[2007,42420476],[2008,42707546],[2009,42707546]],
"lifeExpectancy":[[2000,43.56],[2001,43.86],[2002,44.22],[2003,64.61],[2004,56.05],[2005,56.52],[2006,66.02],[2007,68.54],[2008,67.06],[2009,73.58]]
}
]
In the start function, you would need to keep track of what year you're currently showing, e.g. with a global variable:
var thisYear = 2000;
// lots of code...
function displayYear(year) {
thisYear = year;
dot.data(interpolateData(year), key).call(position).sort(order);
label.text(Math.round(year));
}
Then you would need to modify the year it starts with depending on the value of that variable:
function tweenYear() {
var year = d3.interpolateNumber(thisYear, 2009);
return function(t) { displayYear(year(t)); };
}
I was working on something very similar and the suggestions by Lars got me very far. However, I kept getting my dots duplicated each time I hit start. I have since discovered the following:
If you would like to make it so your dots are not duplicated each time you select the start button, you would need to add the following code as a part of your start() function, and ideally just before the dots are initially added:
svg.selectAll(".dot").remove()
This removes the previous .dot elements; new .dot elements are subsequently created assuming you've setup the thisYear global variable mentioned by Lars.

Resources