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; */
}