持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情
开始绘制
引入D3模块
- 这里引入的是整个D3模块。最近D3官网的CDN有点问题,这里就直接全部引入。
<script src="https://d3js.org/d3.v7.min.js"></script>
数据
- 自定义数据格式。
var bColor = ['#4385F4', '#34A853', '#FBBC05', '#E94335', '#01ACC2', '#AAACC2']
var dataArr = [
[
{
x: 70.5,
y: 0.5,
shape: 0
},
{
x: 30.5,
y: 30.5,
shape: 0
},
{
x: 50.5,
y: 20.5,
shape: 0
},
{
x: 60.5,
y: 10.5,
shape: 0
},
{
x: 20.5,
y: 70.5,
shape: 0
},
{
x: 70.5,
y: 70.5,
shape: 0
},
{
x: 60.5,
y: 90.5,
shape: 0
},
{
x: 70.5,
y: 10.5,
shape: 0
},
{
x: 10.5,
y: 30.5,
shape: 0
},
{
x: 30.5,
y: 20.5,
shape: 0
}
],
[
{
x: 71.5,
y: 2.5,
shape: 1
},
{
x: 30.5,
y: 60.5,
shape: 1
},
{
x: 50.5,
y: 70.5,
shape: 1
},
{
x: 60.5,
y: 50.5,
shape: 1
},
{
x: 10.5,
y: 70.5,
shape: 1
},
{
x: 60.5,
y: 60.5,
shape: 1
},
{
x: 90.5,
y: 90.5,
shape: 1
},
{
x: 70.5,
y: 10.5,
shape: 1
},
{
x: 20.5,
y: 30.5,
shape: 1
},
{
x: 80.5,
y: 10.5,
shape: 1
}
]
]
添加画布
- 初始化画布。
var svg = d3
.select('.d3Chart')
.append('svg')
.attr('width', width)
.attr('height', height)
.style('background-color', '#1a3055')
// 图
var chart = svg.append('g').attr('transform', `translate(${margin * 2}, ${margin})`)
创建比例尺
- 根据需求创建比例迟。
// 线性比例尺
var xScale = d3.scaleLinear().range([0, 400]).domain([0, 100])
// 线性比例尺
var yScale = d3.scaleLinear().range([400, 0]).domain([0, 100])
// 序数比例尺 颜色
let colorScale = d3.scaleOrdinal().domain(d3.range(0, dataArr.length)).range(bColor)
绘制坐标轴
- 和折线图一样,根据比例尺使用
axis模块
自动绘制坐标轴。
// 坐标轴
const xAxis = d3.axisBottom(xScale).tickSize(-400)
chart.append('g').attr('transform', `translate(0, ${400})`).call(xAxis)
// 坐标轴
const yAxis = d3
.axisLeft()
.scale(yScale)
.tickSize(-400)
.tickFormat((d) => {
return d + '%'
})
chart.append('g').attr('transform', 'translate(0, 0)').call(yAxis)
d3.selectAll('.d3Chart text').style('fill', '#fff')
d3.selectAll('.d3Chart line').style('stroke', '#fff')
d3.selectAll('.d3Chart path').style('stroke', '#fff')
- 和上一节一样使用
.tickSize()
绘制网格。
绘制散点
const groups = chart.append('g').selectAll().data(dataArr)
const points = groups
.enter()
.append('g')
.attr('fill', (d, i) => bColor[i])
.selectAll()
.data((d) => d)
- 创建绘制组
g
,绑定数据。 - 为每一种类型创建新的组
g
,绑定点数据。
points
.enter()
.append('path')
.attr('transform', (d) => 'translate(' + xScale(d.x) + ',' + yScale(d.y) + ')')
.attr('class', 'pathCircle')
.attr(
'd',
d3
.symbol()
.type(function (d) {
return d3.symbols[d.shape]
})
.size(1)
)
.transition()
.duration(500)
.attr(
'd',
d3
.symbol()
.type(function (d) {
return d3.symbols[d.shape]
})
.size(100)
)
- 对每个数据绘制形状。
- 使用
d3.symbol()
创建初始形状,然后添加动画。由小变大。
d3.symbol()
创建一个新的符号生成器。d3.symbols
数组。0~6 对应D3中绘制好的形状。symbol.type()
设置符号的类型。symbol.size()
设置符号的大小。
交互动画
function arcTweenMouse(type) {
return function () {
if (type) {
d3.select(this)
.transition()
.attr(
'd',
d3
.symbol()
.type(function (d) {
return d3.symbols[d.shape]
})
.size(300)
)
} else {
d3.select(this)
.transition()
.attr(
'd',
d3
.symbol()
.type(function (d) {
return d3.symbols[d.shape]
})
.size(100)
)
}
}
}
d3.selectAll('.pathCircle').on('mouseover', arcTweenMouse(true)).on('mouseout', arcTweenMouse(false))
- 通过标识符获取符号对象。
- 监听鼠标事件,放大缩小符号。
- 代码地址