需求:基于React实现获取图片原始尺寸对应的坐标点
实现基于图片原始尺寸的坐标点获取
核心思路
要获取不依赖CSS显示尺寸的原始坐标,关键是计算显示尺寸与原始尺寸的缩放比例,再将点击的显示坐标转换为原始坐标:
- 利用图片原生属性
naturalWidth/naturalHeight获取原始尺寸 - 通过
getBoundingClientRect()获取图片当前的显示尺寸 - 计算缩放比例:
scaleX = 原始宽度 / 显示宽度,scaleY = 原始高度 / 显示高度 - 最终原始坐标 = 点击的显示坐标 × 对应缩放比例
修改后的完整代码
import React, { useState } from 'react'; import src from "../assets/testCoordinate.jpeg"; import ReactPlayer from 'react-player' import Select from "react-select" const ImageDetection = () => { const [isSelecting, setIsSelecting] = useState(false); // 显示坐标:用于页面上标记点的定位 const [startX, setStartX] = useState(null); const [startY, setStartY] = useState(null); const [endX, setEndX] = useState(null); const [endY, setEndY] = useState(null); // 原始尺寸坐标:最终需要的目标结果 const [startOriginalX, setStartOriginalX] = useState(null); const [startOriginalY, setStartOriginalY] = useState(null); const [endOriginalX, setEndOriginalX] = useState(null); const [endOriginalY, setEndOriginalY] = useState(null); const [imageWidth, setImageWidth] = useState(null); const [imageHeight, setImageHeight] = useState(null); const handleClick = (event) => { const { offsetX, offsetY } = event.nativeEvent; const { width: displayWidth, height: displayHeight } = event.currentTarget.getBoundingClientRect(); const { naturalWidth: originalWidth, naturalHeight: originalHeight } = event.currentTarget; // 计算显示尺寸到原始尺寸的缩放比例 const scaleX = originalWidth / displayWidth; const scaleY = originalHeight / displayHeight; // 转换为原始尺寸下的坐标 const originalX = offsetX * scaleX; const originalY = offsetY * scaleY; if (isSelecting) { setEndX(offsetX); setEndY(offsetY); setEndOriginalX(Math.round(originalX)); setEndOriginalY(Math.round(originalY)); setIsSelecting(false); console.log(`原始终点坐标: (${originalX.toFixed(2)}, ${originalY.toFixed(2)})`); } else { setStartX(offsetX); setStartY(offsetY); setStartOriginalX(Math.round(originalX)); setStartOriginalY(Math.round(originalY)); setIsSelecting(true); console.log(`原始起点坐标: (${originalX.toFixed(2)}, ${originalY.toFixed(2)})`); } }; const startMarkerStyle = { position: 'absolute', left: `${startX}px`, top: `${startY}px`, width: '10px', height: '10px', backgroundColor: 'green', borderRadius: '50%', zIndex: 2, }; const endMarkerStyle = { position: 'absolute', left: `${endX}px`, top: `${endY}px`, width: '10px', height: '10px', backgroundColor: 'red', borderRadius: '50%', zIndex: 2, }; const lineStyle = { position: 'absolute', zIndex: 1, left: 0, top: 0, width: '100%', height: '100%', }; const handleImageLoad = (event) => { const { naturalWidth, naturalHeight } = event.target; setImageWidth(naturalWidth); setImageHeight(naturalHeight); }; return ( <div style={{ position: 'relative', }} > <img src={src} alt="Test Image" onClick={handleClick} className='w-[740px] h-[540px]' onLoad={handleImageLoad} style={{ display: 'block' }} // 消除行内元素默认留白,避免坐标计算偏差 /> {startX !== null && ( <div style={startMarkerStyle}></div> )} {endX !== null && ( <div style={endMarkerStyle}></div> )} {startX !== null && endX !== null && ( <svg style={lineStyle}> <line x1={startX} y1={startY} x2={endX} y2={endY} stroke="blue" strokeWidth="2" /> </svg> )} {imageWidth && imageHeight && ( <p>图片原始尺寸: {imageWidth} x {imageHeight}</p> )} {startOriginalX !== null && ( <p>原始起点坐标: ({startOriginalX}, {startOriginalY})</p> )} {endOriginalX !== null && ( <p>原始终点坐标: ({endOriginalX}, {endOriginalY})</p> )} </div> ); }; export default ImageDetection;
关键修改说明
- 新增原始坐标状态变量,专门存储转换后的目标结果
- 在点击事件中完成显示坐标到原始坐标的比例转换
- 给标记点添加
zIndex,确保标记点在SVG线条上方显示 - 给图片设置
display: block,避免默认行内元素留白影响坐标计算 - 用
Math.round()和toFixed(2)优化坐标的显示精度
内容的提问来源于stack exchange,提问作者SARON RAVUTH
相关产品推荐
相关产品推荐

