mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Add mix-blend-mode effects to iOS (#45304)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45304 Add support for most keyword values of mix-blend-mode on iOS and added RNTester Example Missing compositing operators and global values Changelog: [Internal] Reviewed By: NickGerleman Differential Revision: D59402969 fbshipit-source-id: b7e1aaed01fbf8f80e04ad0fa73d2ef63b5ad933
This commit is contained in:
committed by
Facebook GitHub Bot
parent
a96272e27e
commit
944d40f204
+57
@@ -20,6 +20,7 @@
|
||||
#import <react/renderer/components/view/ViewEventEmitter.h>
|
||||
#import <react/renderer/components/view/ViewProps.h>
|
||||
#import <react/renderer/components/view/accessibilityPropsConversions.h>
|
||||
#import <react/renderer/graphics/BlendMode.h>
|
||||
|
||||
#ifdef RCT_DYNAMIC_FRAMEWORKS
|
||||
#import <React/RCTComponentViewFactory.h>
|
||||
@@ -403,6 +404,11 @@ using namespace facebook::react;
|
||||
_needsInvalidateLayer = YES;
|
||||
}
|
||||
|
||||
// `mixBlendMode`
|
||||
if (oldViewProps.mixBlendMode != newViewProps.mixBlendMode) {
|
||||
_needsInvalidateLayer = YES;
|
||||
}
|
||||
|
||||
// `boxShadow`
|
||||
if (oldViewProps.boxShadow != newViewProps.boxShadow) {
|
||||
_needsInvalidateLayer = YES;
|
||||
@@ -776,6 +782,57 @@ static RCTBorderStyle RCTBorderStyleFromBorderStyle(BorderStyle borderStyle)
|
||||
[self.layer addSublayer:_filterLayer];
|
||||
}
|
||||
|
||||
switch (_props->mixBlendMode) {
|
||||
case BlendMode::Multiply:
|
||||
layer.compositingFilter = @"multiplyBlendMode";
|
||||
break;
|
||||
case BlendMode::Screen:
|
||||
layer.compositingFilter = @"screenBlendMode";
|
||||
break;
|
||||
case BlendMode::Overlay:
|
||||
layer.compositingFilter = @"overlayBlendMode";
|
||||
break;
|
||||
case BlendMode::Darken:
|
||||
layer.compositingFilter = @"darkenBlendMode";
|
||||
break;
|
||||
case BlendMode::Lighten:
|
||||
layer.compositingFilter = @"lightenBlendMode";
|
||||
break;
|
||||
case BlendMode::ColorDodge:
|
||||
layer.compositingFilter = @"colorDodgeBlendMode";
|
||||
break;
|
||||
case BlendMode::ColorBurn:
|
||||
layer.compositingFilter = @"colorBurnBlendMode";
|
||||
break;
|
||||
case BlendMode::HardLight:
|
||||
layer.compositingFilter = @"hardLightBlendMode";
|
||||
break;
|
||||
case BlendMode::SoftLight:
|
||||
layer.compositingFilter = @"softLightBlendMode";
|
||||
break;
|
||||
case BlendMode::Difference:
|
||||
layer.compositingFilter = @"differenceBlendMode";
|
||||
break;
|
||||
case BlendMode::Exclusion:
|
||||
layer.compositingFilter = @"exclusionBlendMode";
|
||||
break;
|
||||
case BlendMode::Hue:
|
||||
layer.compositingFilter = @"hueBlendMode";
|
||||
break;
|
||||
case BlendMode::Saturation:
|
||||
layer.compositingFilter = @"saturationBlendMode";
|
||||
break;
|
||||
case BlendMode::Color:
|
||||
layer.compositingFilter = @"colorBlendMode";
|
||||
break;
|
||||
case BlendMode::Luminosity:
|
||||
layer.compositingFilter = @"luminosityBlendMode";
|
||||
break;
|
||||
case BlendMode::Normal:
|
||||
layer.compositingFilter = nil;
|
||||
break;
|
||||
}
|
||||
|
||||
_boxShadowLayer = nil;
|
||||
if (!_props->boxShadow.empty()) {
|
||||
_boxShadowLayer = [CALayer layer];
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <react/renderer/core/LayoutMetrics.h>
|
||||
#include <react/renderer/core/Props.h>
|
||||
#include <react/renderer/core/PropsParserContext.h>
|
||||
#include <react/renderer/graphics/BlendMode.h>
|
||||
#include <react/renderer/graphics/BoxShadow.h>
|
||||
#include <react/renderer/graphics/Color.h>
|
||||
#include <react/renderer/graphics/Filter.h>
|
||||
@@ -63,7 +64,7 @@ class BaseViewProps : public YogaStylableProps, public AccessibilityProps {
|
||||
std::vector<FilterPrimitive> filter{};
|
||||
|
||||
// MixBlendMode
|
||||
std::string mixBlendMode;
|
||||
BlendMode mixBlendMode;
|
||||
|
||||
// Transform
|
||||
Transform transform{};
|
||||
|
||||
@@ -61,7 +61,8 @@ void ViewShadowNode::initialize() noexcept {
|
||||
viewProps.accessibilityViewIsModal ||
|
||||
viewProps.importantForAccessibility != ImportantForAccessibility::Auto ||
|
||||
viewProps.removeClippedSubviews || viewProps.cursor != Cursor::Auto ||
|
||||
!viewProps.filter.empty() || !viewProps.mixBlendMode.empty() ||
|
||||
!viewProps.filter.empty() ||
|
||||
viewProps.mixBlendMode != BlendMode::Normal ||
|
||||
HostPlatformViewTraitsInitializer::formsStackingContext(viewProps);
|
||||
|
||||
bool formsView = formsStackingContext ||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <react/renderer/core/LayoutMetrics.h>
|
||||
#include <react/renderer/core/PropsParserContext.h>
|
||||
#include <react/renderer/core/RawProps.h>
|
||||
#include <react/renderer/graphics/BlendMode.h>
|
||||
#include <react/renderer/graphics/BoxShadow.h>
|
||||
#include <react/renderer/graphics/Filter.h>
|
||||
#include <react/renderer/graphics/PlatformColorParser.h>
|
||||
@@ -1069,6 +1070,27 @@ inline void fromRawValue(
|
||||
result = filter;
|
||||
}
|
||||
|
||||
inline void fromRawValue(
|
||||
const PropsParserContext& /*context*/,
|
||||
const RawValue& value,
|
||||
BlendMode& result) {
|
||||
react_native_expect(value.hasType<std::string>());
|
||||
result = BlendMode::Normal;
|
||||
if (!value.hasType<std::string>()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto rawBlendMode = static_cast<std::string>(value);
|
||||
std::optional<BlendMode> blendMode = blendModeFromString(rawBlendMode);
|
||||
|
||||
if (!blendMode) {
|
||||
LOG(ERROR) << "Could not parse blend mode: " << rawBlendMode;
|
||||
return;
|
||||
}
|
||||
|
||||
result = blendMode.value();
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
inline std::string toString(const std::array<float, N> vec) {
|
||||
std::string s;
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <react/renderer/graphics/Float.h>
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
enum class BlendMode {
|
||||
Normal,
|
||||
Multiply,
|
||||
Screen,
|
||||
Overlay,
|
||||
Darken,
|
||||
Lighten,
|
||||
ColorDodge,
|
||||
ColorBurn,
|
||||
HardLight,
|
||||
SoftLight,
|
||||
Difference,
|
||||
Exclusion,
|
||||
Hue,
|
||||
Saturation,
|
||||
Color,
|
||||
Luminosity,
|
||||
};
|
||||
|
||||
inline std::optional<BlendMode> blendModeFromString(
|
||||
std::string_view blendModeName) {
|
||||
if (blendModeName == "normal") {
|
||||
return BlendMode::Normal;
|
||||
} else if (blendModeName == "multiply") {
|
||||
return BlendMode::Multiply;
|
||||
} else if (blendModeName == "screen") {
|
||||
return BlendMode::Screen;
|
||||
} else if (blendModeName == "overlay") {
|
||||
return BlendMode::Overlay;
|
||||
} else if (blendModeName == "darken") {
|
||||
return BlendMode::Darken;
|
||||
} else if (blendModeName == "lighten") {
|
||||
return BlendMode::Lighten;
|
||||
} else if (blendModeName == "color-dodge") {
|
||||
return BlendMode::ColorDodge;
|
||||
} else if (blendModeName == "color-burn") {
|
||||
return BlendMode::ColorBurn;
|
||||
} else if (blendModeName == "hard-light") {
|
||||
return BlendMode::HardLight;
|
||||
} else if (blendModeName == "soft-light") {
|
||||
return BlendMode::SoftLight;
|
||||
} else if (blendModeName == "difference") {
|
||||
return BlendMode::Difference;
|
||||
} else if (blendModeName == "exclusion") {
|
||||
return BlendMode::Exclusion;
|
||||
} else if (blendModeName == "hue") {
|
||||
return BlendMode::Hue;
|
||||
} else if (blendModeName == "saturation") {
|
||||
return BlendMode::Saturation;
|
||||
} else if (blendModeName == "color") {
|
||||
return BlendMode::Color;
|
||||
} else if (blendModeName == "luminosity") {
|
||||
return BlendMode::Luminosity;
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
} // namespace facebook::react
|
||||
@@ -298,6 +298,10 @@ const APIs: Array<RNTesterModuleInfo> = ([
|
||||
key: 'FilterExample',
|
||||
module: require('../examples/Filter/FilterExample'),
|
||||
},
|
||||
{
|
||||
key: 'MixBlendModeExample',
|
||||
module: require('../examples/MixBlendMode/MixBlendModeExample'),
|
||||
},
|
||||
{
|
||||
key: 'TurboModuleExample',
|
||||
module: require('../examples/TurboModule/TurboModuleExample'),
|
||||
|
||||
Reference in New Issue
Block a user