feat: DonutChart extends PieChart
This commit is contained in:
parent
dc00b46a7a
commit
73f1d9b1e3
@ -1,86 +1,28 @@
|
|||||||
import AggregationChart from './AggregationChart';
|
import PieChart from './PieChart';
|
||||||
import { getComponent } from '../objects/ChartComponents';
|
import { getComponent } from '../objects/ChartComponents';
|
||||||
import { getOffset } from '../utils/dom';
|
|
||||||
import { getPositionByAngle } from '../utils/helpers';
|
|
||||||
import { makeArcStrokePathStr, makeStrokeCircleStr } from '../utils/draw';
|
import { makeArcStrokePathStr, makeStrokeCircleStr } from '../utils/draw';
|
||||||
import { lightenDarkenColor } from '../utils/colors';
|
|
||||||
import { transform } from '../utils/animation';
|
|
||||||
import { FULL_ANGLE } from '../utils/constants';
|
|
||||||
|
|
||||||
export default class DonutChart extends AggregationChart {
|
export default class DonutChart extends PieChart {
|
||||||
constructor(parent, args) {
|
constructor(parent, args) {
|
||||||
super(parent, args);
|
super(parent, args);
|
||||||
this.type = 'donut';
|
|
||||||
this.initTimeout = 0;
|
|
||||||
this.init = 1;
|
|
||||||
|
|
||||||
this.setup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
configure(args) {
|
configure(args) {
|
||||||
super.configure(args);
|
super.configure(args);
|
||||||
this.mouseMove = this.mouseMove.bind(this);
|
|
||||||
this.mouseLeave = this.mouseLeave.bind(this);
|
|
||||||
|
|
||||||
this.hoverRadio = args.hoverRadio || 0.1;
|
this.type = 'donut';
|
||||||
this.config.startAngle = args.startAngle || 0;
|
this.sliceName = 'donutSlices';
|
||||||
|
|
||||||
|
this.arcFunc = makeArcStrokePathStr;
|
||||||
|
this.shapeFunc = makeStrokeCircleStr;
|
||||||
|
|
||||||
this.clockWise = args.clockWise || false;
|
|
||||||
this.strokeWidth = args.strokeWidth || 30;
|
this.strokeWidth = args.strokeWidth || 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
calc() {
|
getRadius() {
|
||||||
super.calc();
|
return this.height > this.width
|
||||||
let s = this.state;
|
? this.center.x - this.strokeWidth / 2
|
||||||
this.radius =
|
: this.center.y - this.strokeWidth / 2;
|
||||||
this.height > this.width
|
|
||||||
? this.center.x - this.strokeWidth / 2
|
|
||||||
: this.center.y - this.strokeWidth / 2;
|
|
||||||
|
|
||||||
const { radius, clockWise } = this;
|
|
||||||
|
|
||||||
const prevSlicesProperties = s.slicesProperties || [];
|
|
||||||
s.sliceStrings = [];
|
|
||||||
s.slicesProperties = [];
|
|
||||||
let curAngle = 180 - this.config.startAngle;
|
|
||||||
|
|
||||||
s.sliceTotals.map((total, i) => {
|
|
||||||
const startAngle = curAngle;
|
|
||||||
const originDiffAngle = (total / s.grandTotal) * FULL_ANGLE;
|
|
||||||
const largeArc = originDiffAngle > 180 ? 1 : 0;
|
|
||||||
const diffAngle = clockWise ? -originDiffAngle : originDiffAngle;
|
|
||||||
const endAngle = curAngle = curAngle + diffAngle;
|
|
||||||
const startPosition = getPositionByAngle(startAngle, radius);
|
|
||||||
const endPosition = getPositionByAngle(endAngle, radius);
|
|
||||||
|
|
||||||
const prevProperty = this.init && prevSlicesProperties[i];
|
|
||||||
|
|
||||||
let curStart, curEnd;
|
|
||||||
if (this.init) {
|
|
||||||
curStart = prevProperty ? prevProperty.startPosition : startPosition;
|
|
||||||
curEnd = prevProperty ? prevProperty.endPosition : startPosition;
|
|
||||||
} else {
|
|
||||||
curStart = startPosition;
|
|
||||||
curEnd = endPosition;
|
|
||||||
}
|
|
||||||
const curPath =
|
|
||||||
originDiffAngle === 360
|
|
||||||
? makeStrokeCircleStr(curStart, curEnd, this.center, this.radius, this.clockWise, largeArc)
|
|
||||||
: makeArcStrokePathStr(curStart, curEnd, this.center, this.radius, this.clockWise, largeArc);
|
|
||||||
|
|
||||||
s.sliceStrings.push(curPath);
|
|
||||||
s.slicesProperties.push({
|
|
||||||
startPosition,
|
|
||||||
endPosition,
|
|
||||||
value: total,
|
|
||||||
total: s.grandTotal,
|
|
||||||
startAngle,
|
|
||||||
endAngle,
|
|
||||||
angle: diffAngle
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
this.init = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setupComponents() {
|
setupComponents() {
|
||||||
@ -88,7 +30,7 @@ export default class DonutChart extends AggregationChart {
|
|||||||
|
|
||||||
let componentConfigs = [
|
let componentConfigs = [
|
||||||
[
|
[
|
||||||
'donutSlices',
|
this.sliceName,
|
||||||
{},
|
{},
|
||||||
function () {
|
function () {
|
||||||
return {
|
return {
|
||||||
@ -99,6 +41,8 @@ export default class DonutChart extends AggregationChart {
|
|||||||
}.bind(this)
|
}.bind(this)
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
console.log(this.sliceName);
|
||||||
|
|
||||||
this.components = new Map(componentConfigs
|
this.components = new Map(componentConfigs
|
||||||
.map(args => {
|
.map(args => {
|
||||||
@ -106,56 +50,4 @@ export default class DonutChart extends AggregationChart {
|
|||||||
return [args[0], component];
|
return [args[0], component];
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
calTranslateByAngle(property) {
|
|
||||||
const { radius, hoverRadio } = this;
|
|
||||||
const position = getPositionByAngle(property.startAngle + (property.angle / 2), radius);
|
|
||||||
return `translate3d(${(position.x) * hoverRadio}px,${(position.y) * hoverRadio}px,0)`;
|
|
||||||
}
|
|
||||||
|
|
||||||
hoverSlice(path, i, flag, e) {
|
|
||||||
if (!path) return;
|
|
||||||
const color = this.colors[i];
|
|
||||||
if (flag) {
|
|
||||||
transform(path, this.calTranslateByAngle(this.state.slicesProperties[i]));
|
|
||||||
path.style.stroke = lightenDarkenColor(color, 50);
|
|
||||||
let g_off = getOffset(this.svg);
|
|
||||||
let x = e.pageX - g_off.left + 10;
|
|
||||||
let y = e.pageY - g_off.top - 10;
|
|
||||||
let title = (this.formatted_labels && this.formatted_labels.length > 0
|
|
||||||
? this.formatted_labels[i] : this.state.labels[i]) + ': ';
|
|
||||||
let percent = (this.state.sliceTotals[i] * 100 / this.state.grandTotal).toFixed(1);
|
|
||||||
this.tip.setValues(x, y, { name: title, value: percent + "%" });
|
|
||||||
this.tip.showTip();
|
|
||||||
} else {
|
|
||||||
transform(path, 'translate3d(0,0,0)');
|
|
||||||
this.tip.hideTip();
|
|
||||||
path.style.stroke = color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bindTooltip() {
|
|
||||||
this.container.addEventListener('mousemove', this.mouseMove);
|
|
||||||
this.container.addEventListener('mouseleave', this.mouseLeave);
|
|
||||||
}
|
|
||||||
|
|
||||||
mouseMove(e) {
|
|
||||||
const target = e.target;
|
|
||||||
let slices = this.components.get('donutSlices').store;
|
|
||||||
let prevIndex = this.curActiveSliceIndex;
|
|
||||||
let prevAcitve = this.curActiveSlice;
|
|
||||||
if (slices.includes(target)) {
|
|
||||||
let i = slices.indexOf(target);
|
|
||||||
this.hoverSlice(prevAcitve, prevIndex, false);
|
|
||||||
this.curActiveSlice = target;
|
|
||||||
this.curActiveSliceIndex = i;
|
|
||||||
this.hoverSlice(target, i, true, e);
|
|
||||||
} else {
|
|
||||||
this.mouseLeave();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mouseLeave() {
|
|
||||||
this.hoverSlice(this.curActiveSlice, this.curActiveSliceIndex, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,6 @@ import { FULL_ANGLE } from '../utils/constants';
|
|||||||
export default class PieChart extends AggregationChart {
|
export default class PieChart extends AggregationChart {
|
||||||
constructor(parent, args) {
|
constructor(parent, args) {
|
||||||
super(parent, args);
|
super(parent, args);
|
||||||
this.type = 'pie';
|
|
||||||
this.initTimeout = 0;
|
this.initTimeout = 0;
|
||||||
this.init = 1;
|
this.init = 1;
|
||||||
|
|
||||||
@ -25,13 +24,23 @@ export default class PieChart extends AggregationChart {
|
|||||||
this.hoverRadio = args.hoverRadio || 0.1;
|
this.hoverRadio = args.hoverRadio || 0.1;
|
||||||
this.config.startAngle = args.startAngle || 0;
|
this.config.startAngle = args.startAngle || 0;
|
||||||
|
|
||||||
|
this.type = 'pie';
|
||||||
|
this.sliceName = 'pieSlices';
|
||||||
|
|
||||||
|
this.arcFunc = makeArcPathStr;
|
||||||
|
this.shapeFunc = makeCircleStr;
|
||||||
|
|
||||||
this.clockWise = args.clockWise || false;
|
this.clockWise = args.clockWise || false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getRadius() {
|
||||||
|
return this.height > this.width ? this.center.x : this.center.y;
|
||||||
|
}
|
||||||
|
|
||||||
calc() {
|
calc() {
|
||||||
super.calc();
|
super.calc();
|
||||||
let s = this.state;
|
let s = this.state;
|
||||||
this.radius = (this.height > this.width ? this.center.x : this.center.y);
|
this.radius = this.getRadius();
|
||||||
|
|
||||||
const { radius, clockWise } = this;
|
const { radius, clockWise } = this;
|
||||||
|
|
||||||
@ -60,8 +69,8 @@ export default class PieChart extends AggregationChart {
|
|||||||
}
|
}
|
||||||
const curPath =
|
const curPath =
|
||||||
originDiffAngle === 360
|
originDiffAngle === 360
|
||||||
? makeCircleStr(curStart, curEnd, this.center, this.radius, clockWise, largeArc)
|
? this.shapeFunc(curStart, curEnd, this.center, this.radius, clockWise, largeArc)
|
||||||
: makeArcPathStr(curStart, curEnd, this.center, this.radius, clockWise, largeArc);
|
: this.arcFunc(curStart, curEnd, this.center, this.radius, clockWise, largeArc);
|
||||||
|
|
||||||
s.sliceStrings.push(curPath);
|
s.sliceStrings.push(curPath);
|
||||||
s.slicesProperties.push({
|
s.slicesProperties.push({
|
||||||
@ -112,7 +121,8 @@ export default class PieChart extends AggregationChart {
|
|||||||
const color = this.colors[i];
|
const color = this.colors[i];
|
||||||
if (flag) {
|
if (flag) {
|
||||||
transform(path, this.calTranslateByAngle(this.state.slicesProperties[i]));
|
transform(path, this.calTranslateByAngle(this.state.slicesProperties[i]));
|
||||||
path.style.fill = lightenDarkenColor(color, 50);
|
// path.style.fill = lightenDarkenColor(color, 50);
|
||||||
|
// path.style.stroke = lightenDarkenColor(color, 50);
|
||||||
let g_off = getOffset(this.svg);
|
let g_off = getOffset(this.svg);
|
||||||
let x = e.pageX - g_off.left + 10;
|
let x = e.pageX - g_off.left + 10;
|
||||||
let y = e.pageY - g_off.top - 10;
|
let y = e.pageY - g_off.top - 10;
|
||||||
@ -135,12 +145,12 @@ export default class PieChart extends AggregationChart {
|
|||||||
|
|
||||||
mouseMove(e) {
|
mouseMove(e) {
|
||||||
const target = e.target;
|
const target = e.target;
|
||||||
let slices = this.components.get('pieSlices').store;
|
let slices = this.components.get(this.sliceName).store;
|
||||||
let prevIndex = this.curActiveSliceIndex;
|
let prevIndex = this.curActiveSliceIndex;
|
||||||
let prevAcitve = this.curActiveSlice;
|
let prevActive = this.curActiveSlice;
|
||||||
if (slices.includes(target)) {
|
if (slices.includes(target)) {
|
||||||
let i = slices.indexOf(target);
|
let i = slices.indexOf(target);
|
||||||
this.hoverSlice(prevAcitve, prevIndex, false);
|
this.hoverSlice(prevActive, prevIndex, false);
|
||||||
this.curActiveSlice = target;
|
this.curActiveSlice = target;
|
||||||
this.curActiveSliceIndex = i;
|
this.curActiveSliceIndex = i;
|
||||||
this.hoverSlice(target, i, true, e);
|
this.hoverSlice(target, i, true, e);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user