You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 09:15:37