简体   繁体   中英

React-Native: How to mark part of a picture, using coordinates and Image zoom?

I just started learning React-Native, I have such a problem in my current project. I am receiving Car part image from API, this image is png format, each part number is numbered in the picture, I also getting coordinates (coordinates(x,y), width, height) of each number. My aim is to give border and border color each number inside part picture The problem is that these coordinates are calculated on a full-sized image, and do not match the image on mobile devices. Also the problem arises when enlarging the image, the existing coordinates are almost useless. I will accept any offer which will give me the right point, Thanks

I want to achieve same result, but I have no idea how they are solving this problem into an existing project: link here

Reproduction Link: link here

 import React from "react"; import { Animated, Dimensions, View, Image, Text} from "react-native"; import ImageZoom from 'react-native-image-pan-zoom'; import {useState} from "react"; const PinchableBox = () => { const [scale, setScale] = useState('') /* Part number, coordinates(x,y, width,height) */ let partPosition = {number:1,coordinates:[327,18,12,22]} let calculated = partPosition.coordinates[0] / scale console.log(calculated) return ( <View> <View style={{position:'relative'}}> <ImageZoom cropWidth={350} cropHeight={290} panToMove={true} minScale={1} maxScale={4} imageHeight={300} onMove={(e)=>setScale(e.scale)} imageWidth={300} style={{marginTop:0}} > <Image style={{ width: '100%', height: 300}} source={{ uri: `https://img.parts-catalogs.com/bmw_2020_01/data/JPG/209412.png` }} resizeMode="contain" /> </ImageZoom> <Text style={{ color:'red', borderWidth:2, height:partPosition.coordinates[3], width:partPosition.coordinates[2], position:'absolute', transform:[{translateX:327 * (scale / 2 )},{translateY:18 * scale}] }} >{partPosition.number} </Text> </View> </View> ); }; export default PinchableBox;

import React from 'react';
import { Animated, Dimensions, View, Image, Text } from 'react-native';
import ImageZoom from 'react-native-image-pan-zoom';
import { useState } from 'react';

const PinchableBox = () => {
  const [scale, setScale] = useState('');
  const transformScale = { width: 300/800, height: 300/500 };
  // 800 is the actual image width and 300 is width shown in screen. Same for height.
  /* Part number, coordinates(x,y, width,height) */
  const [textPosition, setTextPosition] = useState({
    x: 315*transformScale.width,
    y: 80*transformScale.height,
  });
  const [showText, setShowText] = useState(false);
  let partPosition = {
    number: 1,
    coordinates: [315, 80, 20, 20],
  };

  const checkIfClickLiesInAnyPart = ({ x, y }) => {
    const tX = x/transformScale.width;
    const tY =y/transformScale.height;
    let c=partPosition.coordinates;
    if(tX<=c[0]+2*c[2] && tX>=c[0]-2*c[2] && tY<=c[1]+c[3] && tY>=c[1]-c[3]) return {matchedWith:1};
    return {matchedWith:false};
  };
  const handleClick = (e) => {
    console.log('clicked', e);
    const {matchedWith}=checkIfClickLiesInAnyPart({ x: e.locationX, y: e.locationY })
    if (matchedWith) {
      setShowText(true);
      setTextPosition({ x: partPosition.coordinates[0]*transformScale.width, y: partPosition.coordinates[1]*transformScale.height });
    } else {
      setShowText(false);
    }
  };
  return (
    <View>
      <View style={{ position: 'relative' }}>
        <ImageZoom
          cropWidth={300}
          cropHeight={300}
          panToMove={true}
          minScale={1}
          maxScale={4}
          imageHeight={300}
          onMove={(e) => setScale(e.scale)}
          imageWidth={300}
          style={{ marginTop: 0 }}
          onClick={handleClick}>
          <Image
            style={{ width: '300px', height: '300px' }}
            source={{
              uri: `https://img.parts-catalogs.com/bmw_2020_01/data/JPG/209412.png`,
            }}
            resizeMode="contain"
          />
          // put textbox inside ImageZoom so that it also zooms / moves with image
          {showText && (
            <Text
              style={{
                color: 'red',
                borderWidth: 2,
                height: '20px',
                width: '20px',
                position: 'absolute',
                left: textPosition.x + 'px',
                top: textPosition.y + 'px',
              }}>
              1
            </Text>
          )}
        </ImageZoom>
      </View>
    </View>
  );
};

export default PinchableBox;

Demo: https://snack.expo.dev/HcBcDZjwWP

[if you click near part1, the box will be highlighted else it'll be hidden...you can modify acceptable click area too]

I have left some comments too. The sample code is for 1 part only..for multiple parts modify checkIfClickLiesInAnyPart to check for all plus some other modifications.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM