feat: FeDropShadow (#2514)

# Summary

Continuation of #2362 introducing highly requested  `FeDropShadow` 
filter. This addition is straightforward since it's essentially a
shorthand (as specified in the spec) for filters that are already
implemented: https://www.w3.org/TR/filter-effects-1/#feDropShadowElement

<img width="532" alt="image"
src="https://github.com/user-attachments/assets/b221ee4c-d8b0-469b-acb0-71224fb2b1e0">

## Test Plan

Example app -> Filters -> FeDropShadow

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |          |
| macOS   |          |
| Android |          |
| Web     |          |
This commit is contained in:
Jakub Grzywacz
2024-10-28 14:44:36 +01:00
committed by GitHub
parent 36ca5c4584
commit e6a27f8a3d
4 changed files with 88 additions and 5 deletions

View File

@@ -1301,7 +1301,9 @@ Filter effects are a way of processing an elements rendering before it is dis
The following filters have been implemented: The following filters have been implemented:
- FeBlend - FeBlend
- FeComposite
- FeColorMatrix - FeColorMatrix
- FeDropShadow
- FeFlood - FeFlood
- FeGaussianBlur - FeGaussianBlur
- FeMerge - FeMerge
@@ -1310,11 +1312,9 @@ The following filters have been implemented:
Not supported yet: Not supported yet:
- FeComponentTransfer - FeComponentTransfer
- FeComposite
- FeConvolveMatrix - FeConvolveMatrix
- FeDiffuseLighting - FeDiffuseLighting
- FeDisplacementMap - FeDisplacementMap
- FeDropShadow
- FeFuncA - FeFuncA
- FeFuncB - FeFuncB
- FeFuncG - FeFuncG

View File

@@ -0,0 +1,59 @@
import React from 'react';
import {
Circle,
FeDropShadow,
FeFlood,
Filter,
Rect,
Svg,
} from 'react-native-svg';
BasicMDN.title = 'Basic MDN example';
function BasicMDN() {
return (
<Svg viewBox="0 0 30 10" width="300" height="100">
<Filter id="shadow">
<FeDropShadow dx="0.2" dy="0.4" stdDeviation="0.2" />
</Filter>
<Filter id="shadow2">
<FeDropShadow dx="0" dy="0" stdDeviation="5" floodColor="cyan" />
</Filter>
<Filter id="shadow3">
<FeDropShadow
dx="-0.8"
dy="-0.8"
stdDeviation="0"
floodColor="pink"
floodOpacity="0.5"
/>
</Filter>
<Circle cx="5" cy="50%" r="4" fill="pink" filter="url(#shadow)" />
<Circle cx="15" cy="50%" r="4" fill="pink" filter="url(#shadow2)" />
<Circle cx="25" cy="50%" r="4" fill="pink" filter="url(#shadow3)" />
</Svg>
);
}
const icon = (
<Svg height="30" width="30" viewBox="0 0 140 140">
<Filter
id="floodFilterIcon"
x="50%"
filterUnits="userSpaceOnUse"
primitiveUnits="userSpaceOnUse">
<FeFlood
y="-10%"
x="10%"
width="50%"
height="50%"
floodColor="yellow"
floodOpacity="0.5"
/>
</Filter>
<Rect x="0" y="0" width="100" height="100" fill="blue" />
<Circle cx="50" cy="50" r="40" filter="url(#floodFilterIcon)" />
</Svg>
);
const samples = [BasicMDN];
export {icon, samples};

View File

@@ -3,6 +3,7 @@ import Svg, {Circle} from 'react-native-svg';
import * as FeBlend from './FeBlend'; import * as FeBlend from './FeBlend';
import * as FeColorMatrix from './FeColorMatrix'; import * as FeColorMatrix from './FeColorMatrix';
import * as FeComposite from './FeComposite'; import * as FeComposite from './FeComposite';
import * as FeDropShadow from './FeDropShadow';
import * as FeFlood from './FeFlood'; import * as FeFlood from './FeFlood';
import * as FeGaussianBlur from './FeGaussianBlur'; import * as FeGaussianBlur from './FeGaussianBlur';
import * as FeMerge from './FeMerge'; import * as FeMerge from './FeMerge';
@@ -13,6 +14,7 @@ const samples = {
FeBlend, FeBlend,
FeColorMatrix, FeColorMatrix,
FeComposite, FeComposite,
FeDropShadow,
FeFlood, FeFlood,
FeGaussianBlur, FeGaussianBlur,
FeMerge, FeMerge,

View File

@@ -1,12 +1,20 @@
import { ColorValue } from 'react-native';
import { NumberArray, NumberProp } from '../../lib/extract/types'; import { NumberArray, NumberProp } from '../../lib/extract/types';
import { warnUnimplementedFilter } from '../../lib/util'; import FeFlood from './FeFlood';
import FeGaussianBlur from './FeGaussianBlur';
import FeMerge from './FeMerge';
import FeMergeNode from './FeMergeNode';
import FeOffset from './FeOffset';
import FilterPrimitive from './FilterPrimitive'; import FilterPrimitive from './FilterPrimitive';
import FeComposite from './FeComposite';
export interface FeDropShadowProps { export interface FeDropShadowProps {
in?: string; in?: string;
stdDeviation?: NumberArray; stdDeviation?: NumberArray;
dx?: NumberProp; dx?: NumberProp;
dy?: NumberProp; dy?: NumberProp;
floodColor?: ColorValue;
floodOpacity?: NumberProp;
} }
export default class FeDropShadow extends FilterPrimitive<FeDropShadowProps> { export default class FeDropShadow extends FilterPrimitive<FeDropShadowProps> {
@@ -17,7 +25,21 @@ export default class FeDropShadow extends FilterPrimitive<FeDropShadowProps> {
}; };
render() { render() {
warnUnimplementedFilter(); const { stdDeviation, in: in1 = 'SourceGraphic', dx, dy } = this.props;
return null; return (
<>
<FeGaussianBlur in={in1} stdDeviation={stdDeviation} />
<FeOffset dx={dx} dy={dy} result="offsetblur" />
<FeFlood
floodColor={this.props.floodColor}
floodOpacity={this.props.floodOpacity}
/>
<FeComposite in2="offsetblur" operator="in" />
<FeMerge>
<FeMergeNode />
<FeMergeNode in={in1} />
</FeMerge>
</>
);
} }
} }