Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
393 views
in Technique[技术] by (71.8m points)

javascript - 放大后如何查看图像。(Expo / ReactNative)(How can I pan across an image once zoomed in. (Expo/ReactNative))

In my Expo app, on a particular screen you can take an image or select from camera roll using expo APIs and then preview.

(在我的Expo应用程序中,您可以在特定屏幕上拍摄图像,或使用expo API从相机胶卷中进行选择,然后进行预览。)

In the preview, I have an overlay where the user can touch a point on the image a dot/marker is displayed over the corresponding X, Y-axis.

(在预览中,我有一个叠加层,用户可以在其中触摸图像上的点,在相应的X,Y轴上显示点/标记。)

I want to be able to zoom into the image and place the marker with more accuracy.

(我希望能够放大图像并更精确地放置标记。)

So far I have tried:

(到目前为止,我已经尝试过:)

  1. Scrollview - this kinda works, but after saving the image and viewing it again the marker is no longer in the correct position.

    (滚动视图-可以,但是保存图像并再次查看后,标记不再位于正确的位置。)

  2. https://kmagiera.github.io/react-native-gesture-handler/docs/handler-pan.html : This zooms much better and maintains accuracy but once zoomed, I am unable to pan around the zoomed image.

    (https://kmagiera.github.io/react-native-gesture-handler/docs/handler-pan.html :这样可以更好地缩放并保持准确性,但是一旦缩放,我将无法平移缩放后的图像。)

3. https://github.com/ascoders/react-native-image-zoom : This appears very glitchy when you try to pan and also lose the marker position.

(3. https://github.com/ascoders/react-native-image-zoom :当您尝试平移并失去标记位置时,这似乎非常不正常。)

Ideally, I am looking at working with option 2 but making changes so I can pan the image.

(理想情况下,我正在考虑使用选项2,但要进行更改以便平移图像。)

Does anyone have a similar working example or suggestions on how I can move forward?

(有没有人有类似的工作示例或关于如何前进的建议?)

import React from "react";
import {
  Container,
  Text,
  Button,
  View,
  Icon,
  StyleProvider,
} from "native-base";
import {
  ImageBackground,
  Image,
  TouchableOpacity,
  TextInput,
  Animated,
  StyleSheet,
  Dimensions,
} from "react-native";

import {
  PinchGestureHandler,
  PanGestureHandler,
  ScrollView,
} from "react-native-gesture-handler";

import styles from "./ShotLoggerStyles";
import texts from "../../Style/texts";

import getTheme from "../../native-base-theme/components";
import marksmenOne from "../../native-base-theme/variables/marksmenOne";

import HeaderComponent from "../../Components/Header/Header";
import FooterComponent from "../../Components/Footer/FooterComponent";
import ChangeWeapon from "../../Components/ChangeWeapon";
import Loader from "../../Components/Loader/Loader";

const mainBG = require("../../assets/Backgrounds/metal.jpg");
const contentBG = require("../../assets/Backgrounds/training.jpg");

const windowWidth = Dimensions.get("window").width;

const ShotLoggerView = props => {
  const {
    leftPress,
    log,
    addShot,
    removeShot,
    updateShots,
    updateScore,
    changeWeaponHandler,
    _takeImageHandler,
    saveLog,
    weaponModalVisible,
    toggleWeaponModal,
    loading,
    displayHeight,
    pinchRef,
    rotationRef,
    _onPinchGestureEvent,
    _onPinchHandlerStateChange,
    _scale,
    panRef,
    _onTiltGestureEvent,
    _onTiltGestureStateChange,
    minDist,
    minPointers,
    maxPointers,
    avgTouches,
    _tiltStr,
  } = props;

  return (
    <Container>
      <StyleProvider style={getTheme(marksmenOne)}>
        <ImageBackground source={mainBG} style={styles.mainBG}>
          <Loader visible={loading} />
          <HeaderComponent
            headerTitle="Logging Shots"
            leftPress={leftPress}
            leftAction="close"
          />
          <View style={styles.content}>
            {!log.image ? (
              <>
                <ChangeWeapon
                  weaponModalVisible={weaponModalVisible}
                  onChangeWeapon={changeWeaponHandler}
                  toggleWeaponModal={toggleWeaponModal}
                />
                <ImageBackground style={styles.noImage} source={contentBG}>
                  <Text style={texts.headerTitle}>
                    Take a picture of your target
                  </Text>

                  <Button
                    icon
                    style={styles.buttonPrimary}
                    onPress={() => _takeImageHandler()}
                  >
                    <Icon style={styles.buttonIcon} name="camera" />
                  </Button>
                </ImageBackground>
              </>
            ) : (
              <>
                <View style={styles.details}>
                  <View style={styles.detailsItem}>
                    <Text style={texts.bodyWhite}>Shots</Text>
                    <TextInput
                      style={styles.input}
                      defaultValue={log.shots.toString()}
                      editable={false}
                    />
                  </View>
                  <View style={styles.detailsItem}>
                    <Text style={texts.bodyWhite}>Score</Text>
                    <TextInput
                      style={styles.input}
                      onChangeText={value => updateScore(value)}
                      clearTextOnFocus
                      keyboardType="number-pad"
                      returnKeyType="done"
                    />
                  </View>
                </View>
                <ScrollView>
                  <PanGestureHandler
                    ref={panRef}
                    onGestureEvent={_onTiltGestureEvent}
                    onHandlerStateChange={_onTiltGestureStateChange}
                    //   onGestureEvent={this._onDragGestureEvent}
                    // onHandlerStateChange={this._onDragHandlerStateChange}
                    minDist={1}
                    minPointers={2}
                    maxPointers={2}
                    avgTouches
                  >
                    <Animated.View
                      style={[
                        styles.style2,
                        {
                          transform: [
                            { perspective: 200 },
                            { scale: _scale },
                            { rotateX: _tiltStr },
                          ],
                        },
                      ]}
                      collapsable={false}
                    >
                      <PinchGestureHandler
                        ref={pinchRef}
                        simultaneousHandlers={rotationRef}
                        onGestureEvent={_onPinchGestureEvent}
                        onHandlerStateChange={_onPinchHandlerStateChange}
                      >
                        <Animated.View
                          style={[
                            styles.style2,
                            {
                              transform: [
                                { perspective: 200 },
                                { scale: _scale },
                                { rotateX: _tiltStr },
                              ],
                            },
                          ]}
                          collapsable={false}
                        >
                          <TouchableOpacity
                            activeOpacity={1}
                            style={styles.pointer}
                            onPress={evt => addShot(evt.nativeEvent)}
                          >
                            <View
                              style={[
                                styles.instructions,
                                log.heatmap.length > 0
                                  ? { zIndex: -5 }
                                  : { zIndex: 20 },
                              ]}
                            >
                              <Text style={texts.headerBody}>
                                Tap the picture to add &amp; remove shots.
                              </Text>
                            </View>

                            <Animated.Image
                              style={{
                                width: "100%",
                                minHeight: props.displayHeight,
                                height: "auto",
                              }}
                              source={{
                                uri: `data:image/jpg;base64,${log.image}`,
                              }}
                            />
                            {log.heatmap.length > 0 &&
                              log.heatmap.map((shot, index) => {
                                return (
                                  <TouchableOpacity
                                    key={index}
                                    onPress={() => removeShot(index)}
                                    style={[
                                      styles.shot,
                                      { left: shot.x - 10, top: shot.y - 10 },
                                    ]}
                                  />
                                );
                              })}
                          </TouchableOpacity>
                        </Animated.View>
                      </PinchGestureHandler>
                    </Animated.View>
                  </PanGestureHandler>
                </ScrollView>
              </>
            )}
          </View>
          <FooterComponent
            rightAction={saveLog}
            rightActionText="Save shots"
            rightActionDisable={!log.image}
          />
        </ImageBackground>
      </StyleProvider>
    </Container>
  );
};

export default ShotLoggerView;

const styles2 = StyleSheet.create({
  container: {
    ...StyleSheet.absoluteFillObject,
    backgroundColor: "black",
    overflow: "hidden",
    alignItems: "center",
    flex: 1,
    justifyContent: "center",
  },
  pinchableImage: {
    width: 250,
    height: 250,
  },
  wrapper: {
    flex: 1,
  },
});

and

(和)

/* eslint-disable no-underscore-dangle */
import React, { Component } from "react";
import { Alert, Dimensions, Animated, PanResponder } from "react-native";
import * as ImagePicker from "expo-image-picker";
import Constants from "expo-constants";

import { State } from "react-native-gesture-handler";

import * as Permissions from "expo-permissions";
import * as ImageManipulator from "expo-image-manipulator";
import * as Segment from "expo-analytics-segment";
import ShotLoggerView from "../ShotLoggerView";
import ENV from "../../../env";

import { USE_NATIVE_DRIVER } from "../../../config";

const windowWidth = Dimensions.get("window").width;
const circleRadius = 30;

Segment.initialize({
  androidWriteKey: ENV.SEGMENT_ANDROID_KEY

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...