chordCircularLayout.js 3.88 KB
var zrUtil = require("zrender/lib/core/util");

var _number = require("../../util/number");

var parsePercent = _number.parsePercent;

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
 * Chord layout
 * @module echarts/chart/chord/chordCircularLayout
 * @author pissang(http://github.com/pissang)
 */

/**
 * @param {module:echarts/data/Graph} graph
 */
function layout(graphs, opts) {
  if (!zrUtil.isArray(graphs)) {
    graphs = [graphs];
  }

  var graph0 = graphs[0];
  var groups = []; // Init groups

  graph0.eachNode(function (node) {
    var group = {
      size: 0,
      subGroups: [],
      node: node
    };
    groups.push(group);
  });
  zrUtil.each(graphs, function (graph) {
    graph.eachEdge(function (edge) {
      var g1 = groups[edge.node1.dataIndex];
      g1.size += edge.getValue('value') || 0;
      g1.subGroups.push({
        size: edge.getValue('value'),
        edge: edge
      });
    });
  });
  var sumSize = zrUtil.reduce(groups, function (sumSize, group) {
    return sumSize + group.size;
  }, 0);

  if (opts.sort && opts.sort != 'none') {
    groups.sort(compareGroups);

    if (opts.sort === 'descending') {
      groups.reverse();
    }
  }

  var unitAngle = (Math.PI * 2 - opts.padding * graph0.data.count()) / sumSize;
  var angle = opts.startAngle * Math.PI / 180;
  var sign = opts.clockwise ? -1 : 1;
  zrUtil.each(groups, function (group) {
    if (opts.sortSub && opts.sortSub != 'none') {
      group.subGroups.sort(compareGroups);

      if (opts.sortSub === 'descending') {
        group.subGroups.reverse();
      }
    }

    var endAngle = angle + sign * group.size * unitAngle;
    group.node.setLayout({
      startAngle: -angle,
      endAngle: -endAngle,
      cx: opts.cx,
      cy: opts.cy,
      r0: opts.r0,
      r: opts.r,
      clockwise: opts.clockwise
    });
    zrUtil.each(group.subGroups, function (subGroup) {
      var startAngle = angle;
      var endAngle = angle + sign * subGroup.size * unitAngle;
      var layout = subGroup.edge.getLayout() || {
        cx: opts.cx,
        cy: opts.cy,
        r: opts.r0,
        clockwise: opts.clockwise
      };
      layout.startAngle = -startAngle;
      layout.endAngle = -endAngle;
      subGroup.edge.setLayout(layout);
      angle = endAngle;
    });
    angle = endAngle + sign * opts.padding;
  });
}

var compareGroups = function (a, b) {
  return a.size - b.size;
};

function _default(ecModel, api, payload) {
  ecModel.eachSeriesByType('chord', function (chordSeries) {
    var graph = chordSeries.getGraph();
    var center = chordSeries.get('center');
    var radius = chordSeries.get('radius');
    var viewWidth = api.getWidth();
    var viewHeight = api.getHeight();
    var viewSize = Math.min(viewWidth, viewHeight) / 2;
    layout(graph, {
      sort: chordSeries.get('sort'),
      sortSub: chordSeries.get('sortSub'),
      padding: chordSeries.get('padding'),
      startAngle: chordSeries.get('startAngle'),
      clockwise: chordSeries.get('clockwise'),
      cx: parsePercent(center[0], viewWidth),
      cy: parsePercent(center[1], viewHeight),
      r0: parsePercent(radius[0], viewSize),
      r: parsePercent(radius[1], viewSize)
    });
  });
}

module.exports = _default;