Skip to content

feat: iOS filter blur #52028

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,7 @@ - (void)invalidateLayer
// filter
[_filterLayer removeFromSuperlayer];
_filterLayer = nil;
self.layer.filters = nil;
self.layer.opacity = (float)_props->opacity;
if (!_props->filter.empty()) {
float multiplicativeBrightness = 1;
Expand All @@ -995,6 +996,36 @@ - (void)invalidateLayer
multiplicativeBrightness *= std::get<Float>(primitive.parameters);
} else if (primitive.type == FilterType::Opacity) {
self.layer.opacity *= std::get<Float>(primitive.parameters);
} else if (primitive.type == FilterType::Blur) {
NSMutableArray *layerFilters = [NSMutableArray new];
static Class FilterClass = nil;
if (FilterClass == nil) {
UIVisualEffectView *tempBlurView =
[[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleRegular]];
// We search for the backdrop subview from UIVisualEffectView
// to access the underlying filter class
for (UIView *subview in tempBlurView.subviews) {
if ([NSStringFromClass(subview.class).lowercaseString containsString:@"backdrop"]) {
if (subview.layer.filters.firstObject) {
FilterClass = [subview.layer.filters.firstObject class];
break;
}
}
}
}
if (FilterClass) {
SEL selector = NSSelectorFromString(@"filterWithType:");
if ([FilterClass respondsToSelector:selector]) {
IMP methodIMP = [FilterClass methodForSelector:selector];
id (*filterWithType)(Class, SEL, NSString *) = (id (*)(Class, SEL, NSString *))methodIMP;
id gaussianBlurFilter = filterWithType(FilterClass, selector, @"gaussianBlur");

CGFloat blurRadius = std::get<Float>(primitive.parameters);
[gaussianBlurFilter setValue:@(blurRadius) forKey:@"inputRadius"];
[layerFilters addObject:gaussianBlurFilter];
}
}
self.layer.filters = layerFilters.count > 0 ? layerFilters : nil;
}
}
}
Expand All @@ -1003,10 +1034,10 @@ - (void)invalidateLayer
[self shapeLayerToMatchView:_filterLayer borderMetrics:borderMetrics];
_filterLayer.compositingFilter = @"multiplyBlendMode";
_filterLayer.backgroundColor = [UIColor colorWithRed:multiplicativeBrightness
green:multiplicativeBrightness
green:multiplicativeBrightness
blue:multiplicativeBrightness
alpha:self.layer.opacity]
.CGColor;
alpha:self.layer.opacity]
.CGColor;
// So that this layer is always above any potential sublayers this view may
// add
_filterLayer.zPosition = CGFLOAT_MAX;
Expand Down
1 change: 0 additions & 1 deletion packages/rn-tester/js/examples/Filter/FilterExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@ exports.examples = [
title: 'Blur',
description: 'blur(10)',
name: 'blur',
platform: 'android',
render(): React.Node {
return (
<StaticViewAndImageComparison
Expand Down
Loading