react-native-blur icon indicating copy to clipboard operation
react-native-blur copied to clipboard

Animate blurAmount

Open jackread opened this issue 8 years ago • 15 comments

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();

jackread avatar Feb 07 '17 22:02 jackread

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.

eliperkins avatar Apr 07 '17 23:04 eliperkins

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>

richardchim avatar Apr 21 '17 03:04 richardchim

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

gran33 avatar Apr 24 '17 12:04 gran33

@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;

richardchim avatar Apr 25 '17 00:04 richardchim

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

ahanriat avatar Apr 27 '17 15:04 ahanriat

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

Kureev avatar Apr 30 '17 16:04 Kureev

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

sjmueller avatar Jun 16 '17 01:06 sjmueller

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.

zachgibson avatar Nov 26 '17 23:11 zachgibson

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

Noitidart avatar Dec 13 '17 07:12 Noitidart

Glad to help @Noitidart!

zachgibson avatar Dec 13 '17 14:12 zachgibson

@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.

sjmueller avatar Dec 13 '17 18:12 sjmueller

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

zachgibson avatar Dec 13 '17 19:12 zachgibson

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.

umitanuki avatar Dec 23 '17 08:12 umitanuki

@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?

Noitidart avatar Dec 23 '17 13:12 Noitidart

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!

lucas-figueiredo-m avatar Mar 25 '21 15:03 lucas-figueiredo-m