UNPKG

zmp-react

Version:

Build full featured iOS & Android apps using ZMP & React

189 lines (168 loc) 6.04 kB
import _extends from "@babel/runtime/helpers/extends"; import React, { forwardRef, useRef, useImperativeHandle, useState, useEffect } from 'react'; import { classNames, getExtraAttrs, emit } from '../shared/utils'; import { zmp } from '../shared/zmp'; var PieChart = /*#__PURE__*/forwardRef(function (props, ref) { var className = props.className, id = props.id, style = props.style, _props$size = props.size, size = _props$size === void 0 ? 320 : _props$size, _props$tooltip = props.tooltip, tooltip = _props$tooltip === void 0 ? false : _props$tooltip, _props$datasets = props.datasets, datasets = _props$datasets === void 0 ? [] : _props$datasets, formatTooltip = props.formatTooltip, children = props.children; var extraAttrs = getExtraAttrs(props); var _useState = useState(null), currentIndex = _useState[0], setCurrentIndex = _useState[1]; var previousIndex = useRef(null); var elRef = useRef(null); var zmpTooltip = useRef(null); useImperativeHandle(ref, function () { return { el: elRef.current }; }); var getSummValue = function getSummValue() { var summ = 0; datasets.map(function (d) { return d.value || 0; }).forEach(function (value) { summ += value; }); return summ; }; var getPaths = function getPaths() { var paths = []; var cumulativePercentage = 0; function getCoordinatesForPercentage(percentage) { var x = Math.cos(2 * Math.PI * percentage) * (size / 3); var y = Math.sin(2 * Math.PI * percentage) * (size / 3); return [x, y]; } datasets.forEach(function (_ref) { var value = _ref.value, label = _ref.label, color = _ref.color; var percentage = value / getSummValue(); var _getCoordinatesForPer = getCoordinatesForPercentage(cumulativePercentage), startX = _getCoordinatesForPer[0], startY = _getCoordinatesForPer[1]; cumulativePercentage += percentage; var _getCoordinatesForPer2 = getCoordinatesForPercentage(cumulativePercentage), endX = _getCoordinatesForPer2[0], endY = _getCoordinatesForPer2[1]; var largeArcFlag = percentage > 0.5 ? 1 : 0; var points = ["M " + startX + " " + startY, // Move "A " + size / 3 + " " + size / 3 + " 0 " + largeArcFlag + " 1 " + endX + " " + endY, // Arc 'L 0 0' // Line ].join(' '); paths.push({ points: points, label: label, color: color }); }); return paths; }; var formatTooltipText = function formatTooltipText() { if (currentIndex === null) return ''; var _datasets$currentInde = datasets[currentIndex], value = _datasets$currentInde.value, label = _datasets$currentInde.label, color = _datasets$currentInde.color; var percentage = value / getSummValue() * 100; var round = function round(v) { if (parseInt(v, 10) === v) return v; return Math.round(v * 100) / 100; }; if (formatTooltip) { return formatTooltip({ index: currentIndex, value: value, label: label, color: color, percentage: percentage }); } var tooltipText = "" + (label ? label + ": " : '') + round(value) + " (" + round(percentage) + "%)"; return "\n <div class=\"pie-chart-tooltip-label\">\n <span class=\"pie-chart-tooltip-color\" style=\"background-color: " + color + ";\"></span> " + tooltipText + "\n </div>\n "; }; var setTooltip = function setTooltip() { if (currentIndex === null && !zmpTooltip.current) return; if (!tooltip || !elRef.current || !zmp) return; if (currentIndex !== null && !zmpTooltip.current) { zmpTooltip.current = zmp.tooltip.create({ trigger: 'manual', containerEl: elRef.current, targetEl: elRef.current.querySelector("path[data-index=\"" + currentIndex + "\"]"), text: formatTooltipText(), cssClass: 'pie-chart-tooltip' }); zmpTooltip.current.show(); return; } if (!zmpTooltip.current) return; if (currentIndex !== null) { zmpTooltip.current.setText(formatTooltipText()); zmpTooltip.current.setTargetEl(elRef.current.querySelector("path[data-index=\"" + currentIndex + "\"]")); zmpTooltip.current.show(); } else { zmpTooltip.current.hide(); } }; useEffect(function () { if (previousIndex.current === currentIndex) return; previousIndex.current = currentIndex; emit(props, 'select', currentIndex, datasets[currentIndex]); setTooltip(); }, [currentIndex]); useEffect(function () { return function () { if (zmpTooltip.current && zmpTooltip.current.destroy) { zmpTooltip.current.destroy(); } zmpTooltip.current = null; }; }, []); var classes = classNames('pie-chart', className); var paths = getPaths(); return /*#__PURE__*/React.createElement("div", _extends({ id: id, style: style, className: classes, ref: elRef }, extraAttrs), /*#__PURE__*/React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: size, height: size, viewBox: "-" + size / 3 + " -" + size / 3 + " " + size * 2 / 3 + " " + size * 2 / 3, style: { transform: 'rotate(-90deg)' } }, paths.map(function (path, index) { return /*#__PURE__*/React.createElement("path", { key: path.label || index, d: path.points, fill: path.color, "data-index": index, className: classNames({ 'pie-chart-hidden': currentIndex !== null && currentIndex !== index }), onClick: function onClick() { return setCurrentIndex(index); }, onMouseEnter: function onMouseEnter() { return setCurrentIndex(index); }, onMouseLeave: function onMouseLeave() { return setCurrentIndex(null); } }); })), children); }); PieChart.displayName = 'zmp-pie-chart'; export default PieChart;