大屏中使用antv g2绘制的环图借助定时器实现联动效果

大屏页面中绘制的统计图实现动态变换的效果

在项目中,有一个大屏页面,主要是对项目中的数据进行整体的展示,既然是大屏,那么就不会是“死页面”,就必然要有动态效果。其中有一个需求就是让 通过antv g2绘制出的环图动起来,主要是动态改变图标每一项的样式,以及中间的Annotation。
基本样式就是这样
在这里插入图片描述

主要是要让他动态的放大某项并且中间的annotation也要展示对应已经放大项的数据;

在官网中查阅,基本上都是通过鼠标hover到图表项或者图例项时会出现想要的联动样式效果,这里可以参考这个实例 饼图图例联动
通过研究这个实例发现,其本质就是通过修改图表项的一个state状态来实现联动效果,因此抱着试一试的想法,开始了探索之路。。。

1、首先把图表画出来

我这里还是先用官网的数据和绘图方式,就是我上面的拿个链接

import { Chart } from '@antv/g2';

const data = [
  { item: '事例一', count: 40, percent: 0.4 },
  { item: '事例二', count: 21, percent: 0.21 },
  { item: '事例三', count: 17, percent: 0.17 },
  { item: '事例四', count: 13, percent: 0.13 },
  { item: '事例五', count: 9, percent: 0.09 },
];

const chart = new Chart({
  container: 'container',
  autoFit: true,
  height: 500,
});

chart.coordinate('theta', {
  radius: 0.75,
  innerRadius: 0.6,
});

chart.data(data);

chart.scale('percent', {
  formatter: val => {
    val = val * 100 + '%';
    return val;
  },
});

chart.tooltip(false);

//  这里记得要const一下 不然之后的方法中使用interval时会显示undefined
const interval = chart
  .interval()
  .adjust('stack')
  .position('percent')
  .color('item',['#5b8ff9','#5ad8a6','#5d7092','#f6bd16','#e86452'])
  .style({
    fillOpacity: 1,
  })
 //  定义active状态下的样式
  .state({
    active: {
      style: element => {
        const shape = element.shape;
        return {
          lineWidth: 10,
          stroke: shape.attr('fill'),
          strokeOpacity: shape.attr('fillOpacity'),
        };
      },
    },
  });

chart.render();

2、之后在官网实例的页面通过打印观察图表项的变化

在这里插入图片描述

通过这里可以看到,主要是通过修改图表中某项的state和stateStatus来修改选中与否的状态,从而实现后期的动态效果

通过打印可以看到ev中的数据
在这里插入图片描述

通过这里就能发现,实例中就是通过监听这个active状态修改图表中的Annotation内容以及图表项的active状态的样式,于是,可以通过定时器,定时修改某一项的active状态

/*
	由于我这里是要实现五个部分循环动态切换active状态,所以在循环的时候指定了i的范围,后期大家可以根据自己的需求自行修改代码
*/

// 通过定时器定时修改active状态
let i = 0
setInterval(()=>{
  if(i > 4){
    i=0
  }
  changeStatus(i)
  i++
},2000)
// 修改状态时不仅要修改当前项为active,也要记得清空其他项的active状态
function changeStatus(i){
   if(i>=1){
   		// 这里一定要用自带的setState方法,而不要直接变成true
       interval.elements[i].setState('active',true)
       interval.elements[i].stateStatus = true
       // 这里一定要用自带的clearStates方法,而不要直接变成false
       interval.elements[(i-1)].clearStates()
       interval.elements[(i-1)].stateStatus = false
       const state = interval.elements[i].states[0]
       const stateStatus = interval.elements[i].stateStatus
       let eledata = interval.elements[i].data
       if (state === 'active') {
           if (stateStatus) {
               // 更新 Annotation
               updateAnnotation(eledata);
           } else {
               // 隐藏 Annotation
               clearAnnotation();
           }
       }
   }else {
    // 临界情况单独考虑
    interval.elements[i].setState('active',true)
    interval.elements[i].stateStatus = true
    interval.elements[4].clearStates()
    interval.elements[4].stateStatus = false
    const state = interval.elements[i].states[0]
    const stateStatus = interval.elements[i].stateStatus
    let eledata = interval.elements[i].data
    if (state === 'active') {
      if (stateStatus) {
        // 更新 Annotation
        updateAnnotation(eledata);
      } else {
        // 隐藏 Annotation
        clearAnnotation();
      }
    }
  }
}

3、之后就可以自定义Annotation内容样式,以及清空annotation的方法

// 绘制 annotation
let lastItem;
function updateAnnotation(data) {
  if (data.item !== lastItem) {
    chart.annotation().clear(true);
    chart
      .annotation()
  .text({
    position: ['50%', '50%'],
    content: data.count+'%',
    style: {
      fontSize: 26,
      fill: '#ffe200',
      textAlign: 'center',
    },
    offsetY: -10,
  })
  .text({
    position: ['50%', '50%'],
    content: data.item,
    style: {
      fontSize: 14,
      fill: '#000000',
      textAlign: 'center',
    },
    offsetX: 0,
    offsetY: 20,
  })
    chart.render(true);
    lastItem = data.item;
  }
}

// 清空 annotation
function clearAnnotation() {
  chart.annotation().clear(true);
  chart.render(true);
  lastItem = null;
}

至此,随着整个过程中的各种“七拼八凑”,总算是实现了功能。不过也不是自己瞎凑,也是一直在查阅官方api的,由此得出结论,基础的api还是好东西,api吃透的,啥都不是事~

前端小菜鸡的第一篇博客,希望能帮助到看到的小伙伴们,如果各位大佬有什么更简单更高效的方法,也希望能收到您的私信分享,非常感谢~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值