基于react-native-skia实现图片点击触发的灰度-彩色Shader过渡效果
React Native Skia 实现灰度与彩色的圆形展开过渡切换
要实现点击时圆形展开的过渡效果来切换图片的灰度/彩色显示,你需要结合动画状态管理和Shader过渡逻辑修改现有代码,具体实现如下:
1. 引入必要工具
先导入动画与交互相关的API:
import { useSharedValue, withTiming } from 'react-native-reanimated'; import { TouchableWithoutFeedback } from 'react-native';
2. 更新Shader,加入过渡逻辑
修改原有灰度Shader,添加进度变量和圆形展开判断:
const TRANSITION_SHADER = Skia.RuntimeEffect.Make(` uniform shader image; uniform float progress; half4 main(in vec2 xy) { // 获取原始像素颜色 vec4 texColor = image.eval(xy).rgba; // 计算灰度值 vec3 gray_scale = vec3(dot(vec3(0.5, 0.2, 0.2), texColor.rgb)); // 计算当前像素到图片中心的归一化距离(xy范围为0-1,中心在(0.5,0.5)) vec2 center = vec2(0.5, 0.5); float distanceToCenter = distance(xy, center); // 根据进度切换显示:progress从0到1时,圆形区域逐步扩大显示彩色 vec3 finalColor = mix(gray_scale, texColor.rgb, step(distanceToCenter, progress)); return vec4(finalColor, texColor.a); } `)!
如果想要更柔和的过渡边缘,可将step替换为smoothstep(distanceToCenter - 0.05, distanceToCenter, progress),调整数值能控制边缘模糊程度。
3. 绑定动画状态与点击事件
在组件中添加状态变量,触发点击切换动画:
const image = useImage('../path/to/image.png'); // 过渡进度:0=全灰度,1=全彩色 const transitionProgress = useSharedValue(0); // 点击触发切换动画 const handleToggle = () => { transitionProgress.value = withTiming( transitionProgress.value === 0 ? 1 : 0, { duration: 800 } // 动画时长可自定义 ); }; return ( <TouchableWithoutFeedback onPress={handleToggle}> <Canvas style={{ flex: 1 }}> <Image image={image} fit="cover" x={0} y={0} width={200} height={200} > <RuntimeShader source={TRANSITION_SHADER} uniforms={{ progress: transitionProgress, }} /> </Image> </Canvas> </TouchableWithoutFeedback> );
核心说明
useSharedValue存储动画进度,确保Shader能实时读取状态变化withTiming实现平滑补间动画,完成0到1或1到0的进度切换- Shader中的
xy是图片归一化坐标,无需考虑实际像素尺寸,适配更灵活
内容的提问来源于stack exchange,提问作者HichamELBSI
相关产品推荐
相关产品推荐

