由于最近接手一个大屏项目,加了个自动轮播循环的饼图示例功能,这个困扰了我一个礼拜,查了官方文档,也查了csdn其他文档,有一个文档是用的定时器做的,但在我这不生效,只好改成手写的了。
先上图(图片截的是静态的,但是成品是三段自动循环点击展示的):
![](https://img-blog.csdnimg.cn/img_convert/9b1672792550827e3c54cd7fdb6347cf.png)
正题来了,其实这些点击饼图之后出现的交互和点击事件都是在chart.render()之后加的
为了针对性的解决这个问题,我先上关键代码(最后会有全代码展示)
这边我是在render()下写了个setInterval函数来进行自动交互,其主要是在于更改antv官方给的选中的属性
// 移除图例点击过滤交互
chart.removeInteraction('legend-filter')
// chart.interaction('element-active')
chart.interaction('element-single-selected')
chart.render()
let count = 0
let timer
let lastItem
updateAnnotation(data[0])
function carousel() {
// if (count === 0) {
// interval.elements[0].setState('selected', count === 1 ? true : false)
// }
count++
interval.elements[0].setState('selected', count === 1 ? true : false)
interval.elements[1].setState('selected', count === 2 ? true : false)
interval.elements[2].setState('selected', count === 3 ? true : false)
if (count === interval.elements.length) {
count = 0
}
}
carousel()
timer = setInterval(carousel, 2000)
这边在写完手写的函数之后接上官方的参考文档,当然会有些改动
重点:如果没有stateStatus的话,你不需要隐藏Annotation,因为如果隐藏的话你的饼图自动走一轮是正常展示,但是从第二遍循环开始,第一条数据文字不会在饼图中间显示,一开始按照官方文档来也入了个坑,因为它会调用一个函数来清除中间的Annotation显示
如果你不需要自动循环播放只需要手动点击的话,上面的代码可以不写但是要加上clearAnnotation()函数,这边我加在最后面了,所以我会最后展示
// 监听 element 上状态的变化来动态更新 Annotation 信息
chart.on('element:statechange', (ev) => {
const { state, stateStatus, element } = ev.gEvent.originalEvent
// 本示例只需要监听 active 的状态变化
if (state === 'selected') {
const data = element.data
if (stateStatus) {
// 更新 Annotation
updateAnnotation(data)
} else {
// 隐藏 Annotation
// clearAnnotation()
}
}
})
在接上面的代码进行绘制饼图中心文字显示
// 绘制 annotation
function updateAnnotation(data) {
if (data.item !== lastItem) {
innerView.annotation().clear(true)
innerView
.annotation()
.text({
position: ['50%', '50%'],
content: data.item,
style: {
fontSize: 12,
fill: '#8c8c8c',
textAlign: 'center',
},
offsetY: 20,
})
.text({
position: ['50%', '50%'],
content: data.percent * 100,
style: {
fontSize: 20,
fill: '#8c8c8c',
textAlign: 'center',
},
offsetX: -10,
offsetY: -10,
})
.text({
position: ['50%', '50%'],
content: '%',
style: {
fontSize: 16,
fill: '#8c8c8c',
textAlign: 'center',
},
offsetY: -10,
offsetX: 10,
})
innerView.render(true)
lastItem = data.item
}
}
clearAnnotation函数:
// 清空 annotation
function clearAnnotation() {
innerView.annotation().clear(true)
innerView.render(true)
lastItem = null
}
整个饼图代码:
const chart = new Chart({
container: 'xxx',
width: 160,
height: 160,
padding: [0],
supportCSSTransform: true,
})
// 新建一个 view 用来单独渲染Annotation
const innerView = chart.createView()
chart.coordinate('theta', {
radius: 0.75,
innerRadius: 0.8,
})
chart.data(data)
chart.scale('percent', {
formatter: (val) => {
val = val * 100 + '%'
return val
},
})
chart.tooltip(false)
chart.legend(false)
const interval = chart
.interval()
.adjust('stack')
.position('percent')
.color('item', ['#a3f6ff', '#3fb787', '#6344e9'])
.style({
fillOpacity: 1,
})
.state({
active: {
style: (element) => {
const shape = element.shape
return {
// matrix: Util.zoom(shape, 1.1),
lineWidth: 10,
stroke: shape.attr('fill'),
strokeOpacity: shape.attr('fillOpacity'),
}
},
},
})
// 移除图例点击过滤交互
chart.removeInteraction('legend-filter')
// chart.interaction('element-active')
chart.interaction('element-single-selected')
chart.render()
let count = 0
let timer
let lastItem
updateAnnotation(data[0])
function carousel() {
console.log(interval.elements, count, data[0], '123')
// if (count === 0) {
// interval.elements[0].setState('selected', count === 1 ? true : false)
// }
count++
interval.elements[0].setState('selected', count === 1 ? true : false)
interval.elements[1].setState('selected', count === 2 ? true : false)
interval.elements[2].setState('selected', count === 3 ? true : false)
if (count === interval.elements.length) {
count = 0
}
}
carousel()
timer = setInterval(carousel, 2000)
// 监听 element 上状态的变化来动态更新 Annotation 信息
chart.on('element:statechange', (ev) => {
// console.log(ev.gEvent.originalEvent.element.data, 'click')
const { state, stateStatus, element } = ev.gEvent.originalEvent
// 本示例只需要监听 active 的状态变化
if (state === 'selected') {
const data = element.data
if (stateStatus) {
// 更新 Annotation
updateAnnotation(data)
} else {
// 隐藏 Annotation
// clearAnnotation()
}
}
})
// 绘制 annotation
// let lastItem
function updateAnnotation(data) {
if (data.item !== lastItem) {
innerView.annotation().clear(true)
innerView
.annotation()
.text({
position: ['50%', '50%'],
content: data.item,
style: {
fontSize: 12,
fill: '#8c8c8c',
textAlign: 'center',
},
offsetY: 20,
})
.text({
position: ['50%', '50%'],
content: data.percent * 100,
style: {
fontSize: 20,
fill: '#8c8c8c',
textAlign: 'center',
},
offsetX: -10,
offsetY: -10,
})
.text({
position: ['50%', '50%'],
content: '%',
style: {
fontSize: 16,
fill: '#8c8c8c',
textAlign: 'center',
},
offsetY: -10,
offsetX: 10,
})
innerView.render(true)
lastItem = data.item
}
}
// 清空 annotation
function clearAnnotation() {
innerView.annotation().clear(true)
innerView.render(true)
lastItem = null
}