AngularJS 整合 Echarts 做饼图

AngularJS 整合 Echarts 做饼图

Flying
2016-10-06 / 0 评论 / 134 阅读 / 正在检测是否收录...

Echarts 很强大有好用,是我工作中做数据 JavaScript 可视化功能的第一选择。本文就是目前项目的统计模块的 demo,希望对你有用。

chart-pie.svg

最终效果

老规矩,先看一下最终效果

分析问题

还记 AngularJS 指令怎样传递函数参数吗?我们将表格封装成了一个指令。如果不封装就没有传递函数参数的问题了吗?我们要重申的是,封装是必要的,封装可以复用代码。试想,如果在再加入一个图表,要求也可以按时间段下钻。如果不封装的话,下钻这块实现要写两次。而且真实场景多数是表格图表都会的。所以说还是封装成组件好。

实现

在前面我们已经将下钻功能放父作用域中,现在只用自定义图表组件,就可以通过指令中传递函数参数的方式调用父作用域中的下钻逻辑。看代码:

<div class="pie-chart" pie-chart source="profits" drill-down="drillDown(profit)"></div>

很简单吧?剩下的工作就是实现 echarts 插件的 AngularJS 版本。Echats 是 Enterprise Charts 的缩写,商业级数据图表,一个纯 Javascript 的图表库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器。此处我们把问题简化,只封装饼图。其实就是 AngularJS 整合第三方库 Javasctipt。

AngularJS 把 Javascript 的 context 分隔成两部分,一部分是原生的 Javascript 的 context,另一部分是 AngularJS 的 context。只有处在 AngularJS 的 context 中的操作才能享受到 Angular 的 data-binding、exception handling、$watch 等服务,但是对于外来者(如原生的 Javascript 操作、自定义的事件回调、第三方的库等)Angular 也不是一概不接见,可以使用 AngularJS 提供的 $apply() 函数将这些外来者包进 AngularJS 的 context 中,让 Angular 感知到他们产生的变化。如下面代码:

angular.module('myApp')
/**
   * Define pie echart directive
   * @param source {Array} chart data provider
   * @param drillDown {Function} click to drill down
   */
  .directive('pieChart', function($filter) {
    return {
      restrict: 'EA',
      scope: {
        source: '=',
        drillDown: '&'
      },
      link: function($scope, element, attrs) {
        var myChart = echarts.init(element[0]);
        /**
         * watch data source
         */
        $scope.$watchCollection('source', function(newValue, oldValue) {
          if (newValue) {
            var legend = [];
            angular.forEach(newValue, function(val) {
              legend.push(val.name);
            });
            var option = {
              tooltip: {
                trigger: 'item',
                formatter: function(params) {
                  return params.name + ' : ' +
                    $filter('number')(params.value) +
                    ' (' + params.percent.toFixed(2) + '%)';
                }
              },
              legend: {
                orient: 'vertical',
                left: 'left',
                data: legend
              },
              series: [{
                type: 'pie',
                radius: '55%',
                center: ['50%', '60%'],
                data: newValue,
                itemStyle: {
                  emphasis: {
                    shadowBlur: 10,
                    shadowOffsetX: 0,
                    shadowColor: 'rgba(0, 0, 0, 0.5)'
                  }
                }
              }]
            };
            myChart.setOption(option);
          }
          myChart.resize();
        });

        /**
         * click chart item to drill down
         */
        myChart.on('click', function(params) {
          $scope.$apply(function() {
            $scope.drillDown({profit: params.data});
          });
        });

        /**
         * adjust the chart size when resizing the window
         */
        window.onresize = function() {
          myChart.resize();
        };
      }
    };
  })

上面代码我们将 click 事件的回调处理包进 AngularJS 的 context 中让 AngularJS 来管理,然后就可以使用强大的 AngularJS 机制来处理问题了。另外,我们使用 $watchCollection 监听图表数据源 source 的变化并相应更新图表的配置。可以看到表格、图表、面包屑实现了三方联动,很酷吗?

值得注意的是,使用 $watchCollection 只会监听数组类型的数据变化,通常比 $watch 性能更好。

参考示例

访问 codepen 查看完整示例代码及效果

2

评论 (0)

取消