ReactJS中带X/Y轴人体图像的数据点绘制实现及资源求助
ReactJS实现带X/Y轴人体图像的数据指针绘制功能
一、数据预处理
先把原始二维数据集转换成便于绘制的格式,去除表头并将X轴字符串转为数值:
const rawData = [ ['Chakra Name', 'X-Position'], ['Chakra1', '4'], ['Chakra2', '2.6'], ['Chakra3', '4.4'], ['Chakra4', '3.2'], ['Chakra5', '1.8'], ['Chakra6', '5'], ['Chakra7', '1'], ['Chakra8', '2.5'], ]; // 转换为[{name: string, x: number}]格式 const chakraData = rawData.slice(1).map(item => ({ name: item[0], x: parseFloat(item[1]) }));
二、Canvas绘制核心实现
在React中使用useRef获取Canvas元素,结合useEffect完成绘制逻辑:
关键参数说明
- Canvas固定尺寸:390x390
- X轴映射:将数据中1-5的范围,对应到Canvas左侧50px到右侧30px的可用宽度区间
- Y轴固定点:垂直方向设置8个均匀分布的Y坐标,覆盖画布高度
完整组件代码
import { useEffect, useRef } from 'react'; export default function HumanChakraCanvas() { const canvasRef = useRef(null); // 预处理数据 const rawData = [ ['Chakra Name', 'X-Position'], ['Chakra1', '4'], ['Chakra2', '2.6'], ['Chakra3', '4.4'], ['Chakra4', '3.2'], ['Chakra5', '1.8'], ['Chakra6', '5'], ['Chakra7', '1'], ['Chakra8', '2.5'], ]; const chakraData = rawData.slice(1).map(item => ({ name: item[0], x: parseFloat(item[1]) })); useEffect(() => { const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext('2d'); const width = canvas.width; const height = canvas.height; // 清空画布 ctx.clearRect(0, 0, width, height); // 1. 绘制坐标轴 // X轴 ctx.beginPath(); ctx.moveTo(50, height - 30); ctx.lineTo(width - 30, height - 30); ctx.strokeStyle = '#333'; ctx.lineWidth = 2; ctx.stroke(); // X轴刻度与标签 const xTicks = [1,2,3,4,5]; xTicks.forEach(tick => { const xPos = 50 + ((tick - 1) / 4) * (width - 80); ctx.beginPath(); ctx.moveTo(xPos, height - 30); ctx.lineTo(xPos, height - 25); ctx.stroke(); ctx.fillStyle = '#333'; ctx.font = '12px Arial'; ctx.textAlign = 'center'; ctx.fillText(tick.toString(), xPos, height - 10); }); // Y轴 ctx.beginPath(); ctx.moveTo(50, 30); ctx.lineTo(50, height - 30); ctx.stroke(); // 2. 绘制人体基底(可替换为自定义图像) ctx.beginPath(); ctx.moveTo(width/2, 30); ctx.lineTo(width/2, height - 30); ctx.strokeStyle = '#666'; ctx.setLineDash([5,3]); ctx.stroke(); ctx.setLineDash([]); // 3. 绘制8个可移动的圆圈 const yPositions = Array.from({length:8}, (_,i) => 40 + i*40); // 垂直8个点的Y坐标 const xMin = 1; const xMax = 5; const canvasXMin = 50; const canvasXMax = width - 30; chakraData.forEach((data, index) => { // 将数据X值映射到Canvas坐标 const xPos = canvasXMin + ((data.x - xMin)/(xMax - xMin)) * (canvasXMax - canvasXMin); const yPos = yPositions[index]; // 绘制圆圈 ctx.beginPath(); ctx.arc(xPos, yPos, 8, 0, Math.PI*2); ctx.fillStyle = '#ff4444'; ctx.fill(); ctx.strokeStyle = '#000'; ctx.stroke(); // 绘制脉轮名称 ctx.fillStyle = '#333'; ctx.font = '10px Arial'; ctx.textAlign = 'right'; ctx.fillText(data.name, xPos - 12, yPos + 3); }); }, []); return ( <canvas ref={canvasRef} id="human" width="390" height="390" style={{border: '1px solid #ccc'}} /> ); }
三、人体图像资源要求
需准备一张390x390像素的PNG/JPG图像,满足:
- 包含清晰的X轴(范围1-5)和Y轴
- 垂直方向有8个固定位置的圆圈,坐标与代码中
yPositions对应(Y=40、80、...、320) - 人体轮廓居中,8个圆圈对应人体垂直分布的脉轮位置
若使用自定义图像,可在useEffect中添加ctx.drawImage()方法,确保图像加载完成后再绘制。
内容的提问来源于stack exchange,提问作者Saahithi d
相关产品推荐
相关产品推荐

