|
|
@@ -1,5 +1,5 @@
|
|
|
import React, { useEffect, useRef, useMemo } from 'react';
|
|
|
-import Taro from '@tarojs/taro';
|
|
|
+import Taro, { useReady } from '@tarojs/taro';
|
|
|
import { Canvas } from '@tarojs/components';
|
|
|
import uChartsClass from '../lib/u-charts-original.js';
|
|
|
import type { ChartsConfig, TouchEvent } from '../lib/u-charts-original';
|
|
|
@@ -83,73 +83,134 @@ export const BaseChartOriginal2D: React.FC<BaseChartOriginal2DProps> = (props) =
|
|
|
/**
|
|
|
* 初始化图表实例
|
|
|
* 使用 Canvas 2D API + 原始 u-charts.js
|
|
|
+ * 只在数据准备好后才初始化(参考官方示例)
|
|
|
*/
|
|
|
- useEffect(() => {
|
|
|
- // 使用 setTimeout 确保 Canvas DOM 元素已渲染完成
|
|
|
- const timer = setTimeout(() => {
|
|
|
- // 使用 Canvas 2D API 的方式获取 context
|
|
|
- const query = Taro.createSelectorQuery();
|
|
|
- query.select('#' + canvasId).fields({ node: true, size: true }).exec((res) => {
|
|
|
- if (res[0]) {
|
|
|
- const canvas = res[0].node;
|
|
|
- const ctx = canvas.getContext('2d');
|
|
|
-
|
|
|
- // 设置 canvas 的实际像素尺寸
|
|
|
- canvas.width = res[0].width * actualPixelRatio;
|
|
|
- canvas.height = res[0].height * actualPixelRatio;
|
|
|
-
|
|
|
- // 将 Taro CanvasContext 转换为 uCharts 需要的 CanvasContext
|
|
|
- const extendedCtx = ctx as ExtendedCanvasContext;
|
|
|
-
|
|
|
- // Canvas 2D: 传入 uCharts 的 width/height 需要乘以 pixelRatio
|
|
|
- const chartConfig: ChartsConfig = {
|
|
|
- type,
|
|
|
- context: extendedCtx,
|
|
|
- categories,
|
|
|
- series,
|
|
|
- width: cWidth * actualPixelRatio,
|
|
|
- height: cHeight * actualPixelRatio,
|
|
|
- pixelRatio: actualPixelRatio,
|
|
|
- animation: true,
|
|
|
- background: '#FFFFFF',
|
|
|
- color: ['#3b82f6', '#10b981', '#f59e0b', '#8b5cf6', '#ef4444'],
|
|
|
- padding: [15, 15, 0, 5],
|
|
|
- enableScroll: false,
|
|
|
- legend: {},
|
|
|
- xAxis: {
|
|
|
- disableGrid: true
|
|
|
- },
|
|
|
- yAxis: {
|
|
|
- data: [{ min: 0 }]
|
|
|
- },
|
|
|
- extra: {
|
|
|
- column: {
|
|
|
- type: 'group',
|
|
|
- width: 30,
|
|
|
- activeBgColor: '#000000',
|
|
|
- activeBgOpacity: 0.08
|
|
|
- }
|
|
|
- },
|
|
|
- ...config,
|
|
|
- };
|
|
|
-
|
|
|
- chartRef.current = new uChartsClass(chartConfig);
|
|
|
- console.log('[BaseChartOriginal2D] 图表初始化完成:', canvasId, {
|
|
|
- cWidth, cHeight, actualPixelRatio,
|
|
|
- canvasWidth: canvas.width,
|
|
|
- canvasHeight: canvas.height
|
|
|
- });
|
|
|
- } else {
|
|
|
- console.error('[BaseChartOriginal2D] 未获取到 canvas node:', canvasId);
|
|
|
- }
|
|
|
+ useReady(() => {
|
|
|
+ // 确保数据已准备好:categories 和 series 都有数据
|
|
|
+ const isDataReady = categories.length > 0 && series.length > 0;
|
|
|
+
|
|
|
+ if (!isDataReady) {
|
|
|
+ console.log('[BaseChartOriginal2D] 数据未准备好,等待数据...', {
|
|
|
+ canvasId,
|
|
|
+ categoriesLength: categories.length,
|
|
|
+ seriesLength: series.length
|
|
|
});
|
|
|
- }, 100);
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- return () => {
|
|
|
- clearTimeout(timer);
|
|
|
- chartRef.current = null;
|
|
|
- };
|
|
|
- }, [canvasId, type, categories, series, cWidth, cHeight, actualPixelRatio, config]);
|
|
|
+ // 使用 Canvas 2D API 的方式获取 context
|
|
|
+ const query = Taro.createSelectorQuery();
|
|
|
+ query.select('#' + canvasId).fields({ node: true, size: true }).exec((res) => {
|
|
|
+ if (res[0]) {
|
|
|
+ const canvas = res[0].node;
|
|
|
+ const ctx = canvas.getContext('2d');
|
|
|
+
|
|
|
+ // 设置 canvas 的实际像素尺寸
|
|
|
+ canvas.width = res[0].width * actualPixelRatio;
|
|
|
+ canvas.height = res[0].height * actualPixelRatio;
|
|
|
+
|
|
|
+ // 将 Taro CanvasContext 转换为 uCharts 需要的 CanvasContext
|
|
|
+ const extendedCtx = ctx as ExtendedCanvasContext;
|
|
|
+
|
|
|
+ // Canvas 2D: 传入 uCharts 的 width/height 需要乘以 pixelRatio
|
|
|
+ const chartConfig: ChartsConfig = {
|
|
|
+ type,
|
|
|
+ context: extendedCtx,
|
|
|
+ categories,
|
|
|
+ series,
|
|
|
+ width: cWidth * actualPixelRatio,
|
|
|
+ height: cHeight * actualPixelRatio,
|
|
|
+ pixelRatio: actualPixelRatio,
|
|
|
+ animation: true,
|
|
|
+ background: '#FFFFFF',
|
|
|
+ color: ['#3b82f6', '#10b981', '#f59e0b', '#8b5cf6', '#ef4444'],
|
|
|
+ padding: [15, 15, 0, 5],
|
|
|
+ enableScroll: false,
|
|
|
+ legend: {},
|
|
|
+ xAxis: {
|
|
|
+ disableGrid: true
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ data: [{ min: 0 }]
|
|
|
+ },
|
|
|
+ extra: {
|
|
|
+ column: {
|
|
|
+ type: 'group',
|
|
|
+ width: 30,
|
|
|
+ activeBgColor: '#000000',
|
|
|
+ activeBgOpacity: 0.08
|
|
|
+ }
|
|
|
+ },
|
|
|
+ ...config,
|
|
|
+ };
|
|
|
+
|
|
|
+ chartRef.current = new uChartsClass(chartConfig);
|
|
|
+ console.log('[BaseChartOriginal2D] 图表初始化完成:', canvasId, {
|
|
|
+ cWidth, cHeight, actualPixelRatio,
|
|
|
+ canvasWidth: canvas.width,
|
|
|
+ canvasHeight: canvas.height,
|
|
|
+ categoriesLength: categories.length,
|
|
|
+ seriesLength: series.length
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ console.error('[BaseChartOriginal2D] 未获取到 canvas node:', canvasId);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ // 当数据变化时重新绘制
|
|
|
+ useEffect(() => {
|
|
|
+ if (!chartRef.current) return;
|
|
|
+
|
|
|
+ const isDataReady = categories.length > 0 && series.length > 0;
|
|
|
+ if (!isDataReady) return;
|
|
|
+
|
|
|
+ // 数据变化时重新绘制
|
|
|
+ const query = Taro.createSelectorQuery();
|
|
|
+ query.select('#' + canvasId).fields({ node: true, size: true }).exec((res) => {
|
|
|
+ if (res[0]) {
|
|
|
+ const canvas = res[0].node;
|
|
|
+ const ctx = canvas.getContext('2d');
|
|
|
+
|
|
|
+ // 清空画布
|
|
|
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
+
|
|
|
+ // 重新创建图表实例
|
|
|
+ const chartConfig: ChartsConfig = {
|
|
|
+ type,
|
|
|
+ context: ctx as ExtendedCanvasContext,
|
|
|
+ categories,
|
|
|
+ series,
|
|
|
+ width: cWidth * actualPixelRatio,
|
|
|
+ height: cHeight * actualPixelRatio,
|
|
|
+ pixelRatio: actualPixelRatio,
|
|
|
+ animation: true,
|
|
|
+ background: '#FFFFFF',
|
|
|
+ color: ['#3b82f6', '#10b981', '#f59e0b', '#8b5cf6', '#ef4444'],
|
|
|
+ padding: [15, 15, 0, 5],
|
|
|
+ enableScroll: false,
|
|
|
+ legend: {},
|
|
|
+ xAxis: {
|
|
|
+ disableGrid: true
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ data: [{ min: 0 }]
|
|
|
+ },
|
|
|
+ extra: {
|
|
|
+ column: {
|
|
|
+ type: 'group',
|
|
|
+ width: 30,
|
|
|
+ activeBgColor: '#000000',
|
|
|
+ activeBgOpacity: 0.08
|
|
|
+ }
|
|
|
+ },
|
|
|
+ ...config,
|
|
|
+ };
|
|
|
+
|
|
|
+ chartRef.current = new uChartsClass(chartConfig);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }, [categories, series, config]);
|
|
|
|
|
|
/**
|
|
|
* 触摸事件处理
|