android - 如何在 React Native 中涂抹部分视图?
问题描述
我想在用户拖动手指的任何地方模糊图像的一部分,我不想模糊整个图像。这是我做模糊的hacky方式
我@react-native-community/blur
用于模糊视图
const MyView = () => {
const [locations, setLocation] = useState([]);
const [top, setTop] = useState();
const [left, setLeft] = useState();
return (
<>
<View
style={styles.container}
onTouchEnd={(event) => {
console.log(event.nativeEvent.locationX);
console.log(event.nativeEvent.locationY);
setLocation([
...locations,
{
right: event.nativeEvent.locationX,
bottom: event.nativeEvent.locationY,
top,
left,
},
]);
}}
onTouchStart={(event) => {
console.log('S' + event.nativeEvent.locationX);
console.log('S' + event.nativeEvent.locationY);
setLeft(event.nativeEvent.locationX);
setTop(event.nativeEvent.locationY);
}}>
<ImageBackground
style={{width, height}}
source={{
uri:
'https://images.unsplash.com/photo-1593642634315-48f5414c3ad9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80',
}}>
<Text>Hi there </Text>
</ImageBackground>
</View>
{locations.map((l, index) => {
return (
<BlurView
key={index.toString()}
style={{
width: l.right - l.left,
height: l.bottom - l.top,
backgroundColor: 'rgba(0,0,0,0.1)',
position: 'absolute',
top: parseFloat(l.top),
left: parseFloat(l.left),
right: parseFloat(l.right),
bottom: parseFloat(l.bottom),
// blurR,
// opacity: 0.4,
}}
blurType="light"
blurAmount={4}
reducedTransparencyFallbackColor="white"
/>
);
})}
</>);
};
这是一种在用户拖动手指的地方涂抹图像的一部分的非常老套的方法。在 Android 上,只要我将手指移动到两个以上的位置,应用程序就会停止响应。有谁知道一种更好的方法来涂抹部分视图而不是模糊用户拖动手指的整个图像视图
解决方案
您可以使用 PanResponder。我为您开发了一个示例应用程序。世博小吃没有模糊视图,但我想你可以轻松地将样本转换为你想要的。这是示例代码:
import React, { useState, useRef } from 'react'
import { StyleSheet, View, ImageBackground, PanResponder, Animated } from 'react-native'
const CIRCLE_RADIUS = 60
const IAmTheBlurComponent = () => {
return (
<View style={[StyleSheet.absoluteFill, { backgroundColor: 'pink', opacity: 0.5 }]}></View>
)
}
const Component = () => {
const [pointers, setPointers] = useState([])
const refs: any = useRef({}).current;
const panResponder = useRef(
PanResponder.create({
onStartShouldSetPanResponder: () => true,
onMoveShouldSetPanResponderCapture: () => true,
onPanResponderStart: (evt) => {
setPointers(evt.nativeEvent.touches.map(touch => touch.identifier))
evt.nativeEvent.touches.forEach((event) => {
refs[event.identifier] = { x: new Animated.Value(event.pageX), y: new Animated.Value(event.pageY) }
})
},
onPanResponderMove: (evt) => {
evt.nativeEvent.touches.forEach((event) => {
refs[event.identifier].x.setValue(event.pageX)
refs[event.identifier].y.setValue(event.pageY)
})
},
onPanResponderEnd: (evt) => {
setPointers(evt.nativeEvent.touches.map(touch => touch.identifier))
},
})
).current
return (
<ImageBackground
style={{
flex: 1,
position: 'relative'
}}
source={{
uri:
'https://images.unsplash.com/photo-1593642634315-48f5414c3ad9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80',
}}
{...panResponder.panHandlers}
>
{pointers.map((pnt) => {
return (
<Animated.View
key={pnt}
style={{
overflow: 'hidden',
height: CIRCLE_RADIUS * 2,
width: CIRCLE_RADIUS * 2,
borderRadius: CIRCLE_RADIUS,
position: 'absolute',
transform: [
{
translateX: Animated.subtract(refs[pnt].x, CIRCLE_RADIUS)
},
{
translateY: Animated.subtract(refs[pnt].y, CIRCLE_RADIUS)
}
]
}}
>
<IAmTheBlurComponent />
</Animated.View>
)
})}
</ImageBackground>
)
}
export default function App() {
return (
<View style={styles.container}>
<Component />
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
})
对于流畅的动画,您可以选择 Reanimated 库。我没有使用 ValueXY 或类似的东西,因此您可以轻松地将该样本转换为重新激活的样本。
这是样品博览会小吃:https ://snack.expo.io/@kubilaysali/suspicious-ice-cream
推荐阅读
- angular - 在 Angular 中导入库/模块
- c++ - 我被困在试图扭转这个公式
- java - 如何在@PostConstruct 中模拟 bean?
- android-studio - 更新到 android studio 3.3 后,使用 android studio 构建的 apk 无法正常工作
- c# - Web API 更改 JSON 解析器
- python - 智能计算距离(稀疏?)numpy.meshgrid
- model-view-controller - mvc下拉列表不显示数据值
- react-native - 试图卸载 rn-fetch-blob
- reporting-services - SSRS 报表在浏览器和报表生成器中的呈现方式不同
- common-lisp - Hunchentoot 是未知的处理程序