Line Chart
vizhub代码:
https://vizhub.com/Edward-Elric233/094396fc7a164c828a4a8c2e13045308
实现效果:
这里先使用d3.line()
设置每个点的x
坐标和y
坐标,然后再用这个东西设置path
的'd'
属性,就可以得到曲线。
const lineGenerator = d3.line().x(d => xScale(xValue(d))).y(d => yScale(yValue(d))).curve(d3.curveBasis); //使得曲线比较光滑g.append('path').attr('class', 'line-path').attr('d', lineGenerator(data));
index.html
<!DOCTYPE html>
<html><head><title>Temperature in San Francisc Line Chart</title><link rel="stylesheet" href="./styles.css"><script src="https://unpkg.com/d3@5.7.0/dist/d3.min.js"></script><!-- find D3 file on UNPKG d3.min.js-->
</head><body><svg width="960" height="500"></svg><script src="./index.js">// console.log(d3); test whether you have imported d3.js or not</script></body></html>
html.js
const svg = d3.select('svg');
// svg.style('background-color', 'red'); test
const width = +svg.attr('width');
const height = +svg.attr('height');const render = data => {const title = 'A week in San Francisco';const xValue = d => d.timestamp;const xAxisLabel = 'Time';const yValue = d => d.temperature;const yAxisLabel = 'Temperature';const margin = { top: 60, right: 20, bottom: 80, left: 100 };const innerWidth = width - margin.left - margin.right;const innerHeight = height - margin.top - margin.bottom;const circleRadius = 6;const xScale = d3.scaleTime()//.domain([min(data, xValue), max(data, xValue)]) //和下面的写法等价.domain(d3.extent(data, xValue)).range([0, innerWidth]).nice(); //作用是如果值域的最大值不够整齐可以变得整齐// const yScale = scaleBand()const yScale = d3.scaleLinear().domain([d3.max(data, yValue), d3.min(data, yValue)]).range([0, innerHeight]).nice();//const xAxisTickFormat = number => format('.3s')(number).replace('G','B');const yAxis = d3.axisLeft(yScale).tickSize(-innerWidth).tickPadding(15);const xAxis = d3.axisBottom(xScale)//.tickFormat(xAxisTickFormat).tickSize(-innerHeight) //设置tick-line的长度.tickPadding(15); //通过设置Padding让x轴的数字离远一点const g = svg.append('g').attr('transform', `translate(${margin.left},${margin.top})`);//yAxis(g.append('g'));const yAxisG = g.append('g').call(yAxis);yAxisG.selectAll('.domain').remove();yAxisG.append('text').attr('class', 'axis-label').attr('y', -70).attr('x', -innerHeight / 2).attr('fill', 'black').attr('transform', `rotate(-90)`).attr('text-anchor', 'middle') //设置锚点在中心.text(yAxisLabel);const xAxisG = g.append('g').call(xAxis).attr('transform', `translate(0,${innerHeight})`);xAxisG.selectAll('.domain').remove();xAxisG.append('text').attr('class', 'axis-label').attr('y', 60).attr('x', innerWidth / 2).attr('fill', 'black').text(xAxisLabel);let colorSet = ['#eb2617', '#ffaa00', '#4dff00', '#00fbff', '#bb00ff', '#eeff00'];const createGetColor = (idx) => {var i = idx || -1;return {get: () => { i = (i + 1) % colorSet.length; return colorSet[i]; }};};const getColor = createGetColor();const lineGenerator = d3.line().x(d => xScale(xValue(d))).y(d => yScale(yValue(d))).curve(d3.curveBasis); //使得曲线比较光滑g.append('path').attr('class', 'line-path').attr('d', lineGenerator(data));/*g.selectAll('circle').data(data).enter().append('circle').attr('cy', d=>yScale(yValue(d))).attr('cx', d => xScale(xValue(d))).attr('r', circleRadius).attr('fill', 'red');*/g.append('text').attr('class', 'title').attr('y', -20).attr('x', innerWidth / 2).attr('text-anchor', 'middle').text(title);
};d3.csv('https://vizhub.com/curran/datasets/temperature-in-san-francisco.csv').then(data => {// console.log(data);data.forEach(d => {//得到的数据默认每个属性的值都是字符串,因此需要进行转换d.temperature = +d.temperature;d.timestamp = new Date(d.timestamp);});render(data);
});
styles.css
body {margin: 0px;overflow: hidden;font-family: manosapce;
}circle {opacity: 0.5;
}text {font-family: sans-serif;
}.tick text {font-size: 2em;fill: #8E8883
}.tick line {stroke: #E5E2E0
}.axis-label {fill: #8E8883;font-size: 2.5em
}.title {font-size: 3em;fill: #8E8883
}.line-path {fill: none;stroke: steelblue;stroke-width: 5;stroke-linejoin: round /*使得曲线比较光滑*/
}
其实也可以在折现图上加上点,只需要去掉原本散点图的注释就可以了。但是我觉得这样不好看就没有加上。
Area Chart
vizhub代码:
https://vizhub.com/Edward-Elric233/9fa9b8c649cf41a3afcde6e185a72cca
https://vizhub.com/Edward-Elric233/39790021eded4d398be6f97726e73dd2
area
图只需要把使用line
的地方换成area
即可。不同的地方在于area
需要设置y0,y1,y
用来划分区域,而且需要设置path
的fill
属性,用来表示区域的颜色。一般来讲应该不需要设置线的stroke
和stroke-width
属性。
例如把上面的图变成Area Chart
需要修改的js代码如下:
const areaGenerator = area().x(d => xScale(xValue(d))).y1(d=>yScale(yValue(d))).y0(innerHeight).curve(curveBasis); //使得曲线比较光滑g.append('path').attr('class', 'line-path').attr('d', areaGenerator(data));
这里还画了一个图,把网格提到了图形的前面。
虽然有些丑,但是如果需要使用的话还是可以的。技巧就是先生成Area图,然后再生成坐标轴就可以了。这样坐标线就会显示在图形的上面。
index.html
<!DOCTYPE html>
<html><head><title>World Population Area Chart</title><link rel="stylesheet" href="./styles.css"><script src="https://unpkg.com/d3@5.7.0/dist/d3.min.js"></script><!-- find D3 file on UNPKG d3.min.js-->
</head><body><svg width="960" height="500"></svg><script src="./index.js">// console.log(d3); test whether you have imported d3.js or not</script></body></html>
index.js
const svg = d3.select('svg');
// svg.style('background-color', 'red'); test
const width = +svg.attr('width');
const height = +svg.attr('height');const render = data => {const title = 'World Population';const xValue = d => d.year;const xAxisLabel = 'Year';const yValue = d => d.population;const yAxisLabel = 'Population';const margin = { top: 60, right: 20, bottom: 80, left: 100 };const innerWidth = width - margin.left - margin.right;const innerHeight = height - margin.top - margin.bottom;const circleRadius = 6;const xScale = d3.scaleTime()//.domain([min(data, xValue), max(data, xValue)]) //和下面的写法等价.domain(d3.extent(data, xValue)).range([0, innerWidth])//.nice(); //作用是如果值域的最大值不够整齐可以变得整齐// const yScale = scaleBand()const yScale = d3.scaleLinear().domain([d3.max(data, yValue), 0]).range([0, innerHeight]).nice();const yAxisTickFormat = number => d3.format('.1s')(number).replace('G', 'B');const yAxis = d3.axisLeft(yScale).tickFormat(yAxisTickFormat).tickSize(-innerWidth).tickPadding(15);const xAxis = d3.axisBottom(xScale)//.tickFormat(xAxisTickFormat).ticks(10) //设置标签的多少,不知道为什么如果设置为10就会很乱,可能是因为这是一周的时间,如果划分成10个以上就需要显示小时吧.tickSize(-innerHeight) //设置tick-line的长度.tickPadding(15); //通过设置Padding让x轴的数字离远一点const g = svg.append('g').attr('transform', `translate(${margin.left},${margin.top})`);const areaGenerator = d3.area().x(d => xScale(xValue(d))).y1(d => yScale(yValue(d))).y0(innerHeight).curve(d3.curveBasis); //使得曲线比较光滑g.append('path').attr('class', 'line-path').attr('d', areaGenerator(data));//yAxis(g.append('g'));const yAxisG = g.append('g').call(yAxis);yAxisG.selectAll('.domain').remove();yAxisG.append('text').attr('class', 'axis-label').attr('y', -70).attr('x', -innerHeight / 2).attr('fill', 'black').attr('transform', `rotate(-90)`).attr('text-anchor', 'middle') //设置锚点在中心.text(yAxisLabel);const xAxisG = g.append('g').call(xAxis).attr('transform', `translate(0,${innerHeight})`);xAxisG.selectAll('.domain').remove();xAxisG.append('text').attr('class', 'axis-label').attr('y', 60).attr('x', innerWidth / 2).attr('fill', 'black').text(xAxisLabel);let colorSet = ['#eb2617', '#ffaa00', '#4dff00', '#00fbff', '#bb00ff', '#eeff00'];const createGetColor = (idx) => {var i = idx || -1;return {get: () => { i = (i + 1) % colorSet.length; return colorSet[i]; }};};const getColor = createGetColor();/*g.selectAll('circle').data(data).enter().append('circle').attr('cy', d=>yScale(yValue(d))).attr('cx', d => xScale(xValue(d))).attr('r', circleRadius).attr('fill', 'red');*/g.append('text').attr('class', 'title').attr('y', -20).attr('x', innerWidth / 2).attr('text-anchor', 'middle').text(title);
};d3.csv('https://vizhub.com/curran/datasets/world-population-by-year-2015.csv').then(data => {console.log(data);data.forEach(d => {//得到的数据默认每个属性的值都是字符串,因此需要进行转换d.population = +d.population;d.year = new Date(d.year);});render(data);
});
styles.css
body {margin: 0px;overflow: hidden;font-family: manosapce;
}circle {opacity: 0.5;
}text {font-family: sans-serif;
}.tick text {font-size: 2em;fill: #8E8883
}.tick line {stroke: #E5E2E0
}.axis-label {fill: #8E8883;font-size: 2.5em
}.title {font-size: 3em;fill: #8E8883
}.line-path {fill: #42A5B3;/* stroke : blue;stroke-width : 5; */
}