Kureev / react-native-blur

React Native Blur component
MIT License
3.76k stars 556 forks source link

Animate blurAmount #152

Open jackread opened 7 years ago

jackread commented 7 years ago

I'd like to be able to animate the blur amount. RIght now, it looks like this is not supported...

<Animated.BlurView blurAmount={this.state.blurAmount} />

Animated.timing(
    this.state.blurAmount,
    {
        toValue: 20,
        easing: Easing.inOut(Easing.ease),
        duration: 300
    }
).start();
eliperkins commented 7 years ago

I've got this kind of working in a branch: https://github.com/eliperkins/react-native-blur/tree/rewrite

By using UIViewPropertyAnimator, we can create an animation from a fully blurred state, to a non-blurred state.

apr-07-2017 19-45-07

Unfortunately, UIViewPropertyAnimator is only available on iOS 10+, so it won't fly for those people targeting iOS 9. It'd be nice to find a way to support this for iOS 10, and fall back to something else gracefully on iOS 9.

I'll see if I can polish things up and get a pull request up.

richardchim commented 7 years ago

Not sure about performance, but I was able get it working and it looks pretty smooth. What I ended up doing was adding a listener to the Animated instance and then setting the blurAmount through state changes:

// Initialize animation and set the listener
this.animation = new Animated.Value(0);
this.animation.addListener((value) => {
  this.setState({modalBlur: value.value});
});

// Start the animation as usual
this.animation.setValue(5);
Animated.timing(
  this.animation,
  {
    duration: 100,
    toValue: 15
  }
).start()

// Render...
<BlurView blurType="light" style={{flex: 1}} blurAmount={this.state.modalBlur}>
    <Button title="close" onPress={this.onCloseModal}/>
</BlurView>
gran33 commented 7 years ago

@richardchim I've tried your solution, seams not to work. Does it work for u?

richardchim commented 7 years ago

@gran33, I apologize, I should have tested my original post. Apparently, I discovered how to do it by accident. In my case, I was actually using a Modal. The Modal wraps the BlurView and has a transparent background. Here's a working example this time:

import React, {
    Component
} from 'react';

import {
    Animated,
    Modal,
    Text,
    TouchableOpacity,
    View,
} from 'react-native';

import {
    BlurView,
} from 'react-native-blur';

class BlurExample extends Component {
    componentWillMount() {
        this.animation.setValue(0);
        Animated.timing(
            this.animation,
            {
                duration: 1000,
                toValue: 20
            }
        ).start();
    }

    constructor(props) {
        super(props);
        this.animation = new Animated.Value(0);
        this.animation.addListener((value) => {
            this.setState({modalBlur: value.value});
        });
    }

    render() {
        return (
            <View>
                <Modal
                    transparent={true}
                >
                    <BlurView blurType="light" style={{flex: 1}} blurAmount={this.state.modalBlur}>
                        <View style={{flex: 1}}>
                            <Text  style={{textAlign: 'center', padding: 22}}>This text is clear</Text>
                        </View>
                   </BlurView>
                </Modal>

                <View style={{flexDirection: 'column', alignItems: 'center'}}>
                    <Text>This gets blurred</Text>
                    <TouchableOpacity style={{backgroundColor: 'red', height: 80, width: 80}}/>
                    <TouchableOpacity style={{backgroundColor: 'green', height: 80, width: 80}}/>
                    <TouchableOpacity style={{backgroundColor: 'blue', height: 80, width: 80}}/>
                </View>
            </View>
        )
    }
}

export default BlurExample;
ahanriat commented 7 years ago

It would be awesome to have some support for real Animated animation => nativeDriver <3

Kureev commented 7 years ago

@ahanriat It'll be great if you can contribute!

sjmueller commented 7 years ago

Did animating blurAmount make it into 3.0.0? If not, is there any recommended workarounds to get similar functionality until it drops?

zachgibson commented 6 years ago

Absolutely position BlurView and place it on top of your UI you want to blur. Then wrap that BlurView in an Animated.View and you can animate opacity to increase/decrease bluriness.

Noitidart commented 6 years ago

@zachgibson that's a really cool idea, that will work on iOS and Android, will give that a shot thanks for sharing!

zachgibson commented 6 years ago

Glad to help @Noitidart!

sjmueller commented 6 years ago

@zachgibson thanks for sharing, but this is not the same as animating blurAmount. iOS 11 does gesture-controlled transitions everywhere that increase the blur radius, and the effect is much more rich than manipulating opacity.

zachgibson commented 6 years ago

@sjmueller Yeah you’re totally right. You lose movement on your blurring shapes.

umitanuki commented 6 years ago

The issue was really painful for me but thanks to the insights on this thread I finally implemented blur animation using UIViewPropertyAnimator. You can take a look at it here: https://github.com/AlpacaDB/react-native-blur/tree/animate

One PR I've sent earlier prevented setNativeProps from working correctly, so createAnimatedComponent() didn't work properly. This was an easy fix. The second issue I had based on @eliperkins repo was that it was not dynamically setting property and also the timing of configuring animation was a bit too early. I deferred it to after the view tree is complete. I'm not sending a PR for this since I completely rewrite BlurView using UIViewPropertyAnimator so it supports iOS 10+ only. Someone can try merge with old code, but basically I didn't want to include the use of private API, so I removed the old hack of setting blurAmount using the subclass approach.

For those who read this and wonder, yes setting opacity is an easy solution but the blur effect is pretty different. Even the subclass approach I noticed the text gets jaggy at lower blurAmount (like 1 or 2). With UIViewPropertyAnimator, it is the same or nearly the same as iOS behavior.

Noitidart commented 6 years ago

@umitanuki wow way cool start! Not submitting a PR yet makes sense. It would need < iOS10 and Android support I think.

By the way, how does the expo animated BlurView work? https://docs.expo.io/versions/latest/sdk/blur-view.html I thought expo just used this module from this repo?

lucas-figueiredo-m commented 3 years ago

Hi @Kureev ! I was investigation about why it isn't possible to animate BlurView, and I found that when Animated.interpolate is used, then suddenly the app. I happens that interpolate may generate float numbers, in order to properly interpolate values. But when I saw BlurViewManager.java file, it seems that defaultRadius and radius from setRadius are both int variables. Then When interpolating float numbers and using into int values crashes the app.

Could you transform those java variables properly to float? I could contribute to it, but I'm not an expert on pure Android development.

Thanks!