feat: add FeMerge and FeMergeNode filters (#2369)

# Summary

As mentioned in #2362
Introduce new filters:
* `FeMerge`
* `FeMergeNode`

## Example usage

```tsx
<Svg width="200" height="200">
  <Filter id="mergeWithOffset" width="180" height="180">
    <FeOffset dx="50" dy="50" result="test" />
    <FeOffset dx="100" dy="100" in="SourceGraphic" />
    <FeMerge>
      <FeMergeNode in="SourceGraphic" />
      <FeMergeNode in="test" />
      <FeMergeNode />
    </FeMerge>
  </Filter>
  <Rect
    x="0"
    y="0"
    width="100"
    height="100"
    stroke="black"
    fill="red"
    filter="url(#mergeWithOffset)"
  />
</Svg>
```

<img width="207" alt="image"
src="https://github.com/user-attachments/assets/9cb3ded6-f939-4b2b-8ece-df54e64fe898">

## Test Plan

`Example` app -> `Filters` -> `FeMerge`

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |         |
| Android |         |

## Checklist

- [x] I have tested this on a device and a simulator
- [x] I added documentation in `README.md`
- [x] I updated the typed files (typescript)
This commit is contained in:
Jakub Grzywacz
2024-07-31 13:23:53 +02:00
committed by GitHub
parent a2e843bc9c
commit b8b022c31e
25 changed files with 508 additions and 9 deletions
@@ -0,0 +1,92 @@
import React, {Component} from 'react';
import {
Svg,
Circle,
FeColorMatrix,
Filter,
G,
FeMerge,
FeMergeNode,
Rect,
FeOffset,
} from 'react-native-svg';
class WithOffsetsExample extends Component {
static title = 'Merge with SourceGraphic and offsets';
render() {
return (
<Svg width="200" height="200">
<Filter id="mergeWithOffset" width="180" height="180">
<FeOffset dx="50" dy="50" result="test" />
<FeOffset dx="100" dy="100" in="SourceGraphic" />
<FeMerge>
<FeMergeNode in="SourceGraphic" />
<FeMergeNode in="test" />
<FeMergeNode />
</FeMerge>
</Filter>
<Rect
x="0"
y="0"
width="100"
height="100"
stroke="black"
fill="red"
filter="url(#mergeWithOffset)"
/>
</Svg>
);
}
}
class WithHueRotateExample extends Component {
static title = 'Merge with SourceGraphic and HueRotate';
render() {
return (
<Svg width="150" height="150">
<Filter id="mergeWithHue" width="180" height="180">
<FeOffset dx="50" dy="50" />
<FeColorMatrix type="hueRotate" values="240" />
<FeMerge>
<FeMergeNode />
<FeMergeNode in="SourceGraphic" />
</FeMerge>
</Filter>
<Rect
x="0"
y="0"
width="100"
height="100"
stroke="black"
fill="red"
filter="url(#mergeWithHue)"
/>
</Svg>
);
}
}
const icon = (
<Svg height="30" width="30" viewBox="0 0 20 20">
<Filter id="mergeWithOffsetIcon" width="180" height="180">
<FeOffset dx="5" dy="5" />
<FeMerge>
<FeMergeNode />
<FeMergeNode in="SourceGraphic" />
</FeMerge>
</Filter>
<Rect
x="1"
y="1"
width="13"
height="13"
fill="blue"
filter="url(#mergeWithOffsetIcon)"
strokeWidth="1"
stroke="black"
/>
</Svg>
);
const samples = [WithOffsetsExample, WithHueRotateExample];
export {icon, samples};
@@ -1,5 +1,12 @@
import * as FeColorMatrix from './FeColorMatrix';
import * as FeGaussianBlur from './FeGaussianBlur';
import * as FeMerge from './FeMerge';
import * as FeOffset from './FeOffset';
import * as ReanimatedFeColorMatrix from './ReanimatedFeColorMatrix';
export {FeColorMatrix, FeGaussianBlur, FeOffset, ReanimatedFeColorMatrix};
export {
FeColorMatrix,
FeGaussianBlur,
FeMerge,
FeOffset,
ReanimatedFeColorMatrix,
};