refactor: work with percentage crops
This commit is contained in:
@@ -2,10 +2,12 @@ import 'react-image-crop/dist/ReactCrop.css'
|
|||||||
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {View} from 'react-native'
|
import {View} from 'react-native'
|
||||||
|
import {Path, Svg} from 'react-native-svg'
|
||||||
import {msg, Trans} from '@lingui/macro'
|
import {msg, Trans} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import ReactCrop, {PixelCrop} from 'react-image-crop'
|
import ReactCrop, {PercentCrop} from 'react-image-crop'
|
||||||
|
|
||||||
|
import {manipulateImage} from '#/state/gallery'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {Button, ButtonText} from '#/components/Button'
|
import {Button, ButtonText} from '#/components/Button'
|
||||||
import * as Dialog from '#/components/Dialog'
|
import * as Dialog from '#/components/Dialog'
|
||||||
@@ -30,15 +32,15 @@ const EditImageInner = ({control, image, onChange}: EditImageDialogProps) => {
|
|||||||
const {initialCrop, initialAspect, sourceAspect} = React.useMemo(() => {
|
const {initialCrop, initialAspect, sourceAspect} = React.useMemo(() => {
|
||||||
const initialArea = manips?.crop
|
const initialArea = manips?.crop
|
||||||
|
|
||||||
let crop: PixelCrop | undefined
|
let crop: PercentCrop | undefined
|
||||||
|
|
||||||
if (initialArea) {
|
if (initialArea) {
|
||||||
crop = {
|
crop = {
|
||||||
unit: 'px',
|
unit: '%',
|
||||||
x: initialArea.originX,
|
x: (initialArea.originX / source.width) * 100,
|
||||||
y: initialArea.originY,
|
y: (initialArea.originY / source.height) * 100,
|
||||||
width: initialArea.width,
|
width: (initialArea.width / source.width) * 100,
|
||||||
height: initialArea.height,
|
height: (initialArea.height / source.height) * 100,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +48,9 @@ const EditImageInner = ({control, image, onChange}: EditImageDialogProps) => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
initialCrop: crop,
|
initialCrop: crop,
|
||||||
initialAspect: crop ? crop.width / crop.height : originalAspect,
|
initialAspect: initialArea
|
||||||
|
? initialArea.width / initialArea.height
|
||||||
|
: originalAspect,
|
||||||
sourceAspect: originalAspect,
|
sourceAspect: originalAspect,
|
||||||
}
|
}
|
||||||
}, [source, manips])
|
}, [source, manips])
|
||||||
@@ -61,17 +65,17 @@ const EditImageInner = ({control, image, onChange}: EditImageDialogProps) => {
|
|||||||
const result = await manipulateImage(image, {
|
const result = await manipulateImage(image, {
|
||||||
crop: !isEmpty
|
crop: !isEmpty
|
||||||
? {
|
? {
|
||||||
originX: crop.x,
|
originX: (crop.x * source.width) / 100,
|
||||||
originY: crop.y,
|
originY: (crop.y * source.height) / 100,
|
||||||
width: crop.width,
|
width: (crop.width * source.width) / 100,
|
||||||
height: crop.height,
|
height: (crop.height * source.height) / 100,
|
||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
})
|
})
|
||||||
|
|
||||||
onChange(result)
|
onChange(result)
|
||||||
control.close()
|
control.close()
|
||||||
}, [crop, isEmpty, image, control, onChange])
|
}, [crop, isEmpty, image, source, control, onChange])
|
||||||
|
|
||||||
const changeAspect = (next: number) => {
|
const changeAspect = (next: number) => {
|
||||||
if (next !== aspect) {
|
if (next !== aspect) {
|
||||||
@@ -90,7 +94,7 @@ const EditImageInner = ({control, image, onChange}: EditImageDialogProps) => {
|
|||||||
<ReactCrop
|
<ReactCrop
|
||||||
aspect={aspect}
|
aspect={aspect}
|
||||||
crop={crop}
|
crop={crop}
|
||||||
onChange={setCrop}
|
onChange={(_, next) => setCrop(next)}
|
||||||
className="ReactCrop--no-animate">
|
className="ReactCrop--no-animate">
|
||||||
<img src={source.path} style={{maxHeight: `50vh`}} />
|
<img src={source.path} style={{maxHeight: `50vh`}} />
|
||||||
</ReactCrop>
|
</ReactCrop>
|
||||||
@@ -183,6 +187,3 @@ const ToolbarButton = ({
|
|||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
import {Path, Svg} from 'react-native-svg'
|
|
||||||
|
|
||||||
import {manipulateImage} from '#/state/gallery'
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {manipulateAsync, SaveFormat} from 'expo-image-manipulator'
|
|||||||
import {LinearGradient} from 'expo-linear-gradient'
|
import {LinearGradient} from 'expo-linear-gradient'
|
||||||
import {msg, Trans} from '@lingui/macro'
|
import {msg, Trans} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import ReactCrop, {PixelCrop} from 'react-image-crop'
|
import ReactCrop, {PercentCrop} from 'react-image-crop'
|
||||||
|
|
||||||
import {useModalControls} from '#/state/modals'
|
import {useModalControls} from '#/state/modals'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
@@ -27,7 +27,8 @@ export function Component({
|
|||||||
|
|
||||||
const {closeModal} = useModalControls()
|
const {closeModal} = useModalControls()
|
||||||
|
|
||||||
const [crop, setCrop] = React.useState<PixelCrop>()
|
const imageRef = React.useRef<HTMLImageElement>(null)
|
||||||
|
const [crop, setCrop] = React.useState<PercentCrop>()
|
||||||
|
|
||||||
const isEmpty = !crop || (crop.width || crop.height) === 0
|
const isEmpty = !crop || (crop.width || crop.height) === 0
|
||||||
|
|
||||||
@@ -37,15 +38,17 @@ export function Component({
|
|||||||
}
|
}
|
||||||
const onPressDone = async () => {
|
const onPressDone = async () => {
|
||||||
if (!isEmpty) {
|
if (!isEmpty) {
|
||||||
|
const img = imageRef.current!
|
||||||
|
|
||||||
const result = await manipulateAsync(
|
const result = await manipulateAsync(
|
||||||
uri,
|
uri,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
crop: {
|
crop: {
|
||||||
originX: crop.x,
|
originX: (crop.x * img.width) / 100,
|
||||||
originY: crop.y,
|
originY: (crop.y * img.height) / 100,
|
||||||
width: crop.width,
|
width: (crop.width * img.width) / 100,
|
||||||
height: crop.height,
|
height: (crop.height * img.height) / 100,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -72,8 +75,8 @@ export function Component({
|
|||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
<View style={[styles.cropper, pal.borderDark]}>
|
<View style={[styles.cropper, pal.borderDark]}>
|
||||||
<ReactCrop crop={crop} onChange={setCrop}>
|
<ReactCrop crop={crop} onChange={(_, next) => setCrop(next)}>
|
||||||
<img src={uri} style={{maxHeight: '75vh'}} />
|
<img ref={imageRef} src={uri} style={{maxHeight: '75vh'}} />
|
||||||
</ReactCrop>
|
</ReactCrop>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.btns}>
|
<View style={styles.btns}>
|
||||||
|
|||||||
Reference in New Issue
Block a user