initial commit
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
/* *
|
||||
* Experimental dependency wheel module
|
||||
*
|
||||
* (c) 2018 Torstein Honsi
|
||||
*
|
||||
* License: www.highcharts.com/license
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import H from '../parts/Globals.js';
|
||||
import '../parts/Utilities.js';
|
||||
import '../parts/Options.js';
|
||||
import '../mixins/nodes.js';
|
||||
|
||||
var unsupportedSeriesType = H.seriesType;
|
||||
|
||||
var base = H.seriesTypes.sankey.prototype;
|
||||
|
||||
unsupportedSeriesType('dependencywheel', 'sankey', {
|
||||
center: [],
|
||||
curveFactor: 0.6,
|
||||
startAngle: 0
|
||||
}, {
|
||||
orderNodes: false,
|
||||
getCenter: H.seriesTypes.pie.prototype.getCenter,
|
||||
|
||||
// Dependency wheel has only one column, it runs along the perimeter
|
||||
createNodeColumns: function () {
|
||||
var columns = [this.createNodeColumn()];
|
||||
this.nodes.forEach(function (node) {
|
||||
node.column = 0;
|
||||
columns[0].push(node);
|
||||
});
|
||||
return columns;
|
||||
},
|
||||
|
||||
// Translate from vertical pixels to perimeter
|
||||
getNodePadding: function () {
|
||||
return this.options.nodePadding / Math.PI;
|
||||
},
|
||||
|
||||
createNode: function (id) {
|
||||
var node = base.createNode.call(this, id);
|
||||
node.index = this.nodes.length - 1;
|
||||
|
||||
// Return the sum of incoming and outgoing links
|
||||
node.getSum = function () {
|
||||
return node.linksFrom.concat(node.linksTo)
|
||||
.reduce(function (acc, link) {
|
||||
return acc + link.weight;
|
||||
}, 0);
|
||||
};
|
||||
|
||||
// Get the offset in weight values of a point/link.
|
||||
node.offset = function (point) {
|
||||
|
||||
var offset = 0,
|
||||
i,
|
||||
links = node.linksFrom.concat(node.linksTo),
|
||||
sliced;
|
||||
|
||||
function otherNode(link) {
|
||||
if (link.fromNode === node) {
|
||||
return link.toNode;
|
||||
}
|
||||
return link.fromNode;
|
||||
}
|
||||
|
||||
// Sort and slice the links to avoid links going out of each node
|
||||
// crossing each other.
|
||||
links.sort(function (a, b) {
|
||||
return otherNode(a).index - otherNode(b).index;
|
||||
});
|
||||
for (i = 0; i < links.length; i++) {
|
||||
if (otherNode(links[i]).index > node.index) {
|
||||
links = links.slice(0, i).reverse().concat(
|
||||
links.slice(i).reverse()
|
||||
);
|
||||
sliced = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!sliced) {
|
||||
links.reverse();
|
||||
}
|
||||
|
||||
for (i = 0; i < links.length; i++) {
|
||||
if (links[i] === point) {
|
||||
return offset;
|
||||
}
|
||||
offset += links[i].weight;
|
||||
}
|
||||
};
|
||||
|
||||
return node;
|
||||
},
|
||||
|
||||
// @todo: Override the refactored sankey translateLink and translateNode
|
||||
// functions instead of the whole translate function
|
||||
translate: function () {
|
||||
|
||||
var options = this.options,
|
||||
factor = 2 * Math.PI /
|
||||
(this.chart.plotHeight + this.getNodePadding()),
|
||||
center = this.getCenter(),
|
||||
startAngle = (options.startAngle - 90) * H.deg2rad;
|
||||
|
||||
base.translate.call(this);
|
||||
|
||||
this.nodeColumns[0].forEach(function (node) {
|
||||
var shapeArgs = node.shapeArgs,
|
||||
centerX = center[0],
|
||||
centerY = center[1],
|
||||
r = center[2] / 2,
|
||||
innerR = r - options.nodeWidth,
|
||||
start = startAngle + factor * shapeArgs.y,
|
||||
end = startAngle + factor * (shapeArgs.y + shapeArgs.height);
|
||||
|
||||
node.shapeType = 'arc';
|
||||
node.shapeArgs = {
|
||||
x: centerX,
|
||||
y: centerY,
|
||||
r: r,
|
||||
innerR: innerR,
|
||||
start: start,
|
||||
end: end
|
||||
};
|
||||
|
||||
node.dlBox = {
|
||||
x: centerX + Math.cos((start + end) / 2) * (r + innerR) / 2,
|
||||
y: centerY + Math.sin((start + end) / 2) * (r + innerR) / 2,
|
||||
width: 1,
|
||||
height: 1
|
||||
};
|
||||
|
||||
// Draw the links from this node
|
||||
node.linksFrom.forEach(function (point) {
|
||||
var distance;
|
||||
var corners = point.linkBase.map(function (top, i) {
|
||||
var angle = factor * top,
|
||||
x = Math.cos(startAngle + angle) * (innerR + 1),
|
||||
y = Math.sin(startAngle + angle) * (innerR + 1),
|
||||
curveFactor = options.curveFactor;
|
||||
|
||||
// The distance between the from and to node along the
|
||||
// perimeter. This affect how curved the link is, so that
|
||||
// links between neighbours don't extend too far towards the
|
||||
// center.
|
||||
distance = Math.abs(point.linkBase[3 - i] * factor - angle);
|
||||
if (distance > Math.PI) {
|
||||
distance = 2 * Math.PI - distance;
|
||||
}
|
||||
distance = distance * innerR;
|
||||
if (distance < innerR) {
|
||||
curveFactor *= (distance / innerR);
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
x: centerX + x,
|
||||
y: centerY + y,
|
||||
cpX: centerX + (1 - curveFactor) * x,
|
||||
cpY: centerY + (1 - curveFactor) * y
|
||||
};
|
||||
});
|
||||
|
||||
point.shapeArgs = {
|
||||
d: [
|
||||
'M',
|
||||
corners[0].x, corners[0].y,
|
||||
'A',
|
||||
innerR, innerR,
|
||||
0,
|
||||
0, // long arc
|
||||
1, // clockwise
|
||||
corners[1].x, corners[1].y,
|
||||
'C',
|
||||
corners[1].cpX, corners[1].cpY,
|
||||
corners[2].cpX, corners[2].cpY,
|
||||
corners[2].x, corners[2].y,
|
||||
'A',
|
||||
innerR, innerR,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
corners[3].x, corners[3].y,
|
||||
'C',
|
||||
corners[3].cpX, corners[3].cpY,
|
||||
corners[0].cpX, corners[0].cpY,
|
||||
corners[0].x, corners[0].y
|
||||
]
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user