I created a copy of the csv file in my local folder because i wanted to mess around with the data a little bit. When i get rid of the link and replace it with the name of my local csv file, the graph doesnt render for some reason. I have added a picture that shows my local file structure. it is in the same folder. What am i doing wrong?
import React, {Component, useRef, useEffect} from 'react';
import * as d3 from "d3";
import { select } from 'd3-selection'
import { extent, max, min } from "d3-array";
class Linechart extends Component {
constructor(props){
super(props)
this.createBarChart = this.createBarChart.bind(this)
}
componentDidMount() {
this.createBarChart()
}
componentDidUpdate() {
this.createBarChart()
}
createBarChart() {
var margin = {top: 30, right: 30, bottom: 30, left: 60},
width = 960 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
var node = this.node
var divObj = select(node)
var svgObj = divObj
.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 + ")");
//Read the data
// when i replace the line below wit this line of code, it doesnt read it d3.csv("5_OneCatSevNumOrdered.csv""), function(data) {
d3.csv("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/5_OneCatSevNumOrdered.csv", function(data) {
// group the data: I want to draw one line per group
var sumstat = d3.nest() // nest function allows to group the calculation per level of a factor
.key(function(d) { return d.name;})
.entries(data);
// Define the div for the tooltip
var tooltip = divObj
.append("div")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.text("I AM A TOOLTIP BOOM SHAKALAKA!! BOOM SHAKALAKA!!");
// Add X axis --> it is a date format
var x = d3.scaleLinear()
.domain(d3.extent(data, function(d) { return d.year; }))
.range([ 0, width ]);
svgObj.append("g")
.attr("transform", "translate(0," + height + ")")
.attr("stroke-width","0.3")
.call(d3.axisBottom(x).tickSize(-height).tickFormat('').ticks(5));
//ticks
svgObj.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).ticks(5));
// Add Y axis
var y = d3.scaleLinear()
.domain([0, d3.max(data, function(d) { return +d.n; })])
.range([ height, 0 ]);
svgObj.append("g")
.attr("stroke-width","0.3")
.call(d3.axisLeft(y).tickSize(-width).tickFormat('').ticks(5));
//ticks
svgObj.append("g")
.call(d3.axisLeft(y).ticks(5));
// color palette
var res = sumstat.map(function(d){ return d.key }) // list of group names
console.log(res)
var color = d3.scaleOrdinal()
.domain(res)
.range(['#e41a1c','#377eb8','#4daf4a','#984ea3','#ff7f00','#ffff33','#a65628','#f781bf','#999999'])
// Draw the line
svgObj.selectAll(".line")
.data(sumstat)
.enter()
.append("path")
.attr("fill", "none")
.attr("stroke", function(d){ return color(d.key) })
.attr("stroke-width", 2.5)
.attr("d", function(d){
return d3.line()
.x(function(d) { return x(d.year); })
.y(function(d) { return y(+d.n); })
(d.values)
})
.on("mouseover", function(){return tooltip.style("visibility", "visible");})
.on("mousemove", function(){return tooltip.style("top", (d3.event.pageY-10)+"px").style("left",(d3.event.pageX+10)+"px");})
.on("mouseout", function(){return tooltip.style("visibility", "hidden");})
})
}
render() {
return <div ref={node => this.node = node} className="example_div"> </div>
}
}
export default Linechart;
d3.csv is part of the d3-fetch library. That library uses the native fetch method to obtain a file from somewhere on the internet. It's unfortunately not able to deal with files on your hard drive.
You'll need to make the file available on localhost:<some port>, just like you're probably doing with your react code. Depending on what you use, you might need to change your webpack/gulp/rollup configuration. Otherwise, if you have a server-side API running with Python/C#/Ruby just serve it from there as a static file.
In any case, the file name/directory will never work, try serving it through localhost.
Edit: serving the file you put on Github
d3.csv("https://raw.githubusercontent.com/QamarFarooq/data-for-testing/main/5_OneCatSevNumOrdered.csv").then((data) => {
console.log(data);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
Related
I built a basic heatmap in html using d3, and the tooltips show properly. I've got the same code working in React, and the heatmap is working, and the mouseover, mousemove, and mouseleave functions are working (and the data is printing into the console accurately), but no matter what i try, I can't get the tooltip to actually show up. Any help would be appreciated
Below is my code-
import rd3 from 'react-d3-library';
import * as d3 from 'd3';
import React from 'react';
import data2 from '../data/hmap_current_year.csv';
const node = document.createElement('div');
// set the dimensions and margins of the graph
const margin = { top: 30, right: 60, bottom: 29, left: 60 },
width = 1400 - margin.left - margin.right,
height = 630 - margin.top - margin.bottom;
// append the svg object to the body of the page
const svg = d3
.select(node)
.append("svg")
//add mobile-friendly
.attr("viewBox", `0 0 ${width + margin.left + margin.right} ${height + margin.top + margin.bottom}`)
// .attr("width", width + margin.left + margin.right)
// .attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
d3.csv(data2).then(function (data) {
const var0 = data.map(function (d0) {
return {
month: d3.timeParse("%Y-%m-%d")(d0.time).getMonth(),
day: d3.timeParse("%Y-%m-%d")(d0.time).getDate(),
value: d0.tmed
}
})
const myGroups = Array.from({ length: 31 }, (_, i) => i + 1)
const myMonths = [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
]
// Build X scales and axis:
const x = d3.scaleBand()
.range([0, width])
.domain(myGroups)
.padding(0.01);
svg.append("g")
.attr("transform", `translate(0, ${height})`)
.call(d3.axisBottom(x))
.call(g => g.select(".domain").remove());
svg.append("g")
.call(d3.axisTop(x))
.call(g => g.select(".domain").remove());
// Build X scales and axis:
const y = d3.scaleBand()
.range([0, height])
.domain(myMonths)
.padding(0.01);
svg.append("g")
.call(d3.axisLeft(y))
.call(g => g.select(".domain").remove());
svg.append("g")
.call(d3.axisRight(y))
.attr("transform", `translate(${width}, 0)`)
.call(g => g.select(".domain").remove());
// Build color scale
const myColor = d3.scaleQuantile()
.domain([0, 5, 20, 40, 60, 80, 95, 100])
.range([
"#08306B",
"#2171B5",
"#6BAED6",
"#FFFFFF",
"#FCBBA1",
"#FA6A4A",
"#CB181D"
]);
// create a tooltip
const tooltip = d3.select(node)
.append("div")
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "2px")
.style("border-radius", "5px")
.style("padding", "5px")
.style("margin-bottom", '51px')
// Three function that change the tooltip when user hover / move / leave a cell
const mouseover = function (event, d) {
tooltip
.style("opacity", 1)
d3.select(this)
.style("stroke", "black")
.style("opacity", 1)
}
const mousemove = function (event, d) {
tooltip
.html("The exact value of<br>this cell is: " + d.value)
//accessing values correctly
console.log(d.value, 'HELLO')
.style("left", (event.x) / 2 + "px")
.style("top", (event.y) / 2 + "px")
};
const mouseleave = function (event, d) {
tooltip
.style("opacity", 0)
d3.select(this)
.style("stroke", "none")
.style("opacity", 1)
}
svg.selectAll()
.data(var0)
.join("rect")
.attr("x", function (d) { return x(d.day) })
.attr("y", function (d) { return y(myMonths[d.month]) })
.attr("width", x.bandwidth())
.attr("height", y.bandwidth())
.style("fill", function (d) { return myColor(d.value) })
.style("stroke", "none")
.on("mouseover", mouseover)
.on("mousemove", mousemove)
.on("mouseleave", mouseleave)
});
const RD3Component = rd3.Component;
class HeatmapInteractive extends React.Component {
constructor(props) {
super(props);
this.state = {d3: ''}
}
componentDidMount() {
this.setState({d3: node});
}
render() {
return (
<div>
<RD3Component data={this.state.d3}/>
</div>
)
}
}
export default HeatmapInteractive;
here you have done perfectly for defining the tooltip initially
const tooltip = d3.select(node)
.append("div")
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "2px")
.style("border-radius", "5px")
.style("padding", "5px")
.style("margin-bottom", '51px')
but while hovering you dont have to select any node by using d3.select(this) in mouseover and mouseleave state
you've written this
const mouseover = function (event, d) {
tooltip
.style("opacity", 1)
d3.select(this)
.style("stroke", "black")
.style("opacity", 1)
}
you can simply remove the d3.select(node) from chaining
Insted of doing like that you can simple change only opacity in mouseover
const mouseover = function(event, d) {
tooltip.style("opacity", 1)
}
if it's mouseleave just reverse
const mouseleave = function(event, d) {
tooltip.style("opacity", 0)
}
if it's a mousemove then you have to add html and postion properties for dynamic float of tooltip according to the mouse values like
Note one more thing dont use console in middle of chaining that may break the chaining, if you have tested with it then have to remove otherwise it won't work
const mousemove = function (event, d) {
tooltip
.html("The exact value of<br>this cell is: " + d.value)
.style("opacity", 1)
.style("left", (event.x) + 20 + "px")
.style("top", (event.y) + 20 + "px")
};
i hope this answer will get clarifies you
I want to make the axis lines either less opaque, or make them light grey. I tried to just do .style(opacity, 0.5), but it only makes the TICKS opaque, not the actual line itself. I want to make the ACTUAL LINE less opaque/light grey. I also tried adding the call(d3.axisLeft...).style(less opaque) approach but I still get nothing. How do I go about doing that?
import React, {Component, useRef, useEffect} from 'react';
import ExperienceScoresData from './experience_scores';
import * as d3 from "d3";
import { select, csv} from 'd3';
import { extent, max, min } from "d3-array";
ExperienceScoresData.map(function(val){
val.customerExperienceScore *= 100;
return 0;
})
class Linechart extends Component {
constructor(props){
super(props)
this.createBarChart = this.createBarChart.bind(this)
}
componentDidMount() {
this.createBarChart()
}
componentDidUpdate() {
this.createBarChart()
}
createBarChart() {
var margin = {top: 85, right: 60, bottom: 60, left: 80},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var node = this.node
var divObj = select(node)
var svgObj = divObj
.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 + ")");
//Read the data
d3.csv("https://raw.githubusercontent.com/QamarFarooq/data-for-testing/main/5_OneCatSevNumOrdered.csv", function(data) {
// group the data: I want to draw one line per group
var sumstat = d3.nest() // nest function allows to group the calculation per level of a factor
.key(function(d) { return d.name;})
.entries(data);
//console.log(sumstat)
// Define the div for the tooltip
var tooltip = divObj
.append("div")
.attr("class","tooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "1px")
.style("border-radius", "5px")
.style("padding", "10px")
.text("I AM A TOOLTIP pakistan zindabad");
// Add title for linechart
svgObj.append("text")
.attr("text-anchor", "end")
.attr("font-size", 25)
.attr("x", 110)
.attr("y", -50)
.text("Online Ratings");
// Add X axis --> it is a date format
var x = d3.scaleLinear()
.domain(d3.extent(data, function(d) { return d.year; }))
.range([ 0, width ]);
svgObj.append("g")
.attr("transform", "translate(0," + height + ")")
.attr("stroke-width","0.3")
.style("opacity","0.5")
.call(d3.axisBottom(x).tickSize(-height).tickFormat('').ticks(5));
// ticks
svgObj.append("g")
.style("opacity","0.85")
.style("font", "14px times")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).ticks(5));
// Add Y axis
var y = d3.scaleLinear()
.domain([0, d3.max(data, function(d) { return +d.n; })])
.range([ height, 0 ]);
svgObj.append("g")
.attr("stroke-width","0.3")
.style("opacity","0.5")
.call(d3.axisLeft(y).tickSize(-width).tickFormat('').ticks(5));
// ticks
svgObj.append("g")
.style("opacity","0.85")
.style("font", "14px times")
.call(d3.axisLeft(y).ticks(5));
// Add X axis label:
svgObj.append("text")
.attr("text-anchor", "end")
.attr("font-size", 20)
.attr("x", width/2 + margin.left)
.attr("y", height + 50)
.style("fill", d3.color("grey"))
.text("Year Of Birth");
// Add Y axis label:
svgObj.append("text")
.attr("text-anchor", "end")
.attr("font-size", 20)
.attr("transform", "rotate(-90)")
.attr("x", -height/2 + 40)
.attr("y", -margin.left + 25)
.style("fill", d3.color("grey"))
.text("N-Value")
// color palette
var key = sumstat.map(function(d){ return d.key }) // list of group names
var color = d3.scaleOrdinal()
.domain(key)
.range(['#e41a1c','#377eb8','#4daf4a'])
// Add one DOT in the legend for each name.
svgObj.selectAll(".dots")
.data(key)
.enter()
.append("circle")
.attr("cx", function(d,i){ return 250 + i*120})
.attr("cy", -30)
.attr("r", 7)
.style("fill", function(d){ return color(d)})
// Add LABEL for legends of each dot.
svgObj.selectAll(".labels")
.data(key)
.enter()
.append("text")
.style("fill", d3.color("grey"))
.attr("x", function(d,i){ return 270 + i*120})
.attr("y", -28)
.text(function(d){ return d})
.attr("text-anchor", "left")
.style("alignment-baseline", "middle")
// Draw the line
svgObj.selectAll(".line")
.data(sumstat)
.enter()
.append("path")
.attr("fill", "none")
.attr("stroke", function(d){ return color(d.key) })
.attr("stroke-width", 4.5)
.attr("d", function(d){
return d3.line()
.curve(d3.curveMonotoneX)
.x(function(d) { return x(d.year); })
.y(function(d) { return y(+d.n); })
(d.values)
})
.on("mouseover", function(){return tooltip.style("visibility", "visible");})
.on("mousemove", function(){return tooltip.style("top", (d3.event.pageY-10)+"px").style("left",(d3.event.pageX+10)+"px");})
.on("mouseout", function(){return tooltip.style("visibility", "hidden");})
var dataUnpacked = sumstat.map( function(d){return d.values})
console.log(data)
// Draw dots on points
svgObj.selectAll(".lineChartDots")
.data(data)
.enter()
.append("circle")
.attr("class","lineChartDots")
.style("fill","white")
.style("stroke-width", "3px")
.style("stroke", function (d) { return color(d.name) })
.attr("cx", function(d) {return x(d.year); })
.attr("cy", function(d) {return y(d.n); })
.attr("r", 5.5)
})
}
render() {
return <div ref={node => this.node = node} className="example_div"> </div>
}
}
export default Linechart;
The following could change the axis line's opacity.
svg.append("g")
.style("opacity", 0.5)
.call(d3.axisLeft(y))
.call(g => { // manipulate the elements' attrs here
g.select("path")
.attr("opacity", 0.5)
});
I run your code and found that the above code actually worked but since there are two svg lines in the axis, both the axis path and the first background grid line, so you might feel the opacity wasn't changed. See jsfiddle here.
a simple demo:
<!DOCTYPE html>
<meta charset="utf-8">
<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>
<script>
// set the dimensions and margins of the graph
var margin = {top: 10, right: 30, bottom: 30, left: 60},
width = 460 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("#my_dataviz")
.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 + ")");
//Read the data
d3.csv("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/3_TwoNumOrdered_comma.csv",
// When reading the csv, I must format variables:
function(d){
return { date : d3.timeParse("%Y-%m-%d")(d.date), value : d.value }
},
// Now I can use this dataset:
function(data) {
// Add X axis --> it is a date format
var x = d3.scaleTime()
.domain(d3.extent(data, function(d) { return d.date; }))
.range([ 0, width ]);
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// Add Y axis
var y = d3.scaleLinear()
.domain([0, d3.max(data, function(d) { return +d.value; })])
.range([ height, 0 ]);
svg.append("g")
.style("opacity", 0.5)
.call(d3.axisLeft(y))
.call(g => {
g.select("path")
.attr("opacity", 0.5)
});
// Add the line
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 1.5)
.attr("d", d3.line()
.x(function(d) { return x(d.date) })
.y(function(d) { return y(d.value) })
)
})
</script>
I am working on creating a horizontal bar chart using D3 in a ReactJS application. The issue I'm having is that the bars are too long and get cut off. How can I scale the bars down proportionally?
Appreciate any advice.
If you want to fit your chart then you need to change width/height of container where your chart is rendered (see <svg> in code below). Usually bars maximum height or width must not exceed correspondent container's dimension size, so probably you have an error somewhere in code. It would be helpful if you could share your code.
Here I provide an example of horizontal bar chart that scales correctly (original: https://bl.ocks.org/caravinden/eb0e5a2b38c8815919290fa838c6b63b):
var data = [{"salesperson":"Bob","sales":33},{"salesperson":"Robin","sales":12},{"salesperson":"Anne","sales":41},{"salesperson":"Mark","sales":16},{"salesperson":"Joe","sales":159},{"salesperson":"Eve","sales":38},{"salesperson":"Karen","sales":21},{"salesperson":"Kirsty","sales":25},{"salesperson":"Chris","sales":30},{"salesperson":"Lisa","sales":47},{"salesperson":"Tom","sales":5},{"salesperson":"Stacy","sales":20},{"salesperson":"Charles","sales":13},{"salesperson":"Mary","sales":29}];
// set the dimensions and margins of the graph
var
svg = d3.select("svg"),
margin = {top: 20, right: 20, bottom: 30, left: 60},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
// set the ranges
var y = d3.scaleBand()
.range([height, 0])
.padding(0.1);
var x = d3.scaleLinear()
.range([0, width]);
// append a 'group' element to 'svg'
// moves the 'group' element to the top left margin
svg = svg
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// format the data
data.forEach(function(d) {
d.sales = +d.sales;
});
// Scale the range of the data in the domains
x.domain([0, d3.max(data, function(d){ return d.sales; })])
y.domain(data.map(function(d) { return d.salesperson; }));
//y.domain([0, d3.max(data, function(d) { return d.sales; })]);
// append the rectangles for the bar chart
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
//.attr("x", function(d) { return x(d.sales); })
.attr("width", function(d) {return x(d.sales); } )
.attr("y", function(d) { return y(d.salesperson); })
.attr("height", y.bandwidth());
// add the x Axis
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// add the y Axis
svg.append("g")
.call(d3.axisLeft(y));
.bar {
fill: steelblue;
}
.bar:hover {
fill: brown;
}
.axis--x path {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.5.0/d3.min.js"></script>
<svg width="300" height="500"></svg>
I'm trying d3 for the very first time and I'm trying to understand how to create a dynamic d3 line chart that needs to get updated every time I receive a websocket message from the server with new a new data point.
I have the below code within my angular directive link function:
var data = [];
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().range([height, 0]);
var xAxis = d3.svg.axis().scale(x)
.orient("bottom");
var yAxis = d3.svg.axis().scale(y)
.orient("left");
var valueline = d3.svg.line()
.x(function (d) { return x(d['label']); })
.y(function (d) { return y(d['value']); });
var svg = d3.select(elem[0])
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("path")
.attr("class", "line")
.attr("d", valueline(data));
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
Statistics.listen('topic', function(message) {
data.push({
label: message.webEvent.creationTimeStamp,
value: +message.webEvent.value
});
x.domain(d3.extent(data, function (d) { return d.label; }));
y.domain([
d3.min(data, function(d) { return d.value; }),
d3.max(data, function(d) { return d.value; })
]);
var svg = d3.select(elem[0]).transition();
svg.select(".line") // change the line
.duration(0)
.attr("d", valueline(data));
svg.select(".x.axis") // change the x axis
.duration(0)
.call(xAxis);
svg.select(".y.axis") // change the y axis
.duration(0)
.call(yAxis);
}
I'm not sure what the purpose of the "duration" is. The messages do not come through the socket at regular intervals. So I'm not sure if I should set a static duration value which I assume refreshes the graph based on the number given. I want the graph to update as and when I get an update. The graph, over time, should look like a running sine wave.
Right now, the first data that come gets rendered. But the graph stays static after that even though I can see incoming messages on the websocket and the data array is growing.
What am I missing? Any help is greatly appreciated.
I have an area graph ( see js fiddle https://jsfiddle.net/o7df3tyn/ ) I want to animate this area graph. I tried the approach in this
question , but this doesnt seem to help because I have more line graphs in the the same svg element
var numberOfDays = 30;
var vis = d3.select('#visualisation'),
WIDTH = 1000,
HEIGHT = 400,
MARGINS = {
top: 20,
right: 20,
bottom: 20,
left: 50
};
var drawArea = function (data) {
var areaData = data;
// var areaData = data.data;
var xRange = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]).domain([0, numberOfDays + 1]),
yRange = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([_.min(areaData), _.max(areaData)]);
var area = d3.svg.area()
.interpolate("monotone")
.x(function(d) {
return xRange(areaData.indexOf(d));
})
.y0(HEIGHT)
.y1(function(d) {
return yRange(d);
});
var path = vis.append("path")
.datum(areaData)
.attr("fill", 'lightgrey')
.attr("d", area);
};
var data = [1088,978,1282,755,908,1341,616,727,1281,247,1188,11204,556,15967,623,681,605,7267,4719,9665,5719,5907,3520,1286,1368,3243,2451,1674,1357,7414,2726]
drawArea(data);
So I cant use the curtain approach.
I want to animate the area from bottom.
Any ideas / explanations ?
Just in case anyone else stuck in the same problem, #thatOneGuy nailed the exact problem. My updated fiddle is here https://jsfiddle.net/sahils/o7df3tyn/14/
https://jsfiddle.net/DavidGuan/o7df3tyn/2/
vis.append("clipPath")
.attr("id", "rectClip")
.append("rect")
.attr("width", 0)
.attr("height", HEIGHT);
You can have a try now.
Remember add clip-path attr to the svg elements you want to hide
In this case
var path = vis.append("path")
.datum(areaData)
.attr("fill", 'lightgrey')
.attr("d", area)
.attr("clip-path", "url(#rectClip)")
Update:
If we want to grow the area from bottom:
vis.append("clipPath")
.attr("id", "rectClip")
.append("rect")
.attr("width", WIDTH)
.attr("height", HEIGHT)
.attr("transform", "translate(0," + HEIGHT + ")")
d3.select("#rectClip rect")
.transition().duration(6000)
.attr("transform", "translate(0," + 0 + ")")
The other answer is okay but this doesn't animate the graph.
Here is how I would do it.
I would add an animation tween to the path so it tweens from 0 to the point on the path.
Something like so :
//create an array of 0's the same size as your current array :
var startData = areaData.map(function(datum) {
return 0;
});
//use this and tween between startData and data
var path = vis.append("path")
.datum(startdata1)
.attr("fill", 'lightgrey')
.attr("d", area)
.transition()
.duration(1500)
.attrTween('d', function() {
var interpolator = d3.interpolateArray(startData, areaData );
return function(t) {
return area(interpolator(t));
}
});
The reason why yours wasn't working was because of this line :
.x(function(d) {
return xRange(areaData.indexOf(d));
})
d at this point is a value between 0 and the current piece of data, so areaData.indexOf(d) will not work.
Just change this :
.x(function(d,i) {
return xRange(i);
})
This will increment along the x axis :)
Updated fiddle : https://jsfiddle.net/thatOneGuy/o7df3tyn/17/