SVG简介
svg是矢量图,无论放大或是缩小倍数都会重新绘制图像,不会像png/jpeg一样出现失真的情况
html5的canvas也是基于像素的,Canvas 绘制的图像都是Canvas的一部分,不能用js获取已经绘制好的图形元素,想改变里面某个元素的位置或者变化需要重新绘制;而SVG绘图时,每个图形都是以DOM节点的形式插入到页面中,可以用js或其他方法直接操作
水平柱状图(视频中的案例)
<!DOCTYPE html>
<html>
<head>
<title>firstDemo</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
</head>
<body>
<svg width="1500" height="800" id="mainsvg" class="svgs"></svg>
<script>
const data = [
{name:"AAA",value:56},
{name:"BBB",value:20},
{name:"CCC",value:43},
{name:"DDD",value:15},
{name:"EEE",value:67},
{name:"FFF",value:45},
{name:"GGG",value:31},
{name:"HHH",value:24},
{name:"III",value:78}
]
const svg = d3.select('#mainsvg');
const width = +svg.attr('width');
const height = +svg.attr('height');
const margin = {top:180 ,left:100, right:60, bottom:100};
const innerWidth = width - margin.left - margin.right; //作图区域
const innerHeight = height - margin.top - margin.bottom; // 作图区域
const xScale = d3.scaleLinear()
.domain([0,d3.max(data,d => d.value)])
.range([0,innerWidth]);
const yScale = d3.scaleBand()
.domain(data.map( d => d.name ))
.range([0,innerHeight])
.padding(0.1);
//padding:间隔
//定义作图区域
const g = svg.append('g')
.attr('id', 'maingroup')
.attr('transform', `translate(${margin.left} , ${margin.top})`);
const yAxis = d3.axisLeft(yScale); //只是坐标轴的定义,并不渲染
const xAxis = d3.axisBottom(xScale);
//一般的坐标轴渲染
const yAxisGroup = g.append('g').call(yAxis)
.attr('id', 'yaxis')
.append('text')
.text('Name')
.attr('font-size', '3em')
.attr('transform', 'rotate(-90)') // y-axis label needs an additional transform;
.attr('x', -innerHeight / 2)
.attr('y', -50)
.attr('fill', 'blue')
const xAxisGroup = g.append('g').call(xAxis)
.attr('id', 'xaxis')
.attr('transform', `translate(0, ${innerHeight})`)
.append('text')
.text('Value')
.attr('font-size', '3em')
.attr('x', innerWidth / 2)
.attr('y', 50)
.attr('fill', 'blue');
data.forEach(d => {
g.append('rect')
.attr('width',xScale(d.value))
.attr('height',yScale.bandwidth())
.attr('fill','green')
.attr('y', yScale(d.name))
.attr('opacity',0.8 );
});
//设置坐标轴文字大小
d3.selectAll('.tick text').attr('font-size', '20px');
//添加标题
g.append('text').text('This is my first D3.js demo').attr('font-size','3em')
.attr('transform', `translate(${innerWidth/2},-10)`)
.attr('text-anchor', 'middle');
</script>
</body>
</html>
效果
垂直柱状图(仿写的)
修修改改终于完成了
<!DOCTYPE html>
<html>
<head>
<title>firstDemo</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
</head>
<body>
<svg width="1500" height="800" id="mainsvg" class="svgs"></svg>
<script>
const data = [
{name:"AAA",value:56},
{name:"BBB",value:20},
{name:"CCC",value:43},
{name:"DDD",value:15},
{name:"EEE",value:67},
{name:"FFF",value:45},
{name:"GGG",value:31},
{name:"HHH",value:24},
{name:"III",value:78}
]
const svg = d3.select('#mainsvg');
//ele.attr('name')获取元素属性 ele.attr('name','value')设置元素属性 可以链式调用,返回的是元素本身
const width = +svg.attr('width');
const height = +svg.attr('height');
const margin = {top:180 ,left:100, right:60, bottom:100};
const innerWidth = width - margin.left - margin.right; //作图区域
const innerHeight = height - margin.top - margin.bottom; // 作图区域
//d3.scaleLinear()线性比例尺定义
//domain()输入数据的范围 range()输出数据的范围 是参数定义
const xScale = d3.scaleLinear()
.domain([0,d3.max(data,d => d.value)+10]) //以数据中最大的值作为轴长
.range([innerHeight,0]); //这里一定要注意 不然x轴的数值会倒过来
//d3.scaleBand()离散比例尺定义
const yScale = d3.scaleBand()
.domain(data.map( d => d.name ))
.range([0,innerWidth])
.padding(0.1);
//padding:间隔
//定义作图区域
const g = svg.append('g')
.attr('id', 'maingroup')
.attr('transform', `translate(${margin.left} , ${margin.top})`);
const yAxis = d3.axisBottom(yScale); //只是坐标轴的定义,并不渲染
const xAxis = d3.axisLeft(xScale);
//最简单的坐标轴设置方式:
// g.append('g').call(yAxis);
// g.append('g').call(xAxis).attr('transform', `translate(0,${innerHeight})`);
//一般的坐标轴渲染
const yAxisGroup = g.append('g').call(yAxis)
.attr('id', 'yaxis')
.attr('transform',`translate(0, ${innerHeight})`)
.append('text')
.text('Name')
.attr('font-size', '3em')
.attr('x', innerWidth / 2)
.attr('y', 50)
.attr('fill', 'purple')
const xAxisGroup = g.append('g').call(xAxis)
.attr('id', 'xaxis')
.append('text')
.text('Value')
.attr('font-size', '3em')
.attr('x',- innerHeight / 2)
.attr('transform','rotate(-90)')
.attr('y', -50)
.attr('fill', 'purple');
data.forEach(d => {
g.append('rect')
.attr('height', innerHeight - xScale(d.value))
.attr('width',yScale.bandwidth())
.attr('fill','pink')
.attr('x', yScale(d.name))
.attr('y',xScale(d.value))
.attr('opacity',0.8 );
});
/**
width: 矩形的宽
height: 矩形的高
fill :填充颜色
y :矩形位置,如果不设置默认为0;这相当于maingroup中的y值
x值不需要设置,默认为0
*/
//设置坐标轴文字大小
d3.selectAll('.tick text').attr('font-size', '20px');
//添加标题
g.append('text').text('This is my first D3.js demo').attr('font-size','3em')
.attr('transform', `translate(${innerWidth/2},-10)`)
.attr('text-anchor', 'middle');
</script>
</body>
</html>
效果
参考视频:【数据可视化编程-使用D3.js】 https://www.bilibili.com/video/BV1HK411L72d/?share_source=copy_web&vd_source=5b9cbd61061ece6129015f21873ee886