UNPKG

reactts-gauge-chart

Version:
171 lines 8.25 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const jsx_runtime_1 = require("react/jsx-runtime"); const chart_js_1 = require("chart.js"); const react_1 = require("react"); function GaugeChart({ needleCurrentValue = 0, minValue = 0, maxValue = 100, veryLowLimit = 20, lowLimit = 40, highLimit = 80, veryHighLimit = 90, veryLowColor = "rgba(27, 98, 190, 0.77)", lowColor = "rgba(255, 227, 68, 0.77)", goodColor = "rgba(71, 185, 48, 0.77)", highColor = "rgba(255, 132, 31, 0.77)", veryHighColor = "rgba(190, 27, 27, 0.77)", borderVeryLowColor = "rgba(27, 98, 190, 0.77)", borderLowColor = "rgba(255, 227, 68, 0.77)", borderGoodColor = "rgba(71, 185, 48, 0.77)", borderHighColor = "rgba(255, 132, 31, 0.77)", borderVeryHighColor = "rgba(190, 27, 27, 0.77)", needleBorderColor = "rgb(136, 136, 136)", needleFillColor = "rgb(136, 136, 136)", needleWidth = 5, meterFont = "bold 30px sans-serif", meterColor = "rgb(34, 34, 34)", labelFont = "14px sans-serif", labelColor = "rgb(34, 34, 34)", aspectRatio = 1.5, paddingTop = 35, paddingBottom = 50, paddingLeft = 40, paddingRight = 40, arcBorderWidth = 0, arcBorderColor = "transparent", datasetBorderWidth = 0, cutout = "65%", canvasWidth }) { const needleValue = needleCurrentValue ?? minValue; // Cálculos para el gráfico const veryLowValue = veryLowLimit - minValue; const lowValue = lowLimit - veryLowLimit; const goodValue = highLimit - lowLimit; const highValue = veryHighLimit - highLimit; const veryHighValue = maxValue - veryHighLimit; // Gráfico const canvasRef = (0, react_1.useRef)(null); const chartInstanceRef = (0, react_1.useRef)(null); chart_js_1.Chart.register(...chart_js_1.registerables); // Plugins para el Gauge const gaugeNeedle = (0, react_1.useMemo)(() => ({ id: "gaugeNeedle", afterDatasetsDraw(chart) { const { ctx, data } = chart; ctx.save(); const meta = chart.getDatasetMeta(0); const xCenter = meta.data[0].x; const yCenter = meta.data[0].y; const innerRadius = meta.data[0].innerRadius; const outerRadius = meta.data[0].outerRadius; const radius = needleWidth; const needleVal = data.datasets[0].needleValue || 0; const widthSlice = (outerRadius - innerRadius) / 2; const circumference = (meta.data[0].circumference / Math.PI / data.datasets[0].data[0]) * needleVal; ctx.translate(xCenter, yCenter); ctx.rotate(Math.PI * (circumference + 1.5)); ctx.beginPath(); ctx.strokeStyle = needleBorderColor; ctx.fillStyle = needleFillColor; ctx.lineWidth = 1; ctx.moveTo(0 - radius, 0); ctx.lineTo(0, 0 - innerRadius - widthSlice); ctx.lineTo(0 + radius, 0); ctx.closePath(); ctx.stroke(); ctx.fill(); ctx.beginPath(); ctx.arc(0, 0, radius, 0, Math.PI * 2, false); ctx.fill(); ctx.restore(); }, }), []); const gaugeFlowMeter = (0, react_1.useMemo)(() => ({ id: "gaugeFlowMeter", afterDatasetsDraw(chart) { const { ctx, data } = chart; const xCenter = chart.getDatasetMeta(0).data[0].x; const yCenter = chart.getDatasetMeta(0).data[0].y; const needleValue = data.datasets[0].needleValue || 0; ctx.font = meterFont; ctx.fillStyle = meterColor; ctx.textAlign = "center"; ctx.fillText(needleValue, xCenter, yCenter + 45); }, }), []); const gaugeLabels = (0, react_1.useMemo)(() => { return { id: 'gaugeLabels', afterDatasetsDraw(chart) { const { ctx } = chart; const xCenter = chart.getDatasetMeta(0).data[0].x; const yCenter = chart.getDatasetMeta(0).data[0].y; const outerRadius = chart.getDatasetMeta(0).data[0].outerRadius; const innerRadius = chart.getDatasetMeta(0).data[0].innerRadius; const widthSlice = (outerRadius - innerRadius) / 2; const calculateAngle = (value) => { const range = maxValue - minValue; const normalizedValue = (value - minValue) / range; return normalizedValue * 180; }; const positions = [ { value: veryLowLimit }, { value: lowLimit }, { value: highLimit }, { value: veryHighLimit }, ].map(({ value }) => ({ value, angle: calculateAngle(value), })); ctx.save(); ctx.font = labelFont; ctx.fillStyle = labelColor; ctx.textAlign = 'center'; positions.forEach(({ value, angle }) => { const radians = (Math.PI / 180) * (angle + 180); const x = xCenter + Math.cos(radians) * (outerRadius + 20); const y = yCenter + Math.sin(radians) * (outerRadius + 20); ctx.fillText(value.toString(), x, y); }); ctx.font = 'bold 14px sans-serif'; ctx.fillText(minValue, xCenter - innerRadius - widthSlice, yCenter + 20); ctx.fillText(maxValue, xCenter + innerRadius + widthSlice, yCenter + 20); ctx.restore(); } }; }, [minValue, veryLowLimit, lowLimit, highLimit, veryHighLimit, maxValue]); const data = { labels: [], datasets: [ { label: "", data: [veryLowValue, lowValue, goodValue, highValue, veryHighValue], backgroundColor: [veryLowColor, lowColor, goodColor, highColor, veryHighColor], borderColor: [borderVeryLowColor, borderLowColor, borderGoodColor, borderHighColor, borderVeryHighColor], borderWidth: datasetBorderWidth, circumference: 180, rotation: 270, cutout: cutout, needleValue: needleValue, }, ], }; const config = { type: "doughnut", data, options: { responsive: true, maintainAspectRatio: false, aspectRatio: aspectRatio, layout: { padding: { bottom: paddingBottom, left: paddingLeft, right: paddingRight, top: paddingTop } }, plugins: { legend: { display: false }, tooltip: { enabled: false }, }, elements: { arc: { borderWidth: arcBorderWidth, borderColor: arcBorderColor, }, }, }, plugins: [gaugeNeedle, gaugeFlowMeter, gaugeLabels], }; (0, react_1.useEffect)(() => { if (canvasRef.current) { if (chartInstanceRef.current) { chartInstanceRef.current.destroy(); } chartInstanceRef.current = new chart_js_1.Chart(canvasRef.current, config); } return () => { if (chartInstanceRef.current) { chartInstanceRef.current.destroy(); } }; }, [minValue, veryLowValue, lowValue, goodValue, highValue, veryHighValue, maxValue]); (0, react_1.useEffect)(() => { if (chartInstanceRef.current) { chartInstanceRef.current.data.datasets[0].needleValue = needleValue; chartInstanceRef.current.update(); } }, [needleValue]); return (0, jsx_runtime_1.jsx)("canvas", { ref: canvasRef, style: { width: canvasWidth ? canvasWidth : "auto", height: "auto" } }); } exports.default = GaugeChart; //# sourceMappingURL=GaugeChart.js.map