在 G2 中,我们提供了四种动画场景类型:

  • appear: 初始化时的入场动画;

  • enter: 更新时的出现动画;

  • update: 更新时的变化动画;

  • leave: 更新时的动画;

通过如下方式为图形定义这四种动画场景的配置:

  1. // 配置更新时的入场动画,其他动画类型相同
  2. geom.animate({
  3. enter: {
  4. animation: 'fadeIn', // 动画名称
  5. easing: 'easeQuadIn', // 动画缓动效果
  6. delay: 100, // 动画延迟执行时间
  7. duration: 600 // 动画执行时间
  8. }
  9. });

另外 easing delay duration 均可支持回调,如下:

  1. /**
  2. * @param {Number} index shape 的索引值
  3. * @param {Number} id shape 的 id 标识
  4. **/
  5. delay(index, id) {}

参数 animation 为对应执行的动画名称,G2 默认内置了如下几种动画:

  1. {
  2. enter: {
  3. clipIn,
  4. zoomIn,
  5. pathIn,
  6. scaleInY,
  7. scaleInX,
  8. fanIn,
  9. fadeIn
  10. },
  11. leave: {
  12. lineWidthOut,
  13. zoomOut,
  14. pathOut,
  15. fadeOut
  16. },
  17. appear: {
  18. clipIn,
  19. zoomIn,
  20. pathIn,
  21. scaleInY,
  22. scaleInX,
  23. fanIn,
  24. fadeIn
  25. },
  26. update: {
  27. fadeIn,
  28. fanIn
  29. }
  30. }

如果上述动画动作不满足需求,用户也可以自己注册动画动作:

  1. const { Animate } = G2;
  2. /**
  3. * @param {String} animationType 动画场景类型 appear enter leave update
  4. * @param {String} 动画名称,用户自定义即可
  5. * @param {Function} 动画执行函数
  6. **/
  7. Animate.registerAnimation(animationType, animationName, animationFun);

图形 Shape 的动画接口说明:shape.animate(props, duration, delay, easing, callback)

  1. /**
  2. * 执行动画
  3. * @param {Object} toProps 动画最终状态
  4. * @param {Number} duration 动画执行时间
  5. * @param {Number} delay 动画延迟时间
  6. * @param {String} easing 动画缓动效果
  7. * @param {Function} callback 动画执行后的回调
  8. */
  9. shape.animate(toProps, duration, delay = 0, easing, callback);

说明:

easing 动画缓动效果参见 d3-ease

例子
  1. const { Chart, Animate, Util } = G2;
  2. Animate.registerAnimation('appear', 'delayScaleInY', function(shape, animateCfg) {
  3. const box = shape.getBBox(); // 获取柱子包围盒
  4. const origin = shape.get('origin'); // 获取柱子原始数据
  5. const points = origin.points; // 获取柱子顶点
  6. // 计算柱子的变换中点
  7. const centerX = (box.minX + box.maxX) / 2;
  8. let centerY;
  9. if (points[0].y - points[1].y <= 0) { // 当顶点在零点之下
  10. centerY = box.maxY;
  11. } else {
  12. centerY = box.minY;
  13. }
  14. // 设置初始态
  15. shape.attr('transform', [
  16. [ 't', -centerX, -centerY ],
  17. [ 's', 1, 0.1 ],
  18. [ 't', centerX, centerY ]
  19. ]);
  20. const index = shape.get('index');
  21. let delay = animateCfg.delay;
  22. if (Util.isFunction(delay)) {
  23. delay = animateCfg.delay(index);
  24. }
  25. let easing = animateCfg.easing;
  26. if (Util.isFunction(easing)) {
  27. easing = animateCfg.easing(index);
  28. }
  29. // 设置动画目标态
  30. shape.animate({
  31. transform: [
  32. [ 't', -centerX, -centerY ],
  33. [ 's', 1, 10 ],
  34. [ 't', centerX, centerY ]
  35. ]
  36. }, animateCfg.duration, easing, animateCfg.callback, delay);
  37. });
  38. const data = [];
  39. for (let i = 0; i < 50; i++) {
  40. data.push({
  41. x: i,
  42. y: (Math.sin(i / 5) * (i / 5 - 10) + i / 6) * 5
  43. });
  44. }
  45. const chart = new Chart({
  46. container: 'c1',
  47. forceFit: true,
  48. height: 400
  49. });
  50. chart.axis('x', false);
  51. chart.legend(false);
  52. chart.source(data);
  53. chart.interval()
  54. .position('x*y')
  55. .color('y', '#4a657a-#308e92-#b1cfa5-#f5d69f-#f5898b-#ef5055')
  56. .animate({
  57. appear: {
  58. animation: 'delayScaleInY',
  59. easing: 'easeElasticOut',
  60. delay(index) {
  61. return index * 10;
  62. }
  63. }
  64. });
  65. chart.render();