mirror of
https://github.com/zoriya/react-native-svg.git
synced 2025-12-06 07:06:11 +00:00
feat: support filters on web (#2346)
# Summary * Export `Filter` and `FeColorMatrix` components on `web` * Change filter IDs in example to be unique* * Generate filter ID when using `FilterImage`* * Hide `FilterImage` example on web, since it's crashing the whole site (see #2334) \* ID on web has to be unique, otherwise it'll use the first element with that ID, even if they are in the separate SVG elements ## Test Plan run `web-example` app ## Compatibility | OS | Implemented | | ------- | :---------: | | Web | ✅ |
This commit is contained in:
@@ -22,6 +22,8 @@ import type { TextProps } from './elements/Text';
|
||||
import type { TextPathProps } from './elements/TextPath';
|
||||
import type { TSpanProps } from './elements/TSpan';
|
||||
import type { UseProps } from './elements/Use';
|
||||
import type { FilterProps } from './elements/filters/Filter';
|
||||
import type { FeColorMatrixProps } from './elements/filters/FeColorMatrix';
|
||||
import type {
|
||||
GestureResponderEvent,
|
||||
TransformsStyle,
|
||||
@@ -576,4 +578,12 @@ export class Pattern extends WebShape<BaseProps & PatternProps> {
|
||||
tag = 'pattern' as const;
|
||||
}
|
||||
|
||||
export class Filter extends WebShape<BaseProps & FilterProps> {
|
||||
tag = 'filter' as const;
|
||||
}
|
||||
|
||||
export class FeColorMatrix extends WebShape<BaseProps & FeColorMatrixProps> {
|
||||
tag = 'feColorMatrix' as const;
|
||||
}
|
||||
|
||||
export default Svg;
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
import { useMemo } from 'react';
|
||||
import {
|
||||
ImageProps,
|
||||
ImageStyle,
|
||||
Platform,
|
||||
Image as RNImage,
|
||||
StyleProp,
|
||||
StyleSheet,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import { Filter, Image, Svg } from '../index';
|
||||
import { extractResizeMode } from './extract/extractImage';
|
||||
import { Filters } from './types';
|
||||
import { resolveAssetUri } from '../lib/resolveAssetUri';
|
||||
import { getRandomNumber } from '../lib/util';
|
||||
import {
|
||||
extractFiltersCss,
|
||||
mapFilterToComponent,
|
||||
} from './extract/extractFilters';
|
||||
import { extractResizeMode } from './extract/extractImage';
|
||||
import { Filters } from './types';
|
||||
|
||||
export interface FilterImageProps extends ImageProps {
|
||||
style?: StyleProp<ImageStyle & { filter?: string | Filters }> | undefined;
|
||||
@@ -23,10 +27,14 @@ export const FilterImage = (props: FilterImageProps) => {
|
||||
const { filters = [], source, style, ...imageProps } = props;
|
||||
const styles = StyleSheet.flatten(style);
|
||||
const extractedFilters = [...filters, ...extractFiltersCss(styles?.filter)];
|
||||
const filterId = useMemo(() => `RNSVG-${getRandomNumber()}`, []);
|
||||
|
||||
const src = RNImage.resolveAssetSource(source);
|
||||
const width = props.width || styles?.width || src.width;
|
||||
const height = props.height || styles?.height || src.height;
|
||||
const src =
|
||||
Platform.OS === 'web'
|
||||
? resolveAssetUri(source)
|
||||
: RNImage.resolveAssetSource(source);
|
||||
const width = props.width || styles?.width || src?.width;
|
||||
const height = props.height || styles?.height || src?.height;
|
||||
const preserveAspectRatio = extractResizeMode(props.resizeMode);
|
||||
|
||||
return (
|
||||
@@ -41,7 +49,7 @@ export const FilterImage = (props: FilterImageProps) => {
|
||||
width="100%"
|
||||
height="100%"
|
||||
preserveAspectRatio={preserveAspectRatio}
|
||||
filter={extractedFilters.length > 0 ? 'url(#filter)' : undefined}
|
||||
filter={extractedFilters.length > 0 ? `url(#${filterId})` : undefined}
|
||||
/>
|
||||
</Svg>
|
||||
</View>
|
||||
|
||||
@@ -12,3 +12,6 @@ export function pickNotNil(object: { [prop: string]: unknown }) {
|
||||
}
|
||||
|
||||
export const idPattern = /#([^)]+)\)?$/;
|
||||
|
||||
export const getRandomNumber = () =>
|
||||
Math.floor(Math.random() * Math.floor(Math.random() * Date.now()));
|
||||
|
||||
Reference in New Issue
Block a user