UNPKG

vislite

Version:

灵活、快速、简单的数据可视化交互式跨端前端库

142 lines (110 loc) 4.39 kB
import type PieLayoutType from '../../types/PieLayout' import type { PieResultType } from '../../types/Pie' import type PieOptionType from '../../types/PieOption' import type { default as PieConfigType, nameType, valueType } from '../../types/PieConfig' import { initOption } from '../common/option' import rotate from '../rotate' import { animation } from "oipage/web/animation/index" class PieLayout implements PieLayoutType { readonly name: string = 'PieLayout' private __config: PieConfigType constructor(config: PieConfigType = {}) { this.__config = initOption(config, { name: (pieData: any, initPie: Array<any>) => pieData.name, value: (pieData: any, initPie: Array<any>) => pieData.value }) } private __option = { cx: 200, cy: 200, radius: [50, 100], duration: 200, } setOption(option: PieOptionType) { initOption(option, this.__option) return this } private __rback: (pie: PieResultType) => void private __oralPie: any private __prePie: PieResultType | null private __hoverIndex = -1 // 表示当前悬浮的序号 use(initPie: Array<any>, hoverIndex: number = -1) { let pie: PieResultType = { count: initPie.length, cx: this.__option.cx, cy: this.__option.cy, radius: this.__option.radius, hoverIndex, node: [] } let totalValue = 0, names = [], values = [] for (let i = 0; i < initPie.length; i++) { names[i] = (this.__config.name as nameType)(initPie[i], initPie) values[i] = (this.__config.value as valueType)(initPie[i], initPie) totalValue += values[i] } let beginDeg = Math.PI * -0.5, currenDeg for (let i = 0; i < initPie.length; i++) { currenDeg = values[i] / totalValue * Math.PI * 2 let radius = [this.__option.radius[0], this.__option.radius[1] * (1 + (hoverIndex === i ? 0.05 : 0))] let pdeg = beginDeg + currenDeg * 0.5, pradius = Math.max(this.__option.radius[0], this.__option.radius[1]) let p0 = rotate(pie.cx, pie.cy, pdeg, pie.cx + pradius, pie.cy) let p1 = rotate(pie.cx, pie.cy, pdeg, pie.cx + pradius + 15, pie.cy) let pflag = p0[0] > pie.cx ? 1 : -1 let p2 = [p1[0] + pflag * 20, p1[1]] let p3 = [p1[0] + pflag * 25, p1[1]] pie.node[i] = { value: values[i], name: names[i], beginDeg, deg: currenDeg, isHover: hoverIndex === i, radius, label: { line: [p0, p1, p2], position: p3, align: pflag === -1 ? "right" : "left" } } beginDeg += currenDeg } return pie } bind(initPie: Array<any>, renderBack: (pie: PieResultType) => void) { this.__rback = renderBack this.__oralPie = initPie this.__prePie = this.use(this.__oralPie, this.__hoverIndex) this.__rback(this.__prePie) return this } unbind() { this.__rback = () => null this.__oralPie = null this.__prePie = null this.__hoverIndex = -1 return this } setHover(index: number) { if (!this.__prePie || this.__hoverIndex === index) return this this.__hoverIndex = index this.doUpdate() return this } doUpdate() { const newPie = this.use(this.__oralPie, this.__hoverIndex) const cachePie = JSON.parse(JSON.stringify(newPie)) animation((deep) => { if (this.__prePie) { for (let i = 0; i < cachePie.count; i++) { cachePie.node[i].radius[1] = this.__prePie.node[i].radius[1] + (newPie.node[i].radius[1] - this.__prePie.node[i].radius[1]) * deep } } this.__rback(cachePie) }, this.__option.duration, () => { this.__prePie = newPie this.__rback(this.__prePie) }) return this } } export default PieLayout