chartx
Version:
Data Visualization Chart Library
634 lines (622 loc) • 20.8 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _canvax = _interopRequireDefault(require("canvax"));
function _callSuper(t, o, e) { return o = (0, _getPrototypeOf2.default)(o), (0, _possibleConstructorReturn2.default)(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], (0, _getPrototypeOf2.default)(t).constructor) : o.apply(t, e)); }
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } //单环pie
var _ = _canvax.default._,
event = _canvax.default.event;
var Sector = _canvax.default.Shapes.Sector;
var Path = _canvax.default.Shapes.Path;
var Text = _canvax.default.Display.Text;
var animation = _canvax.default.animation;
var Pie = exports.default = /*#__PURE__*/function (_event$Dispatcher) {
function Pie(_graphs, data) {
var _this;
(0, _classCallCheck2.default)(this, Pie);
_this = _callSuper(this, Pie);
_this.width = 0;
_this.height = 0;
_this.origin = {
x: 0,
y: 0
};
//这个pie所属的graphs对象
_this._graphs = _graphs;
_this.domContainer = _graphs.app.canvax.domView;
_this.data = data;
_this.sprite = null;
_this.textSp = null;
_this.sectorsSp = null;
_this.selectedSp = null;
_this.init();
_this.sectors = [];
_this.textMaxCount = 15;
_this.textList = [];
_this.completed = false; //首次加载动画是否完成
return _this;
}
(0, _inherits2.default)(Pie, _event$Dispatcher);
return (0, _createClass2.default)(Pie, [{
key: "init",
value: function init() {
this.sprite = new _canvax.default.Display.Sprite();
this.sectorsSp = new _canvax.default.Display.Sprite();
this.sprite.addChild(this.sectorsSp);
this.selectedSp = new _canvax.default.Display.Sprite();
this.sprite.addChild(this.selectedSp);
if (this._graphs.label.enabled) {
this.textSp = new _canvax.default.Display.Sprite();
}
;
}
}, {
key: "draw",
value: function draw(opt) {
var me = this;
_.extend(true, this, opt);
this.sprite.context.x = me.origin.x;
this.sprite.context.y = me.origin.y;
me._widget();
}
}, {
key: "resetData",
value: function resetData(data) {
var me = this;
this.data = data;
me.destroyLabel();
var completedNum = 0;
for (var i = 0; i < me.sectors.length; i++) {
var sec = me.sectors[i];
var secData = this.data.list[i];
sec.animate({
r: secData.outRadius,
startAngle: secData.startAngle,
endAngle: secData.endAngle
}, {
duration: 280,
onComplete: function onComplete() {
completedNum++;
if (completedNum == me.sectors.length) {
if (me._graphs.label.enabled) {
me._startWidgetLabel();
}
;
}
}
});
}
}
}, {
key: "_widget",
value: function _widget() {
var me = this;
var list = me.data.list;
var total = me.data.total;
//let moreSecData;
if (list.length > 0 && total > 0) {
me.textSp && me.sprite.addChild(me.textSp);
for (var i = 0; i < list.length; i++) {
var item = list[i];
//扇形主体
var sector = new Sector({
hoverClone: false,
xyToInt: false,
//扇形不需要自动取整
context: {
x: item.focused ? item.outOffsetx : 0,
y: item.focused ? item.outOffsety : 0,
r0: item.innerRadius,
r: item.outRadius,
startAngle: item.startAngle,
endAngle: item.endAngle,
fillStyle: item.fillStyle,
//iNode: item.iNode,
cursor: "pointer"
},
id: 'sector' + i
});
sector.nodeData = item;
item.focusEnabled && sector.hover(function () {
me.focusOf(this.nodeData);
}, function () {
!this.nodeData.selected && me.unfocusOf(this.nodeData);
});
//触发注册的事件
sector.on(event.types.get(), function (e) {
//me.fire( e.type, e );
e.eventInfo = {
trigger: 'this._graphs.node',
//me._graphs.node,
nodes: [this.nodeData]
};
//图表触发,用来处理Tips
me._graphs.app.fire(e.type, e);
});
me.sectorsSp.addChildAt(sector, 0);
me.sectors.push(sector);
}
;
if (me._graphs.label.enabled) {
me._startWidgetLabel();
}
;
}
}
}, {
key: "focusOf",
value: function focusOf(node, callback) {
if (node.focused) return;
var me = this;
var sec = me.sectors[node.iNode];
sec.animate({
//x: node.outOffsetx,
//y: node.outOffsety
r: node.outRadius + node.moveDis
}, {
duration: 100,
onComplete: function onComplete() {
callback && callback();
}
});
node.focused = true;
}
}, {
key: "unfocusOf",
value: function unfocusOf(node, callback) {
if (!node.focused) return;
var me = this;
var sec = me.sectors[node.iNode];
sec.animate({
//x: 0,
//y: 0
r: node.outRadius
}, {
duration: 100,
onComplete: function onComplete() {
callback && callback();
}
});
node.focused = false;
}
}, {
key: "selectOf",
value: function selectOf(node) {
var me = this;
if (!this.sectors.length || !node.selectEnabled) {
return;
}
;
var sec = this.sectors[node.iNode];
if (node.selected) {
return;
}
;
if (!node.focused) {
node._focusTigger = "select";
this.focusOf(node, function () {
me.addCheckedSec(sec);
});
} else {
this.addCheckedSec(sec);
}
;
node.selected = true;
}
}, {
key: "unselectOf",
value: function unselectOf(node) {
var sec = this.sectors[node.iNode];
if (!node.selected || !node.selectEnabled) {
return;
}
;
var me = this;
me.cancelCheckedSec(sec, function () {
if (node._focusTigger == "select") {
me.unfocusOf(node);
}
;
});
node.selected = false;
}
}, {
key: "addCheckedSec",
value: function addCheckedSec(sec, callback) {
var secc = sec.context;
var nodeData = sec.nodeData;
if (!secc) return;
var sector = new Sector({
xyToInt: false,
context: {
x: secc.x,
y: secc.y,
r0: secc.r - 1,
r: secc.r + nodeData.selectedR,
startAngle: secc.startAngle,
endAngle: secc.startAngle,
//secc.endAngle,
fillStyle: secc.fillStyle,
globalAlpha: nodeData.selectedAlpha
},
id: 'selected_' + sec.id
});
sec._selectedSec = sector;
this.selectedSp.addChild(sector);
if (this.completed) {
sector.animate({
endAngle: secc.endAngle
}, {
duration: this._getAngleTime(secc),
onComplete: function onComplete() {
callback && callback();
}
});
} else {
sector.context.endAngle = secc.endAngle;
}
}
}, {
key: "cancelCheckedSec",
value: function cancelCheckedSec(sec, callback) {
var selectedSec = sec._selectedSec;
selectedSec.animate({
startAngle: selectedSec.context.endAngle - 0.5
}, {
duration: this._getAngleTime(sec.context),
onComplete: function onComplete() {
delete sec._selectedSec;
selectedSec.destroy();
callback && callback();
}
});
}
}, {
key: "_getAngleTime",
value: function _getAngleTime(secc) {
return Math.abs(secc.startAngle - secc.endAngle) / 360 * 500;
}
}, {
key: "grow",
value: function grow(callback) {
var me = this;
_.each(me.sectors, function (sec) {
if (sec.context) {
sec.context.r0 = 0;
sec.context.r = 0;
sec.context.startAngle = me._graphs.startAngle;
sec.context.endAngle = me._graphs.startAngle;
}
});
me._hideGrowLabel();
var _tween = animation.registTween({
from: {
process: 0
},
to: {
process: 1
},
duration: 500,
onUpdate: function onUpdate(status) {
for (var i = 0; i < me.sectors.length; i++) {
var sec = me.sectors[i];
var nodeData = sec.nodeData;
var secc = sec.context;
var _startAngle = nodeData.startAngle;
var _endAngle = nodeData.endAngle;
var _r = nodeData.outRadius;
var _r0 = nodeData.innerRadius;
if (secc) {
secc.r = _r * status.process;
secc.r0 = _r0 * status.process;
if (i == 0) {
secc.startAngle = _startAngle;
secc.endAngle = _startAngle + (_endAngle - _startAngle) * status.process;
} else {
var lastEndAngle = function (iNode) {
var lastIndex = iNode - 1;
var lastSecc = me.sectors[lastIndex].context;
if (lastIndex == 0) {
return lastSecc ? lastSecc.endAngle : 0;
}
if (lastSecc) {
return lastSecc.endAngle;
} else {
return arguments.callee(lastIndex);
}
}(i);
secc.startAngle = lastEndAngle;
secc.endAngle = secc.startAngle + (_endAngle - _startAngle) * status.process;
}
//如果已经被选中,有一个选中态
if (sec._selectedSec) {
sec._selectedSec.context.r0 = secc.r - 1;
sec._selectedSec.context.r = secc.r + nodeData.selectedR;
sec._selectedSec.context.startAngle = secc.startAngle;
sec._selectedSec.context.endAngle = secc.endAngle;
}
}
}
},
onComplete: function onComplete() {
//把下面me.sprite._tweens.push( _tween );的 动画实例删除
me.sprite._removeTween(_tween);
me._showGrowLabel();
me.completed = true;
callback && callback();
}
});
me.sprite._tweens.push(_tween);
}
}, {
key: "_widgetLabel",
value: function _widgetLabel(quadrant, indexs, lmin, rmin, isEnd, ySpaceInfo) {
var me = this;
var count = 0;
var data = me.data.list;
var minTxtDis = 15;
var textOffsetX = 5;
var currentIndex;
var preY, currentY, adjustX, txtDis, bwidth, bheight, bx, by;
var yBound, remainingNum, remainingY;
var clockwise = quadrant == 2 || quadrant == 4;
var isleft = quadrant == 2 || quadrant == 3;
var isup = quadrant == 3 || quadrant == 4;
var minY = isleft ? lmin : rmin;
//text的绘制顺序做修正,text的Y值在饼图上半部分(isup)时,Y值越小的先画,反之Y值在饼图下部分时,Y值越大的先画.
if (indexs.length > 0) {
indexs.sort(function (a, b) {
return isup ? data[a].edgey - data[b].edgey : data[b].edgey - data[a].edgey;
});
}
for (var i = 0; i < indexs.length; i++) {
currentIndex = indexs[i];
var itemData = data[currentIndex];
var outCircleRadius = itemData.outRadius + itemData.moveDis;
//若Y值小于最小值,不画text
if (!itemData.enabled || itemData.y < minY || count >= me.textMaxCount) continue;
count++;
currentY = itemData.edgey;
adjustX = Math.abs(itemData.edgex);
txtDis = currentY - preY;
if (i != 0 && (Math.abs(txtDis) < minTxtDis || isup && txtDis < 0 || !isup && txtDis > 0)) {
currentY = isup ? preY + minTxtDis : preY - minTxtDis;
if (outCircleRadius - Math.abs(currentY) > 0) {
adjustX = Math.sqrt(Math.pow(outCircleRadius, 2) - Math.pow(currentY, 2));
}
if (isleft && -adjustX > itemData.edgex || !isleft && adjustX < itemData.edgex) {
adjustX = Math.abs(itemData.edgex);
}
}
if (isEnd) {
yBound = isleft ? ySpaceInfo.left : ySpaceInfo.right;
remainingNum = indexs.length - i;
remainingY = isup ? yBound - remainingNum * minTxtDis : yBound + remainingNum * minTxtDis;
if (isup && currentY > remainingY || !isup && currentY < remainingY) {
currentY = remainingY;
}
}
preY = currentY;
if (!isEnd) {
if (isleft) {
ySpaceInfo.left = preY;
} else {
ySpaceInfo.right = preY;
}
}
;
var currentX = isleft ? -adjustX - textOffsetX : adjustX + textOffsetX;
var globalX = currentX + me.origin.x;
var globalY = currentY + me.origin.y;
if (globalX > me._graphs.app.width || globalY < 0 || globalY > me._graphs.app.height) {
return;
}
;
var pathStr = "M" + itemData.centerx + "," + itemData.centery;
pathStr += "Q" + itemData.outx + "," + itemData.outy + "," + currentX + "," + currentY;
var path = new Path({
context: {
lineType: 'solid',
path: pathStr,
lineWidth: 1,
strokeStyle: itemData.fillStyle
}
});
var textTxt = itemData.labelText;
var textEle = void 0;
if (me.domContainer) {
textEle = document.createElement("div");
textEle.style.cssText = " ;position:absolute;left:-1000px;top:-1000px;color:" + itemData.fillStyle + "";
textEle.innerHTML = textTxt;
me.domContainer.appendChild(textEle);
bwidth = textEle.offsetWidth;
bheight = textEle.offsetHeight;
} else {
//小程序等版本里面没有domContainer, 需要直接用cavnas绘制
textEle = new Text(textTxt, {
context: {
fillStyle: itemData.fillStyle
}
});
me.textSp.addChild(textEle);
bwidth = Math.ceil(textEle.getTextWidth());
bheight = Math.ceil(textEle.getTextHeight());
}
bx = isleft ? -adjustX : adjustX;
by = currentY;
switch (quadrant) {
case 1:
bx += textOffsetX;
by -= bheight / 2;
break;
case 2:
bx -= bwidth + textOffsetX;
by -= bheight / 2;
break;
case 3:
bx -= bwidth + textOffsetX;
by -= bheight / 2;
break;
case 4:
bx += textOffsetX;
by -= bheight / 2;
break;
}
;
//如果是dom 的话就会有style属性
if (textEle.style) {
textEle.style.left = bx + me.origin.x + "px";
textEle.style.top = by + me.origin.y + "px";
} else if (textEle.context) {
textEle.context.x = bx;
textEle.context.y = by;
}
;
me.textSp.addChild(path);
me.textList.push({
width: bwidth,
height: bheight,
x: bx + me.origin.x,
y: by + me.origin.y,
data: itemData,
textTxt: textTxt,
textEle: textEle
});
}
}
}, {
key: "_startWidgetLabel",
value: function _startWidgetLabel() {
var me = this;
var data = me.data.list;
var rMinPercentage = 0,
lMinPercentage = 0,
rMinY = 0,
lMinY = 0;
var quadrantsOrder = [];
var quadrantInfo = [{
indexs: [],
count: 0
}, {
indexs: [],
count: 0
}, {
indexs: [],
count: 0
}, {
indexs: [],
count: 0
}];
//默认从top开始画
var widgetInfo = {
right: {
startQuadrant: 4,
endQuadrant: 1,
clockwise: true,
indexs: []
},
left: {
startQuadrant: 3,
endQuadrant: 2,
clockwise: false,
indexs: []
}
};
for (var i = 0; i < data.length; i++) {
var cur = data[i].quadrant;
quadrantInfo[cur - 1].indexs.push(i);
quadrantInfo[cur - 1].count++;
}
//1,3象限的绘制顺序需要反转
if (quadrantInfo[0].count > 1) quadrantInfo[0].indexs.reverse();
if (quadrantInfo[2].count > 1) quadrantInfo[2].indexs.reverse();
if (quadrantInfo[0].count > quadrantInfo[3].count) {
widgetInfo.right.startQuadrant = 1;
widgetInfo.right.endQuadrant = 4;
widgetInfo.right.clockwise = false;
}
if (quadrantInfo[1].count > quadrantInfo[2].count) {
widgetInfo.left.startQuadrant = 2;
widgetInfo.left.endQuadrant = 3;
widgetInfo.left.clockwise = true;
}
widgetInfo.right.indexs = quadrantInfo[widgetInfo.right.startQuadrant - 1].indexs.concat(quadrantInfo[widgetInfo.right.endQuadrant - 1].indexs);
widgetInfo.left.indexs = quadrantInfo[widgetInfo.left.startQuadrant - 1].indexs.concat(quadrantInfo[widgetInfo.left.endQuadrant - 1].indexs);
var overflowIndexs, sortedIndexs;
if (widgetInfo.right.indexs.length > me.textMaxCount) {
sortedIndexs = widgetInfo.right.indexs.slice(0);
sortedIndexs.sort(function (a, b) {
return data[b].y - data[a].y;
});
overflowIndexs = sortedIndexs.slice(me.textMaxCount);
rMinPercentage = data[overflowIndexs[0]].percentage;
rMinY = data[overflowIndexs[0]].y;
}
if (widgetInfo.left.indexs.length > me.textMaxCount) {
sortedIndexs = widgetInfo.left.indexs.slice(0);
sortedIndexs.sort(function (a, b) {
return data[b].y - data[a].y;
});
overflowIndexs = sortedIndexs.slice(me.textMaxCount);
lMinPercentage = data[overflowIndexs[0]].percentage;
lMinY = data[overflowIndexs[0]].y;
}
quadrantsOrder.push(widgetInfo.right.startQuadrant);
quadrantsOrder.push(widgetInfo.right.endQuadrant);
quadrantsOrder.push(widgetInfo.left.startQuadrant);
quadrantsOrder.push(widgetInfo.left.endQuadrant);
var ySpaceInfo = {};
for (var _i = 0; _i < quadrantsOrder.length; _i++) {
var isEnd = _i == 1 || _i == 3;
me._widgetLabel(quadrantsOrder[_i], quadrantInfo[quadrantsOrder[_i] - 1].indexs, lMinY, rMinY, isEnd, ySpaceInfo);
}
}
}, {
key: "destroyLabel",
value: function destroyLabel() {
var me = this;
if (this.textSp) {
this.textSp.removeAllChildren();
}
;
_.each(this.textList, function (lab) {
if (me.domContainer) {
me.domContainer.removeChild(lab.textEle);
}
});
this.textList = [];
}
}, {
key: "_showGrowLabel",
value: function _showGrowLabel() {
if (this.textSp && this.textSp.context) {
this.textSp.context.globalAlpha = 1;
_.each(this.textList, function (lab) {
if (lab.textEle.style) {
lab.textEle.style.visibility = "visible";
}
});
}
}
}, {
key: "_hideGrowLabel",
value: function _hideGrowLabel() {
if (this.textSp && this.textSp.context) {
this.textSp.context.globalAlpha = 0;
_.each(this.textList, function (lab) {
if (lab.textEle.style) {
lab.textEle.style.visibility = "hidden";
}
});
}
}
}]);
}(event.Dispatcher);