如何镜像和调整具有固定宽度和高度的图像部分

时间:2022-11-10 15:39:37

如何镜像和调整具有固定宽度和高度的图像部分

I'm building "Tagging from photo" functionality.

我正在构建“从照片标记”功能。

  1. When the user move or pinch the square on the image,
  2. 当用户移动或捏住图像上的方块时,

  3. PanResponder changes the state of x-coordinate(left), y-coordinate(top), the length of square(thumbSize)
  4. PanResponder改变x坐标(左),y坐标(顶部),方形长度(thumbSize)的状态

  5. With the data, I want to show the part of square real-time
  6. 有了数据,我想显示方形的实时部分

So this image below should be placed into the left of A, All All from the image above.

因此,下面这张图片应放在A,All All左侧的上图中。

如何镜像和调整具有固定宽度和高度的图像部分

Here is the part of render showing the "cropped" image.

这是渲染部分显示“裁剪”图像。

console.log(left) // 80
console.log(top) // 200
console.log(thumbSize) // 150
<Image
      source={{uri: image}}
      style={{height:70, width: 70, bottom: (-top), right: (-left)
      }} <- style is not complete. I'm putting some example code
/>

This is continuous problem from: How to show the only part of the image.

这是一个持续存在的问题:如何显示图像的唯一部分。

It works but the solution doesn't meet my expectation.

它有效,但解决方案不符合我的期望。

  • It's not changing width and height ( I want to fix resize the image from 'the width of square' to '70' for each width and height)
  • 它没有改变宽度和高度(我想修复每个宽度和高度的图像从“正方形的宽度”调整到“70”)

  • It breaks the whole style (A, All, All things disappear)
  • 它打破了整个风格(A,All,All things disappear)

I've been trying to solve this idea for days but couldn't find the exact way.

我一直试图解决这个问题好几天但找不到确切的方法。


Update: I almost solved it but resizing matters

更新:我几乎解决了它,但重新调整问题

I changed Image to CroppedImage (new component)

我将Image更改为CroppedImage(新组件)

<CroppedImage
      source={{uri: image}}
      cropTop={top}
      cropLeft={left}
      cropWidth={thumbSize}
      cropHeight={thumbSize}
      width={width(100)}
      height={width(100)}
      resizeMode="contain" />

Here is CroppedImage

这是CroppedImage

return (
  <View style={[{
    overflow: 'hidden',
    height: this.props.cropHeight,
    width: this.props.cropWidth,
    backgroundColor: 'transparent'
    }, this.props.style]}>
    <Image style={{
      position: 'absolute',
      top: this.props.cropTop * -1,
      left: this.props.cropLeft * -1,
      width: this.props.width,
      height: this.props.height
    }}
      source={this.props.source}
      resizeMode={this.props.resizeMode}>
      {this.props.children}
    </Image>
  </View>
);

It seems working but it can't resize (from square width x height to 70x70).

它似乎工作但它不能调整大小(从方形宽度x高度到70x70)。

如何镜像和调整具有固定宽度和高度的图像部分

2 个解决方案

#1


3  

Well, I finally managed to create a working React Native code (never used it before, sorry if it is noobish code) doing the same as in my other answer.

好吧,我终于设法创建了一个有效的React Native代码(之前从未使用它,对不起,如果它是noobish代码),就像我的其他答案一样。

Here is the code:

这是代码:

import React, { Component } from 'react';
import { TouchableWithoutFeedback, ImageBackground, Image, View, StyleSheet } from 'react-native';

const IMAGEURI = 'http://fakeimg.pl/300x300/';
const SIZERATIO = .6;
const IMAGEWIDTH = 300;
const IMAGEHEIGHT = 300;
const CROPIMAGEWIDTH = 100;
const CROPIMAGEHEIGHT = 100;

export default class App extends Component {
  state = {
    style: {
      marginLeft: 0,
      marginTop: 0,
    },
    uri: ''
  };

  repositionImage(event) {
    this.setState({
      style: {
        marginLeft: CROPIMAGEWIDTH/2 - event.nativeEvent.locationX*SIZERATIO,
        marginTop: CROPIMAGEHEIGHT/2 - event.nativeEvent.locationY*SIZERATIO
      },
      uri: IMAGEURI
    });
  }

  render() {
    return (
      <View>
        <TouchableWithoutFeedback onPress={(event) => this.repositionImage(event)}>
          <View>
            <Image
              style={styles.image}
              source={{ uri: IMAGEURI }}
            />
          </View>
        </TouchableWithoutFeedback>
        <View style={styles.tag}>
          <ImageBackground style={[styles.cropped,this.state.style]} source={{uri: this.state.uri }} />
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  image: {
    width: IMAGEWIDTH,
    height: IMAGEHEIGHT,
  },

  tag: {
    borderWidth: 1,
    borderColor: '#000',
    width: CROPIMAGEWIDTH,
    height: CROPIMAGEHEIGHT,
    overflow: 'hidden'
  },

  cropped: {
    width: IMAGEWIDTH*SIZERATIO,
    height: IMAGEHEIGHT*SIZERATIO
  }
});

And here is the Snack

这是小吃

I really hope it helped!! Good luck!!

我真的希望它有所帮助!!祝你好运!!

EDIT: Ok I will explain a bit what I'm doing here.

First, I set a State with the parameters that will change based on some event:

首先,我设置一个State,其参数将根据某些事件而改变:

 state = {
    style: {
      marginLeft: 0,
      marginTop: 0,
    },
    uri: ''
  };

Then, I make the component to get its properties from that state:

然后,我使组件从该状态获取其属性:

< ImageBackground style={[styles.cropped,this.state.style]} source={{uri: this.state.uri }} />

Finally, I prepare the onPress event to call a function which will update the state:

最后,我准备onPress事件来调用一个更新状态的函数:

< TouchableWithoutFeedback onPress={(event) => this.repositionImage(event)}>

this.repositionImage(event)}>

Here I'm feeding my function with the event object so I will be available to get the coordinates where the user pressed.

在这里,我用事件对象提供我的函数,这样我就可以得到用户按下的坐标。

That last function takes the data from the event and updates the state. The view will automatically refresh with the new state data.

最后一个函数从事件中获取数据并更新状态。视图将自动刷新新的状态数据。

repositionImage(event) {
  this.setState({
    style: {
      marginLeft: CROPIMAGEWIDTH/2 - event.nativeEvent.locationX*SIZERATIO,
      marginTop: CROPIMAGEHEIGHT/2 - event.nativeEvent.locationY*SIZERATIO
    },
    uri: IMAGEURI
  });
}

To position the image, I simply do a math operation:

要定位图像,我只需进行数学运算:

CROPIMAGEWIDTH is the width of my tag element so to get the center I divide it by 2. Then, I substract the locationX of the event to move the image to the left so the locationX will be at the center of the tag.

CROPIMAGEWIDTH是我的标签元素的宽度,所以为了获得中心我将它除以2.然后,我减去事件的locationX以将图像向左移动,因此locationX将位于标签的中心。

That is only for positioning. To scale it just multiply the size of the image and the locationX by the same value. Note I multiplied the width and height of the image with the SIZERATIO in the cropped style

那只是为了定位。要缩放它,只需将图像和locationX的大小乘以相同的值即可。注意我将图像的宽度和高度乘以裁剪样式中的SIZERATIO

cropped: {
  width: IMAGEWIDTH*SIZERATIO,
  height: IMAGEHEIGHT*SIZERATIO
}

An example of this scaling stuff:

这个缩放的一个例子:

If your image has 200 width and you want to scale it to a half, you multiply it by 0.5. So if you click at the, say, pixel 180 starting for the left, the equivalent pixel for your scaled image will have to be multiplied by 0.5 too and it will be 90.

如果您的图像宽度为200,并且您希望将其缩放到一半,则将其乘以0.5。因此,如果您点击左边的像素180,则缩放图像的等效像素也必须乘以0.5,它将为90。

If there is something I didn't explaing clearly enough just ask me again a I will be glad to help you.

如果有什么我没有清楚地解释清楚,请再次问我,我很乐意帮助你。

#2


7  

I made a fiddle to show what calculations you have to do to correctly position and resize your tag image:

我做了一个小提琴来展示你需要做些什么计算来正确定位和调整标签图像的大小:

$('#image').click(function(event) {
  var size_ratio = .6;

  var img_src = $(this).attr('src');
  
  var tag = $('#tag-rectangle');
  
  var top_position = tag.height()/2 - event.offsetX*size_ratio;
  var left_position = tag.width()/2 - event.offsetY*size_ratio;
  $('#tag-rectangle').css({
  	'background-image': 'url('+img_src+')',
    'background-position': top_position +'px '+ left_position + 'px',
    'background-size': $(this).width()*size_ratio + 'px ' + $(this).height()*size_ratio + 'px'
    });
});
#tag-rectangle {
  width: 50px;
  height: 50px;
  border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<img id="image" src="http://fakeimg.pl/250x100/" alt="">

<div id="tag-rectangle"></div>

#1


3  

Well, I finally managed to create a working React Native code (never used it before, sorry if it is noobish code) doing the same as in my other answer.

好吧,我终于设法创建了一个有效的React Native代码(之前从未使用它,对不起,如果它是noobish代码),就像我的其他答案一样。

Here is the code:

这是代码:

import React, { Component } from 'react';
import { TouchableWithoutFeedback, ImageBackground, Image, View, StyleSheet } from 'react-native';

const IMAGEURI = 'http://fakeimg.pl/300x300/';
const SIZERATIO = .6;
const IMAGEWIDTH = 300;
const IMAGEHEIGHT = 300;
const CROPIMAGEWIDTH = 100;
const CROPIMAGEHEIGHT = 100;

export default class App extends Component {
  state = {
    style: {
      marginLeft: 0,
      marginTop: 0,
    },
    uri: ''
  };

  repositionImage(event) {
    this.setState({
      style: {
        marginLeft: CROPIMAGEWIDTH/2 - event.nativeEvent.locationX*SIZERATIO,
        marginTop: CROPIMAGEHEIGHT/2 - event.nativeEvent.locationY*SIZERATIO
      },
      uri: IMAGEURI
    });
  }

  render() {
    return (
      <View>
        <TouchableWithoutFeedback onPress={(event) => this.repositionImage(event)}>
          <View>
            <Image
              style={styles.image}
              source={{ uri: IMAGEURI }}
            />
          </View>
        </TouchableWithoutFeedback>
        <View style={styles.tag}>
          <ImageBackground style={[styles.cropped,this.state.style]} source={{uri: this.state.uri }} />
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  image: {
    width: IMAGEWIDTH,
    height: IMAGEHEIGHT,
  },

  tag: {
    borderWidth: 1,
    borderColor: '#000',
    width: CROPIMAGEWIDTH,
    height: CROPIMAGEHEIGHT,
    overflow: 'hidden'
  },

  cropped: {
    width: IMAGEWIDTH*SIZERATIO,
    height: IMAGEHEIGHT*SIZERATIO
  }
});

And here is the Snack

这是小吃

I really hope it helped!! Good luck!!

我真的希望它有所帮助!!祝你好运!!

EDIT: Ok I will explain a bit what I'm doing here.

First, I set a State with the parameters that will change based on some event:

首先,我设置一个State,其参数将根据某些事件而改变:

 state = {
    style: {
      marginLeft: 0,
      marginTop: 0,
    },
    uri: ''
  };

Then, I make the component to get its properties from that state:

然后,我使组件从该状态获取其属性:

< ImageBackground style={[styles.cropped,this.state.style]} source={{uri: this.state.uri }} />

Finally, I prepare the onPress event to call a function which will update the state:

最后,我准备onPress事件来调用一个更新状态的函数:

< TouchableWithoutFeedback onPress={(event) => this.repositionImage(event)}>

this.repositionImage(event)}>

Here I'm feeding my function with the event object so I will be available to get the coordinates where the user pressed.

在这里,我用事件对象提供我的函数,这样我就可以得到用户按下的坐标。

That last function takes the data from the event and updates the state. The view will automatically refresh with the new state data.

最后一个函数从事件中获取数据并更新状态。视图将自动刷新新的状态数据。

repositionImage(event) {
  this.setState({
    style: {
      marginLeft: CROPIMAGEWIDTH/2 - event.nativeEvent.locationX*SIZERATIO,
      marginTop: CROPIMAGEHEIGHT/2 - event.nativeEvent.locationY*SIZERATIO
    },
    uri: IMAGEURI
  });
}

To position the image, I simply do a math operation:

要定位图像,我只需进行数学运算:

CROPIMAGEWIDTH is the width of my tag element so to get the center I divide it by 2. Then, I substract the locationX of the event to move the image to the left so the locationX will be at the center of the tag.

CROPIMAGEWIDTH是我的标签元素的宽度,所以为了获得中心我将它除以2.然后,我减去事件的locationX以将图像向左移动,因此locationX将位于标签的中心。

That is only for positioning. To scale it just multiply the size of the image and the locationX by the same value. Note I multiplied the width and height of the image with the SIZERATIO in the cropped style

那只是为了定位。要缩放它,只需将图像和locationX的大小乘以相同的值即可。注意我将图像的宽度和高度乘以裁剪样式中的SIZERATIO

cropped: {
  width: IMAGEWIDTH*SIZERATIO,
  height: IMAGEHEIGHT*SIZERATIO
}

An example of this scaling stuff:

这个缩放的一个例子:

If your image has 200 width and you want to scale it to a half, you multiply it by 0.5. So if you click at the, say, pixel 180 starting for the left, the equivalent pixel for your scaled image will have to be multiplied by 0.5 too and it will be 90.

如果您的图像宽度为200,并且您希望将其缩放到一半,则将其乘以0.5。因此,如果您点击左边的像素180,则缩放图像的等效像素也必须乘以0.5,它将为90。

If there is something I didn't explaing clearly enough just ask me again a I will be glad to help you.

如果有什么我没有清楚地解释清楚,请再次问我,我很乐意帮助你。

#2


7  

I made a fiddle to show what calculations you have to do to correctly position and resize your tag image:

我做了一个小提琴来展示你需要做些什么计算来正确定位和调整标签图像的大小:

$('#image').click(function(event) {
  var size_ratio = .6;

  var img_src = $(this).attr('src');
  
  var tag = $('#tag-rectangle');
  
  var top_position = tag.height()/2 - event.offsetX*size_ratio;
  var left_position = tag.width()/2 - event.offsetY*size_ratio;
  $('#tag-rectangle').css({
  	'background-image': 'url('+img_src+')',
    'background-position': top_position +'px '+ left_position + 'px',
    'background-size': $(this).width()*size_ratio + 'px ' + $(this).height()*size_ratio + 'px'
    });
});
#tag-rectangle {
  width: 50px;
  height: 50px;
  border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<img id="image" src="http://fakeimg.pl/250x100/" alt="">

<div id="tag-rectangle"></div>