在调整屏幕大小后返回完全相同的javascript图像坐标

vsmadaxz  于 2021-09-23  发布在  Java
关注(0)|答案(1)|浏览(413)

我想检索足球场png上的精确坐标。我能用计算机得到一些坐标 offsetLeftoffsetTop ,但不幸的是,一旦图像大小调整,或页面在不同分辨率或设备上打开,这些内容就开始发生变化。
这里是代码沙箱
无论屏幕分辨率或设备如何,我都需要坐标完全相同,因为我想向用户打印用户单击的球场上的确切码数。有没有办法用javascript实现这一点?我看了一下这个答案,但其中一些有点混乱,我无法得到我想要的。
这是我的代码:

import React, { useState } from "react";
import "./App.css";
import { Col, Container, Row } from "react-bootstrap";

import footballField from "./resources/images/AmFBfield.png";

function App() {
  const [x, setX] = useState(0);
  const [y, setY] = useState(0);
  const printCoordinates = (e) => {
    const x = e.pageX - e.currentTarget.offsetLeft;
    const y = e.pageY - e.currentTarget.offsetTop;

    setX(x);
    setY(y);
  };

  return (
    <Row>
      <Col sm={4}>
        {x}:{y}
      </Col>
      <Col sm={8}>
        <Container>
          <img
            id="football-field"
            src={footballField}
            alt="football-field"
            style={{ width: "80%", height: "80%" }}
            onClick={(e) => printCoordinates(e)}
          />
        </Container>
      </Col>
    </Row>
  );
}

export default App;
cotxawn7

cotxawn71#

如果您只想在图像边界内保持一致的单击位置,而不关心图像的内容,则只需转换 xy 基于显示图像的高度和宽度,相对于图像帧的单击偏移为百分比。
这里使用 MouseEvent.offsetX/Y 直接返回单击相对于图像元素的偏移(可以通过 nativeEvent react合成事件的属性),以及 element.getBoundingRect() 检索元素的高度和宽度。

const printCoordinates = (e) => {
  const { width, height } = e.target.getBoundingClientRect();
  const { offsetX, offsetY } = e.nativeEvent

  setX(Math.round((offsetX / width) * 100));
  setY(Math.round((offsetY / height) * 100));
};

但是,如果您想要相对于图像内容的坐标(即单击的实际码线),则有两个选项。
最简单的方法是从多个部分创建“俯仰”图像,将边界、端点区域和码数分离为单独的图像,并对每个组件使用上述方法。
或者,要处理您拥有的单个图像,您需要通过从单击的百分比偏移中减去边界和结束区域(作为总图像高度/宽度的百分比),然后将这些校正的单击偏移Map到图像中实际节距占总图像的百分比来计算边界和结束区域。
下面是一个粗略的示例,它来自图像的粗略百分比Map,其中边框+端点区域是图像宽度的10%,上边框是图像高度的5%。

const printCoordinates = (e) => {
  const { width, height } = e.target.getBoundingClientRect();
  const { offsetX, offsetY } = e.nativeEvent;

  // calculate percentage, subtract border/endzone percentage(10), map 80% to 100%, calculate yardage
  setX(Math.round(((((offsetX / width) * 100) - 10) / 80) * 100));
  // calculate percentage, subtract top-border percentage(5), map 90% to 100%, calculate yardage (53.3 yards total width)
  setY(Math.round(((((offsetY / height) * 100) - 5) / 90) * 53.3));
};

请参阅:codesandbox

相关问题