Repository: 73R3WY/react-native-svg-animations
Branch: master
Commit: 7779a7613d7a
Files: 20
Total size: 45.2 KB
Directory structure:
gitextract_nvt6lyug/
├── .gitignore
├── LICENSE
├── README.md
├── components/
│ ├── AnimatedPath/
│ │ └── index.tsx
│ ├── AnimatedSVG/
│ │ └── index.tsx
│ ├── AnimatedSVGPath/
│ │ └── index.tsx
│ └── AnimatedSVGPaths/
│ └── index.tsx
├── examples/
│ ├── HiSVG/
│ │ ├── d.js
│ │ └── index.js
│ └── IngenuityPreloaderSVG/
│ ├── d.js
│ └── index.js
├── index.js
├── package.json
└── utils/
├── AnimatedListener/
│ └── index.js
├── AnimatedSVG/
│ └── index.js
├── AnimatedSVGBrush/
│ └── index.js
├── AnimatedSVGPropString/
│ └── index.js
├── AnimatedSVGState/
│ └── index.js
├── AnimatedSVGTransform/
│ └── index.js
└── Matrix2D/
└── index.ts
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.vscode/
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2017 Jeremy Patrick Pacabis
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# react-native-svg-animations [](https://badge.fury.io/js/react-native-svg-animations)
> SVG Animations wrapper for react-native. Based on examples from this project: https://github.com/ethantran/react-native-examples
## Dependencies
- `svg-path-properties`
- `react-native-svg`
## Installation
```
npm i react-native-svg-animations --save
```
or
```
yarn add react-native-svg-animations
```
## Demo
<table>
<tr>
<td>
<strong>AnimatedSVGPath</strong>
</td>
<td>
<strong>AnimatedSVGPaths</strong>
</td>
</tr>
<tr>
<td>
<img src="https://raw.githubusercontent.com/73R3WY/react-native-svg-animations/master/examples/HiSVG/hi_1.gif" width="300">
</td>
<td>
<img src="https://raw.githubusercontent.com/73R3WY/react-native-svg-animations/master/examples/IngenuityPreloaderSVG/preloader_1.gif" width="300">
</td>
</tr>
</table>
## Usage
This package contains wrapper components for displaying animated SVG in react-native, currently, this contains the following:
- AnimatedSVGPath
- AnimatedSVGPaths
###### AnimatedSVGPath
Component to display a single animated SVG Path.
See <a href="https://github.com/73R3WY/react-native-svg-animations/tree/master/examples/HiSVG">Hi example</a> for the complete implementation.
<img src="https://raw.githubusercontent.com/73R3WY/react-native-svg-animations/master/examples/HiSVG/hi_2.gif" width="300">
```javascript
import { AnimatedSVGPath } from "react-native-svg-animations";
```
...
```javascript
<View>
<AnimatedSVGPath
strokeColor={"green"}
duration={500}
strokeWidth={10}
strokeLinecap={"round"}
strokeDashArray={[42.76482137044271, 42.76482137044271]}
height={400}
width={400}
scale={0.75}
delay={100}
d={d}
loop={false}
/>
</View>
```
where the properties are:
- `d` - the SVG Path to be animated. (required)
- `strokeColor` - the color of the path stroke. (defaults to black)
- `strokeWidth` - the thickness of the path stroke. (defaults to 1)
- `strokeLinecap` - the shape to be used at the end of open subpaths when they are stroked. (defaults to butt)
- `strokeDashArray` - the number and length of strokes. (defaults to total length obtained from properties of d)
- `height` - the height of the base SVG. (defaults to screen viewport height)
- `width` - the width of the base SVG. (defaults to screen viewport width)
- `scale` - the scale of the output SVG based on the width and height of the base SVG. (defaults to 1.0 or 100%)
- `delay` - time in `ms` before starting animation. (defaults to 1000ms or 1s)
- `pause` - time in `ms` to pause at the end of the animation or at the half point of a rewound animation. (defaults 0)
- `duration` - time in `ms` to complete the path drawing from starting point to ending point. (defaults to 1000ms or 1s)
- `fill` - the color fill of the closed path. (defaults to none)
- `loop` - whether the animation loops infinitely. (defaults to true)
- `reverse` - Begins drawn and fades as you go . (defaults to false)
- `rewind` - the path is rewound when it was complete. (defaults to false)
###### AnimatedSVGPaths
Component to display a multiple animated SVG Paths.
See <a href="https://github.com/73R3WY/react-native-svg-animations/tree/master/examples/IngenuityPreloaderSVG">Ingenuity preloader example</a> for the complete implementation.
<img src="https://raw.githubusercontent.com/73R3WY/react-native-svg-animations/master/examples/IngenuityPreloaderSVG/preloader_2.gif" width="300">
```javascript
import { AnimatedSVGPaths } from "react-native-svg-animations";
```
...
```javascript
<View>
<AnimatedSVGPaths
strokeColor={"red"}
strokeWidth={5}
duration={10000}
height={600}
width={600}
scale={0.5}
delay={100}
ds={ds}
/>
</View>
```
where the properties are:
- `strokeColor` - the color of the path stroke. (defaults to black)
- `strokeWidth` - the thickness of the path stroke. (defaults to 1)
- `height` - the height of the base SVG. (defaults to screen viewport height)
- `width` - the width of the base SVG. (defaults to screen viewport width)
- `scale` - the scale of the output SVG based on the width and height of the base SVG. (defaults to 1.0 or 100%)
- `delay` - time in `ms` before starting animation. (defaults to 1000ms or 1s)
- `pause` - time in `ms` to pause at the end of the animation or at the half point of a rewound animation. (defaults 0)
- `duration` - time in `ms` to complete the path drawing from starting point to ending point. (defaults to 1000ms or 1s)
- `fill` - the color fill of the closed path. (defaults to none)
- `loop` - whether the animation loops infinitely. (defaults to true)
- `reverse` - Begins drawn and fades as you go . (defaults to false)
- `rewind` - the path is rewound when it was complete. (defaults to false)
- `sequential` - paths start to animate sequentially with the delay between them specified in the `delay` prop, and wait for the last one to finish before a new animation begins. (defaults to false)
- `ds` - the SVG Paths to be animated, must be an array; either this or `customSvgProps` is required.
- `customSvgProps` - an array of objects to define path properties; other properties will be overwritten by the values defined in these objects; either this or `ds` is required.
```javascript
<AnimatedSVGPaths
//...
customSvgProps={[
{
d: "M 10 10 C 20 20, 40 20, 50 10",
strokeColor: 'blue',
strokeWidth: 1
//...
},
{
d: "M 70 10 C 70 20, 110 20, 110 10",
strokeColor: 'red',
strokeWidth: 3
//...
},
]}
//...
/>
```
## TODO
- Other animated SVG objects.
## Contributing
1. Fork it!
2. Create your feature branch: `git checkout -b my-new-feature`
3. Commit your changes: `git commit -am 'Add some feature'`
4. Push to the branch: `git push origin my-new-feature`
5. Submit a pull request :D
## Contributors
Special thanks to these contributors:
<table>
<tbody>
<tr>
<td align="center" valign="top" width="14.28%">
<a href="https://github.com/Mr-Bhardwa7">
<img src="https://avatars.githubusercontent.com/u/40822939?v=3?s=100" width="100px;" alt="Mr-Bhardwa7"/>
<br />
<sub><b>Mr-Bhardwa7</b></sub>
</a>
</td>
<td align="center" valign="top" width="14.28%">
<a href="https://github.com/dimofte">
<img src="https://avatars.githubusercontent.com/u/4060827?v=3?s=100" width="100px;" alt="dimofte"/>
<br />
<sub><b>dimofte</b></sub>
</a>
</td>
<td align="center" valign="top" width="14.28%">
<a href="https://github.com/jvt">
<img src="https://avatars.githubusercontent.com/u/2718101?v=3?s=100" width="100px;" alt="jvt"/>
<br />
<sub><b>jvt</b></sub>
</a>
</td>
<td align="center" valign="top" width="14.28%">
<a href="https://github.com/b8ne">
<img src="https://avatars.githubusercontent.com/u/19263633?v=3?s=100" width="100px;" alt="b8ne"/>
<br />
<sub><b>b8ne</b></sub>
</a>
</td>
<td align="center" valign="top" width="14.28%">
<a href="https://github.com/hovlev">
<img src="https://avatars.githubusercontent.com/u/1330309?v=3?s=100" width="100px;" alt="hovlev"/>
<br />
<sub><b>hovlev</b></sub>
</a>
</td>
<td align="center" valign="top" width="14.28%">
<a href="https://github.com/qvick1pro">
<img src="https://avatars.githubusercontent.com/u/12903197?v=3?s=100" width="100px;" alt="qvick1pro"/>
<br />
<sub><b>qvick1pro</b></sub>
</a>
</td>
<td align="center" valign="top" width="14.28%">
<a href="https://github.com/TristanTouchain">
<img src="https://avatars.githubusercontent.com/u/36477156?v=3?s=100" width="100px;" alt="TristanTouchain"/>
<br />
<sub><b>TristanTouchain</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%">
<a href="https://github.com/nitzanbener">
<img src="https://avatars.githubusercontent.com/u/44496859?v=3?s=100" width="100px;" alt="nitzanbener"/>
<br />
<sub><b>nitzanbener</b></sub>
</a>
</td>
<td align="center" valign="top" width="14.28%">
<a href="https://github.com/muh-hamada">
<img src="https://avatars.githubusercontent.com/u/56512406?v=3?s=100" width="100px;" alt="muh-hamada"/>
<br />
<sub><b>muh-hamada</b></sub>
</a>
</td>
<td align="center" valign="top" width="14.28%">
<a href="https://github.com/benomatis">
<img src="https://avatars.githubusercontent.com/u/5822748?v=3?s=100" width="100px;" alt="benomatis"/>
<br />
<sub><b>benomatis</b></sub>
</a>
</td>
</tr>
</tbody>
</table>
## License
MIT
================================================
FILE: components/AnimatedPath/index.tsx
================================================
import React, { useEffect, useState } from 'react'
import { Animated, Easing } from 'react-native'
import { svgPathProperties } from 'svg-path-properties'
import { PathProps } from 'react-native-svg'
import Path from '../AnimatedSVG'
export interface AnimatedSvgPathProps {
d: string
strokeColor?: PathProps[`stroke`]
strokeWidth?: PathProps[`strokeWidth`]
strokeLinecap?: PathProps[`strokeLinecap`]
easing?: Animated.TimingAnimationConfig[`easing`]
fill?: PathProps[`fill`]
duration?: number
delay?: number
scale?: number
loop?: boolean
transform?: PathProps[`transform`]
reverse?: boolean
rewind?: boolean
pause?: number
}
const AnimatedSvgPath: React.FC<AnimatedSvgPathProps> = ({
d,
strokeColor = 'black',
strokeWidth = 1,
strokeLinecap = 'butt',
easing = Easing.inOut(Easing.ease),
duration = 1000,
delay = 1000,
fill = 'none',
scale = 1,
loop = true,
transform = '',
reverse = false,
rewind = false,
pause = 0,
}) => {
let loopCount = 0
const properties = new svgPathProperties(d)
const length = properties.getTotalLength()
const strokeDashoffset = new Animated.Value(!reverse ? length : 0)
const animate = () => {
strokeDashoffset.setValue(!reverse ? length : 0)
const animationsSequence = [].concat(
[
Animated.delay(delay * (loopCount && rewind ? 2 : 1)),
Animated.timing(strokeDashoffset, {
toValue: !reverse ? 0 : length,
duration: duration,
useNativeDriver: true,
easing,
}),
],
pause
? [Animated.delay(pause)]
: [],
rewind
? [
Animated.timing(strokeDashoffset, {
toValue: !reverse ? length : 0,
duration: duration,
useNativeDriver: true,
easing,
}),
]
: []
)
Animated.sequence(animationsSequence).start(() => {
if (loop) {
animate()
}
})
loopCount = 1
}
useEffect(() => {
animate()
}, [])
return (
<Path
strokeDasharray={[length, length]}
strokeDashoffset={strokeDashoffset}
strokeWidth={strokeWidth}
strokeLinecap={strokeLinecap}
stroke={strokeColor}
scale={scale}
fill={fill}
transform={transform}
d={d}
/>
)
}
export default AnimatedSvgPath
================================================
FILE: components/AnimatedSVG/index.tsx
================================================
import React, { Component, Ref } from 'react'
import { Path, PathProps } from 'react-native-svg'
import AnimatedSvg from '../../utils/AnimatedSVG'
interface AnimatedSvgPathBaseProps extends PathProps {
ref?: Ref<Path>
}
class AnimatedSvgPathBase extends Component<AnimatedSvgPathBaseProps> {
#_component: Path | null = null
setNativeProps = (props: AnimatedSvgPathBaseProps = {}) => {
this.#_component && this.#_component.setNativeProps(props)
}
render() {
return (
<Path
ref={(component) => (this.#_component = component)}
{...this.props}
/>
)
}
}
const AnimatedSvgPath = AnimatedSvg(AnimatedSvgPathBase)
export default AnimatedSvgPath
================================================
FILE: components/AnimatedSVGPath/index.tsx
================================================
import React, { useEffect, useState } from 'react'
import Svg, { PathProps } from 'react-native-svg'
import { Animated, Dimensions, Easing } from 'react-native'
import { svgPathProperties } from 'svg-path-properties'
import Path from '../AnimatedSVG'
const {
height: windowHeight,
width: windowWidth,
} = Dimensions.get('window')
export interface AnimatedSVGPathProps {
d: string
strokeColor?: PathProps[`stroke`]
strokeWidth?: PathProps[`strokeWidth`]
strokeLinecap?: PathProps[`strokeLinecap`]
easing?: Animated.TimingAnimationConfig[`easing`]
fill?: PathProps[`fill`]
duration?: number
height?: number
delay?: number
width?: number
scale?: number
loop?: boolean
transform?: PathProps[`transform`]
reverse?: boolean
rewind?: boolean
strokeDasharray?: string[]
pause?: number
}
const AnimatedSVGPath: React.FC<AnimatedSVGPathProps> = ({
d,
strokeColor = 'black',
strokeWidth = 1,
strokeLinecap = 'butt',
easing = Easing.inOut(Easing.ease),
duration = 1000,
delay = 1000,
fill = 'none',
scale = 1,
loop = true,
transform = '',
reverse = false,
rewind = false,
height = windowHeight,
width = windowWidth,
strokeDasharray,
pause = 0,
}) => {
let loopCount = 0
const properties = new svgPathProperties(d)
const length = properties.getTotalLength()
const strokeDashoffset = new Animated.Value(!reverse ? length : 0)
const animate = () => {
strokeDashoffset.setValue(!reverse ? length : 0)
const animationsSequence = [].concat(
[
Animated.delay(delay * (loopCount ? 2 : 1)),
Animated.timing(strokeDashoffset, {
toValue: !reverse ? 0 : length,
duration: duration,
useNativeDriver: true,
easing: typeof easing === 'function' ? easing : Easing[easing],
}),
],
pause
? [Animated.delay(pause)]
: [],
rewind
? [
Animated.timing(strokeDashoffset, {
toValue: !reverse ? length : 0,
duration: duration,
useNativeDriver: true,
easing: typeof easing === 'function' ? easing : Easing[easing],
}),
]
: []
)
Animated.sequence(animationsSequence).start(() => {
if (loop) {
animate()
}
})
loopCount = 1
}
useEffect(() => {
animate()
}, [])
return (
<Svg height={height * scale + 5} width={width * scale + 5}>
<Path
strokeDasharray={strokeDasharray || [length, length]}
strokeDashoffset={strokeDashoffset}
strokeWidth={strokeWidth}
strokeLinecap={strokeLinecap}
stroke={strokeColor}
scale={scale}
fill={fill}
transform={transform}
d={d}
/>
</Svg>
)
}
export default AnimatedSVGPath
================================================
FILE: components/AnimatedSVGPaths/index.tsx
================================================
import React from 'react'
import Svg, { PathProps } from 'react-native-svg'
import { Dimensions } from 'react-native'
import Path from '../AnimatedPath'
import { AnimatedSVGPathProps } from '../AnimatedSVGPath'
const {
height: windowHeight,
width: windowWidth,
} = Dimensions.get('window')
export type CustomSVGPathProps = AnimatedSVGPathProps
export interface AnimatedSvgPathsProps {
ds?: string[],
customSVGProps?: CustomSVGPathProps[]
strokeColor?: PathProps[`stroke`]
strokeWidth?: PathProps[`strokeWidth`]
fill?: PathProps[`fill`]
duration?: number
height?: number
delay?: number
width?: number
scale?: number
loop?: boolean
rewind?: boolean
pause?: number
sequential?: boolean
}
const AnimatedSVGPaths: React.FC<AnimatedSvgPathsProps> = ({
ds = [],
customSVGProps = [],
strokeColor = 'black',
strokeWidth = 1,
duration = 1000,
delay = 1000,
fill = 'none',
scale = 1,
loop = true,
rewind = false,
pause = 0,
sequential = false,
height = windowHeight,
width = windowWidth,
}) => {
const svgArray = ds.length > 0
? ds
: customSVGProps.length > 0
? customSVGProps
: []
const svgPaths = svgArray.map((d: string | CustomSVGPathProps, index: number) => {
let pathProps: AnimatedSVGPathProps & {
key: number
} = {
key: index,
strokeWidth,
strokeColor,
duration,
delay: sequential ? index * delay : delay,
scale,
fill,
loop,
rewind,
d: '',
height,
width,
}
if (typeof d === 'string') {
pathProps.d = d
} else {
Object.assign(pathProps, d)
}
if (sequential) {
pathProps.pause = (svgArray.length - 1 - index) * delay * (rewind ? 2 : 1)
}
if (pause) {
pathProps.pause = pause
}
return (
<Path {...pathProps}/>
)
})
return (
<Svg height={height * scale + 5} width={width * scale + 5}>
{svgPaths}
</Svg>
)
}
export default AnimatedSVGPaths
================================================
FILE: examples/HiSVG/d.js
================================================
export default 'M366.2,204.2c-9.8,0-15-5.6-15-15.1V77.2h-85v28h19.5c9.8,0,8.5,2.1,8.5,11.6v72.4c0,9.5,0.5,15.1-9.3,15.1H277h-20.7c-8.5,0-14.2-4.1-14.2-12.9V52.4c0-8.5,5.7-12.3,14.2-12.3h18.8v-28h-127v28h18.1c8.5,0,9.9,2.1,9.9,8.9v56.1h-75V53.4c0-11.5,8.6-13.3,17-13.3h11v-28H2.2v28h26c8.5,0,12,2.1,12,7.9v142.2c0,8.5-3.6,13.9-12,13.9h-21v33h122v-33h-11c-8.5,0-17-4.1-17-12.2v-57.8h75v58.4c0,9.1-1.4,11.6-9.9,11.6h-18.1v33h122.9h5.9h102.2v-33H366.2z';
================================================
FILE: examples/HiSVG/index.js
================================================
import React, {
Component,
} from 'react';
import {
View,
} from 'react-native';
import AnimatedSVGPath from '../../components/AnimatedSVGPath';
import d from './d';
export default class HiSVG extends Component {
render() {
return (
<View style={{ marginTop: 40 }}>
<AnimatedSVGPath
strokeColor={"pink"}
duration={2500}
strokeWidth={5}
height={400}
width={400}
scale={0.5}
delay={500}
d={d}
/>
</View>
);
}
}
================================================
FILE: examples/IngenuityPreloaderSVG/d.js
================================================
export default preloaderLines = [
'M498.465,1L1,288.188',
'M600.984,288.188L103.53,1',
'M462.988,601V1',
'M107.176,601l493.651-285',
'M1,315.91L494.822,601',
'M139,1v600',
'M1,322.827L558.475,1',
'M43.537,1L601,322.844',
'M432.986,1v600l0,0',
'M600.828,281.357L600.828,281.357L47.172,601',
'M554.82,601L1,281.268',
'M169,601V1',
'M300.581,288.648c-33.954,0-61.577-27.622-61.577-61.574c0-33.952,27.624-61.573,61.577-61.573c33.952,0,61.573,27.622,61.573,61.573C362.154,261.026,334.533,288.648,300.581,288.648z',
'M300.582,318.592c-50.466,0-91.522-41.055-91.522-91.518c0-50.463,41.058-91.517,91.522-91.517c50.462,0,91.517,41.055,91.517,91.517C392.099,277.537,351.044,318.592,300.582,318.592z',
'M299.774,441.807c-33.953,0-61.576-27.625-61.576-61.58c0-33.953,27.623-61.578,61.576-61.578c33.954,0,61.575,27.625,61.575,61.578C361.351,414.182,333.728,441.807,299.774,441.807z',
'M299.774,471.807c-50.494,0-91.574-41.083-91.574-91.58c0-50.496,41.08-91.578,91.574-91.578c50.495,0,91.571,41.082,91.571,91.578C391.349,430.724,350.269,471.807,299.774,471.807z',
'M1,303.598h599.828',
'M303,1v601',
'M1,1h599.828v600H1V1z'
];
================================================
FILE: examples/IngenuityPreloaderSVG/index.js
================================================
import React, {
Component
} from 'react';
import {
View
} from 'react-native';
import ds from './d';
import AnimatedSVGPaths from '../../components/AnimatedSVGPaths';
class IngenuityPreloaderSVG extends Component {
render() {
return (
<View>
<AnimatedSVGPaths
strokeColor={"orange"}
strokeWidth={2.5}
duration={1000}
height={600}
width={600}
scale={0.5}
delay={100}
ds={ds}
/>
</View>
);
}
}
export default IngenuityPreloaderSVG;
================================================
FILE: index.js
================================================
import AnimatedSVGPath from './components/AnimatedSVGPath';
import AnimatedSVGPaths from './components/AnimatedSVGPaths';
/* Export ==================================================================== */
module.exports = {
AnimatedSVGPath: AnimatedSVGPath,
AnimatedSVGPaths: AnimatedSVGPaths,
}
================================================
FILE: package.json
================================================
{
"name": "react-native-svg-animations",
"version": "1.0.0",
"description": "SVG Animations wrapper for react-native.",
"main": "index.js",
"directories": {
"example": "examples"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git@github.com:73R3WY/react-native-svg-animations.git"
},
"keywords": [
"react-native",
"svg",
"animations"
],
"author": "Jeremy Patrick Pacabis <jeremy@ingenuity.ph> (https://ingenuity.ph)",
"license": "ISC",
"bugs": {
"url": "https://github.com/73R3WY/react-native-svg-animations/issues"
},
"homepage": "https://github.com/73R3WY/react-native-svg-animations",
"dependencies": {
"color": "^4.2.3",
"react-native-svg": "^14.1.0",
"svg-path-properties": "^1.0.3"
},
"devDependencies": {
"@babel/core": "^7.20.0"
}
}
================================================
FILE: utils/AnimatedListener/index.js
================================================
// @flow
import { Animated } from 'react-native';
type ResultArray = {
values: any[],
listeners: any[]
};
type ResultObject = {
values: Object,
listeners: Object
};
type ResultAnimated = {
values: number | string,
listeners: string
};
type ResultOther = {
values: any
};
type RecResult = ResultArray | ResultObject;
type Result = RecResult | ResultAnimated | ResultOther;
export type AnimatedListener = Result;
type AnimatedValue = typeof Animated.Value | typeof Animated.Interpolation;
/**
* Iterates object keys to find Animated objects to add listeners to and returns an object of values and listeners. The values field will be shaped identically to the passed in object with the Animated objects replaced with the value from __getValue at the time it was called.
*/
function recursiveListen(
object,
accumulator: ResultArray | ResultObject,
accIndex: number,
cb: Function
): RecResult {
if (Array.isArray(object)) {
let initialValue = new AnimatedTracker([], []);
return object.reduce(
(previousValue, currentValue, currentIndex, array) => {
const result = recursiveListen(
currentValue,
previousValue.values,
currentIndex,
cb
);
previousValue.values[currentIndex] = result.values;
previousValue.listeners[currentIndex] = result.listeners;
return previousValue;
},
initialValue
);
}
if (
object instanceof Animated.Value ||
object instanceof Animated.Interpolation
) {
const id = addListenerForAnimated(object, accumulator, accIndex, cb);
return new AnimatedTracker(
object.__getValue(),
new ListenerTracker(id, object)
);
}
if (typeof object === 'object' && object !== null) {
let initialValue = new AnimatedTracker({}, {});
return Object.keys(object).reduce((previousValue, currentValue) => {
const value = object[currentValue];
const result = recursiveListen(
value,
previousValue.values,
currentValue,
cb
);
previousValue.values[currentValue] = result.values;
previousValue.listeners[currentValue] = result.listeners;
return previousValue;
}, initialValue);
}
return new AnimatedTracker(object);
}
function addListenerForAnimated(
animatedValue: AnimatedValue,
accumulator: ResultArray | ResultObject,
accIndex: number,
cb: Function
) {
const addListener = animatedValue._parent
? animatedValue._parent.addListener.bind(animatedValue._parent)
: animatedValue.addListener.bind(animatedValue);
const interpolator = animatedValue._interpolation;
let callback = e => e;
if (interpolator) {
callback = _value => interpolator(_value);
}
let prevCallback = callback;
callback = e => {
const value = prevCallback(e.value);
accumulator[accIndex] = value;
cb();
};
return addListener(callback);
}
export function listen(object: Object | any[], cb: Function): Result {
return recursiveListen(object, null, null, cb);
}
/**
* Iterates object keys to find a ListenerTracker with an Animated object and listener id to remove
*/
function recursiveRemoveListeners(listeners: Object | any[]) {
if (Array.isArray(listeners)) {
listeners.forEach((listener, index) =>
recursiveRemoveListeners(listener)
);
} else if (listeners instanceof ListenerTracker) {
const id = listeners.id;
const object = listeners.object;
object._parent
? object._parent.removeListener(id)
: object.removeListener(id);
} else if (typeof listeners === 'object' && listeners !== null) {
Object.keys(listeners).forEach(key =>
recursiveRemoveListeners(listeners[key])
);
}
}
export function removeListeners(listeners: Object | any[] | AnimatedTracker) {
if (listeners instanceof AnimatedTracker) {
recursiveRemoveListeners(listeners.listeners);
} else {
recursiveRemoveListeners(listeners);
}
}
class ListenerTracker {
id: string;
object: Animated.Value | Animated.Interpolation;
constructor(id: string, object: Animated.Value | Animated.Interpolation) {
this.id = id;
this.object = object;
}
}
class AnimatedTracker {
values: any[] | Object | number | string;
listeners: ?(ListenerTracker | ListenerTracker[] | Object);
constructor(
values?: any[] | Object | string,
listeners?: ListenerTracker | ListenerTracker[] | Object
) {
this.values = values;
this.listeners = listeners;
}
}
================================================
FILE: utils/AnimatedSVG/index.js
================================================
import {
Animated,
} from 'react-native';
import AnimatedSVGBrush from '../AnimatedSVGBrush';
import AnimatedSVGPropString from '../AnimatedSVGPropString';
import AnimatedSVGState from '../AnimatedSVGState';
import AnimatedSVGTransform from '../AnimatedSVGTransform';
function AnimatedSVG (Component, {
state, propString, keepXY
} = {}) {
Component = AnimatedSVGState(Component, state);
Component = AnimatedSVGBrush(Component);
Component = AnimatedSVGPropString(Component, propString);
Component = AnimatedSVGTransform(Component, { keepXY });
Component = Animated.createAnimatedComponent(Component);
return Component;
}
export default AnimatedSVG;
================================================
FILE: utils/AnimatedSVGBrush/index.js
================================================
// @flow
/**
* Problem: Color props such as fill and stroke cannot be animated through setNativeProps. They can be animated through state, but setNativeProps is better
* Solution: Extract brush, update propList (does not seem to do anything but to be consistent extractProps I did it anyway)
*/
import React, { Component } from 'react';
import Color from 'color';
import pick from 'lodash/pick';
import { listen, removeListeners } from '../AnimatedListener';
import type { AnimatedListener } from '../AnimatedListener';
// https://github.com/react-native-community/react-native-svg/blob/master/lib/extract/extractBrush.js
const patternReg = /^url\(#(.+?)\)$/;
function extractBrush(colorOrBrush) {
if (colorOrBrush === 'none' || !colorOrBrush) {
return null;
}
try {
let matched = colorOrBrush.match(patternReg);
// brush
if (matched) {
return [1, matched[1]];
//todo:
} else { // solid color
let [r, g, b, a = 1] = Color(colorOrBrush).rgb().array();
return [0, r / 255, g / 255, b / 255, a];
}
} catch (err) {
console.warn(`"${colorOrBrush}" is not a valid color or brush`);
return null;
}
}
const fillKeys = ['fill', 'fillOpacity', 'fillRule'];
const strokeKeys = [
'stroke',
'strokeWidth',
'strokeOpacity',
'strokeDasharray',
'strokeDashoffset',
'strokeLinecap',
'strokeLinejoin',
'strokeMiterlimit'
];
function getPropList(nextProps, prevProps) {
let propList = [];
fillKeys.forEach(name => {
if (nextProps.hasOwnProperty(name) || prevProps.hasOwnProperty(name)) {
propList.push(name);
}
});
strokeKeys.forEach(name => {
if (nextProps.hasOwnProperty(name) || prevProps.hasOwnProperty(name)) {
propList.push(name);
}
});
return propList;
}
const separator = /\s*,\s*/;
function getStrokeDasharray(strokeDasharray) {
if (typeof strokeDasharray === 'string') {
strokeDasharray = strokeDasharray.split(separator).map(dash => +dash);
}
if (strokeDasharray && strokeDasharray.length === 1) {
strokeDasharray.push(strokeDasharray[0]);
}
// have to clone array to allow animation with mutable changes
return strokeDasharray ? [...strokeDasharray] : strokeDasharray;
}
function getStrokeDashoffset(nextProps, prevProps) {
const strokeDasharray =
getStrokeDasharray(nextProps.strokeDasharray) ||
getStrokeDasharray(prevProps.strokeDasharray);
return strokeDasharray
? +nextProps.strokeDashoffset || +prevProps.strokeDashoffset || 0
: null;
}
const KEYS = ['fill', 'stroke', 'strokeDashoffset'];
export default function SvgBrushFix(WrappedComponent) {
return class extends Component {
strokeDasharray: AnimatedListener;
constructor(props) {
super(props);
this.updateCache(props);
this.strokeDasharray = listen(props.strokeDasharray, _ =>
this.setNativeProps({ updateStrokeDasharray: true })
);
}
updateCache(props) {
this.prevProps = pick(props, KEYS);
}
setNativeProps = props => {
props.propList = getPropList(props, this.prevProps);
if (props.fill) {
props.fill = extractBrush(props.fill);
}
if (props.stroke) {
props.stroke = extractBrush(props.stroke);
}
if (props.updateStrokeDasharray || props.strokeDashoffset) {
props.strokeDasharray = getStrokeDasharray(
this.strokeDasharray.values
);
props.strokeDashoffset = getStrokeDashoffset(
props,
this.prevProps
);
}
this._component && this._component.setNativeProps(props);
};
componentDidUpdate(prevProps) {
this.updateCache(prevProps);
if (this.props.strokeDasharray !== prevProps.strokeDasharray) {
removeListeners(this.strokeDasharray);
this.strokeDasharray = listen(prevProps.strokeDasharray, _ =>
this.setNativeProps({ updateStrokeDasharray: true }));
}
}
componentWillUnmount() {
removeListeners(this.strokeDasharray);
}
render() {
const strokeDasharray = getStrokeDasharray(
this.strokeDasharray.values
);
return (
<WrappedComponent
ref={component => (this._component = component)}
{...this.props}
strokeDasharray={strokeDasharray}
/>
);
}
};
}
================================================
FILE: utils/AnimatedSVGPropString/index.js
================================================
import React, { Component } from 'react';
/**
* Problem: Props cannot be animated, too many times you have to do val.toString() in setNativeProps
* Solution: Use a higher order component to do that for you
*/
const KEYS = [
'strokeWidth', 'strokeOpacity', 'fillOpacity'
];
export default function SvgPropStringFix(WrappedComponent, propKeys = []) {
propKeys = [...KEYS, ...propKeys];
return class extends Component {
setNativeProps = (props) => {
propKeys.reduce((acc, key) => {
const val = props[key];
if (val != null) {
acc[key] = val.toString();
}
return acc;
}, props);
this._component && this._component.setNativeProps(props);
}
render() {
return (
<WrappedComponent
ref={component => (this._component = component)}
{...this.props}
/>
);
}
};
}
================================================
FILE: utils/AnimatedSVGState/index.js
================================================
import React, { Component } from 'react';
import omit from 'lodash/omit';
/**
* Problem: Some props cannot be animated through setNativeProps
* Solution: Use state for those and use setNativeProps for the rest
*/
function createState(props, keys) {
return keys.reduce((acc, key) => {
const value = props[key];
if (value != null) {
acc[key] = value;
}
return acc;
}, {});
}
export default function SvgStateFix(WrappedComponent, propToStateKeys = [], { cancelSetNativeProps } = {}) {
return class extends Component {
state = createState(this.props, propToStateKeys);
setNativeProps = (props) => {
if (!cancelSetNativeProps) {
const nativeProps = omit(props, propToStateKeys);
this._component && this._component.setNativeProps(nativeProps);
}
const newState = createState(props, propToStateKeys);
this.setState(newState);
}
render() {
return (
<WrappedComponent
ref={component => (this._component = component)}
{...this.props}
{...this.state}
/>
);
}
};
}
================================================
FILE: utils/AnimatedSVGTransform/index.js
================================================
import React, { Component } from 'react';
import omit from 'lodash/omit';
import pick from 'lodash/pick';
import Matrix2D from '../Matrix2D';
/**
* Problem: Animating transform props is not easy
* Solution: Use Animated.ValueXY in universal props, create matrix when ever transform props change, use setNativeProps
* BUG: Using Animated.ValueXY does not work for some reason
*/
// https://github.com/react-native-community/react-native-svg/blob/master/lib/extract/extractTransform.js
// modified to deal with nextProps and prevProps situations with both static props on this.props and dynamic props passing through setNativeProps
function _universal2axis(universal, axisX, axisY, defaultValue) {
let x;
let y;
if (typeof universal === 'object') {
x = universal.x;
y = universal.y;
} else if (typeof universal === 'number') {
x = y = universal;
}
axisX = +axisX;
if (!isNaN(axisX)) {
x = axisX;
}
axisY = +axisY;
if (!isNaN(axisY)) {
y = axisY;
}
return [x || defaultValue || 0, y || defaultValue || 0];
}
function universal2axis(key, nextProps, prevProps, defaultValue) {
let [nextX, nextY] = _universal2axis(nextProps[key], nextProps[key + 'X'], nextProps[key + 'Y']);
let [prevX, prevY] = _universal2axis(prevProps[key], prevProps[key + 'X'], prevProps[key + 'Y'], defaultValue);
return [nextX || prevX, nextY || prevY];
}
function createTransformObject(nextProps, prevProps) {
const [originX, originY] = universal2axis('origin', nextProps, prevProps);
const [scaleX, scaleY] = universal2axis('scale', nextProps, prevProps, 1);
const [skewX, skewY] = universal2axis('skew', nextProps, prevProps);
const [translateX, translateY] = universal2axis('translate', nextProps, prevProps);
const x = translateX || nextProps.x || prevProps.x || 0;
const y = translateY || nextProps.y || prevProps.y || 0;
const rotation = +nextProps.rotation || +nextProps.rotate || +prevProps.rotation || +prevProps.rotate || 0;
return {
rotation,
originX,
originY,
scaleX,
scaleY,
skewX,
skewY,
x,
y
};
}
let pooledMatrix = new Matrix2D();
function createTransformMatrix(props, transform) {
pooledMatrix.reset();
appendTransform(props);
if (transform) {
appendTransform(transform);
}
return pooledMatrix.toArray();
}
function appendTransform(transform) {
pooledMatrix
.appendTransform(
transform.x + transform.originX,
transform.y + transform.originY,
transform.scaleX, transform.scaleY,
transform.rotation,
transform.skewX,
transform.skewY,
transform.originX,
transform.originY
);
}
const UNIVERSAL_KEYS = ['origin', 'scale', 'skew', 'translate'];
const KEYS = [...UNIVERSAL_KEYS, 'originX', 'originY', 'scaleX', 'scaleY', 'skewX', 'skewY', 'translateX', 'translateY', 'x', 'y', 'rotation', 'rotate'];
export default function SvgTransformFix(WrappedComponent, { keepXY } = {}) {
return class extends Component {
prevProps = pick(this.props, KEYS)
setNativeProps = (props) => {
// if some transform key exists in props, create a new matrix
if (KEYS.some((key, index) => props[key] != null)) {
const matrix = createTransformMatrix(createTransformObject(props, this.prevProps));
let x, y;
// some components like rect need these still
if (keepXY) {
x = props.x && props.x.toString();
y = props.y && props.y.toString();
}
// remove transform props since they are moved into matrix prop
props = omit(props, KEYS);
props.matrix = matrix;
props.x = x;
props.y = y;
// cache dynamic prop values since you need them to generate an accurate matrix
this.prevProps = Object.assign(this.prevProps, pick(props, KEYS));
}
this._component && this._component.setNativeProps(props);
}
render() {
return (
<WrappedComponent
ref={component => (this._component = component)}
{...this.props}
/>
);
}
};
}
================================================
FILE: utils/Matrix2D/index.ts
================================================
/**
* based on
* https://github.com/CreateJS/EaselJS/blob/631cdffb85eff9413dab43b4676f059b4232d291/src/easeljs/geom/Matrix2D.js
*/
const DEG_TO_RAD = Math.PI / 180
/**
* Represents an affine transformation matrix, and provides tools for constructing and concatenating matrices.
*
* This matrix can be visualized as:
*
* [ a c tx
* b d ty
* 0 0 1 ]
*
* Note the locations of b and c.
*
* @class Matrix2D
* @param {Number} [a=1] Specifies the a property for the new matrix.
* @param {Number} [b=0] Specifies the b property for the new matrix.
* @param {Number} [c=0] Specifies the c property for the new matrix.
* @param {Number} [d=1] Specifies the d property for the new matrix.
* @param {Number} [tx=0] Specifies the tx property for the new matrix.
* @param {Number} [ty=0] Specifies the ty property for the new matrix.
* @constructor
**/
export default class Matrix2D {
constructor(a, b, c, d, tx, ty) {
this.setTransform(a, b, c, d, tx, ty)
// public properties:
// assigned in the setValues method.
/**
* Position (0, 0) in a 3x3 affine transformation matrix.
* @property a
* @type Number
**/
/**
* Position (0, 1) in a 3x3 affine transformation matrix.
* @property b
* @type Number
**/
/**
* Position (1, 0) in a 3x3 affine transformation matrix.
* @property c
* @type Number
**/
/**
* Position (1, 1) in a 3x3 affine transformation matrix.
* @property d
* @type Number
**/
/**
* Position (2, 0) in a 3x3 affine transformation matrix.
* @property tx
* @type Number
**/
/**
* Position (2, 1) in a 3x3 affine transformation matrix.
* @property ty
* @type Number
**/
}
/**
* Set current matrix to new absolute matrix.
* @method setTransform
* @param {Number} [a=1] Specifies the a property for the new matrix.
* @param {Number} [b=0] Specifies the b property for the new matrix.
* @param {Number} [c=0] Specifies the c property for the new matrix.
* @param {Number} [d=1] Specifies the d property for the new matrix.
* @param {Number} [tx=0] Specifies the tx property for the new matrix.
* @param {Number} [ty=0] Specifies the ty property for the new matrix.
* @return {Matrix2D} This instance. Useful for chaining method calls.
*/
setTransform = function(a, b, c, d, tx, ty) {
/*eslint eqeqeq:0*/
this.a = a == null ? 1 : a
this.b = b || 0
this.c = c || 0
this.d = b == null ? 1 : d
this.tx = tx || 0
this.ty = ty || 0
return this
}
/**
* Reset current matrix to an identity matrix.
* @method reset
* @return {Matrix2D} This matrix. Useful for chaining method calls.
**/
reset = function() {
this.a = this.d = 1
this.b = this.c = this.tx = this.ty = 0
return this
}
/**
* Returns an array with current matrix values.
* @method toArray
* @return {Array} an array with current matrix values.
**/
toArray = function() {
return [this.a, this.b, this.c, this.d, this.tx, this.ty]
}
/**
* Copies all properties from the specified matrix to this matrix.
* @method copy
* @param {Matrix2D} matrix The matrix to copy properties from.
* @return {Matrix2D} This matrix. Useful for chaining method calls.
*/
copy = function(matrix) {
return this.setTransform(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty)
}
/**
* Clones current instance and returning a new matrix.
* @method clone
* @return {Matrix2D} a clone of the Matrix2D instance.
**/
clone = function() {
return new Matrix2D(this.a, this.b, this.c, this.d, this.tx, this.ty)
}
/**
* Prepends the specified matrix properties to this matrix.
* This is the equivalent of multiplying `(specified matrix) * (this matrix)`.
* All parameters are required.
* @method prepend
* @param {Number} a
* @param {Number} b
* @param {Number} c
* @param {Number} d
* @param {Number} tx
* @param {Number} ty
* @return {Matrix2D} This matrix. Useful for chaining method calls.
**/
prepend = function(a, b, c, d, tx, ty) {
var a1 = this.a
var c1 = this.c
var tx1 = this.tx
this.a = a * a1 + c * this.b
this.b = b * a1 + d * this.b
this.c = a * c1 + c * this.d
this.d = b * c1 + d * this.d
this.tx = a * tx1 + c * this.ty + tx
this.ty = b * tx1 + d * this.ty + ty
return this
}
/**
* Appends the specified matrix properties to this matrix. All parameters are required.
* This is the equivalent of multiplying `(this matrix) * (specified matrix)`.
* @method append
* @param {Number} a
* @param {Number} b
* @param {Number} c
* @param {Number} d
* @param {Number} tx
* @param {Number} ty
* @return {Matrix2D} This matrix. Useful for chaining method calls.
**/
append = function(a, b, c, d, tx, ty) {
var a1 = this.a
var b1 = this.b
var c1 = this.c
var d1 = this.d
if (a !== 1 || b !== 0 || c !== 0 || d !== 1) {
this.a = a1 * a + c1 * b
this.b = b1 * a + d1 * b
this.c = a1 * c + c1 * d
this.d = b1 * c + d1 * d
}
this.tx = a1 * tx + c1 * ty + this.tx
this.ty = b1 * tx + d1 * ty + this.ty
return this
}
/**
* Generates matrix properties from the specified display object transform properties, and appends them to this matrix.
* For example, you can use this to generate a matrix representing the transformations of a display object:
*
* var mtx = new createjs.Matrix2D()
* mtx.appendTransform(o.x, o.y, o.scaleX, o.scaleY, o.rotation)
* @method appendTransform
* @param {Number} x
* @param {Number} y
* @param {Number} scaleX
* @param {Number} scaleY
* @param {Number} rotation
* @param {Number} skewX
* @param {Number} skewY
* @param {Number} regX Optional.
* @param {Number} regY Optional.
* @return {Matrix2D} This matrix. Useful for chaining method calls.
**/
appendTransform = function(x, y, scaleX, scaleY, rotation, skewX, skewY, regX, regY) {
if (rotation % 360) {
var r = rotation * DEG_TO_RAD
var cos = Math.cos(r)
var sin = Math.sin(r)
} else {
cos = 1
sin = 0
}
if (skewX || skewY) {
// TODO: can this be combined into a single append operation?
skewX *= DEG_TO_RAD
skewY *= DEG_TO_RAD
this.append(Math.cos(skewY), Math.sin(skewY), -Math.sin(skewX), Math.cos(skewX), x, y)
this.append(cos * scaleX, sin * scaleX, -sin * scaleY, cos * scaleY, 0, 0)
} else {
this.append(cos * scaleX, sin * scaleX, -sin * scaleY, cos * scaleY, x, y)
}
if (regX || regY) {
// append the registration offset:
this.tx -= regX * this.a + regY * this.c
this.ty -= regX * this.b + regY * this.d
}
return this
}
/**
* Generates matrix properties from the specified display object transform properties, and prepends them to this matrix.
* For example, you could calculate the combined transformation for a child object using:
*
* var o = myDisplayObject
* var mtx = new createjs.Matrix2D()
* do {
* // prepend each parent's transformation in turn:
* mtx.prependTransform(o.x, o.y, o.scaleX, o.scaleY, o.rotation, o.skewX, o.skewY, o.regX, o.regY)
* } while (o = o.parent)
*
* Note that the above example would not account for {{#crossLink "DisplayObject/transformMatrix:property"}}{{/crossLink}}
* values. See {{#crossLink "Matrix2D/prependMatrix"}}{{/crossLink}} for an example that does.
* @method prependTransform
* @param {Number} x
* @param {Number} y
* @param {Number} scaleX
* @param {Number} scaleY
* @param {Number} rotation
* @param {Number} skewX
* @param {Number} skewY
* @param {Number} regX Optional.
* @param {Number} regY Optional.
* @return {Matrix2D} This matrix. Useful for chaining method calls.
**/
prependTransform = function(x, y, scaleX, scaleY, rotation, skewX, skewY, regX, regY) {
if (rotation % 360) {
var r = rotation * DEG_TO_RAD
var cos = Math.cos(r)
var sin = Math.sin(r)
} else {
cos = 1
sin = 0
}
if (regX || regY) {
// prepend the registration offset:
this.tx -= regX
this.ty -= regY
}
if (skewX || skewY) {
// TODO: can this be combined into a single prepend operation?
skewX *= DEG_TO_RAD
skewY *= DEG_TO_RAD
this.prepend(cos * scaleX, sin * scaleX, -sin * scaleY, cos * scaleY, 0, 0)
this.prepend(Math.cos(skewY), Math.sin(skewY), -Math.sin(skewX), Math.cos(skewX), x, y)
} else {
this.prepend(cos * scaleX, sin * scaleX, -sin * scaleY, cos * scaleY, x, y)
}
return this
}
}
gitextract_nvt6lyug/
├── .gitignore
├── LICENSE
├── README.md
├── components/
│ ├── AnimatedPath/
│ │ └── index.tsx
│ ├── AnimatedSVG/
│ │ └── index.tsx
│ ├── AnimatedSVGPath/
│ │ └── index.tsx
│ └── AnimatedSVGPaths/
│ └── index.tsx
├── examples/
│ ├── HiSVG/
│ │ ├── d.js
│ │ └── index.js
│ └── IngenuityPreloaderSVG/
│ ├── d.js
│ └── index.js
├── index.js
├── package.json
└── utils/
├── AnimatedListener/
│ └── index.js
├── AnimatedSVG/
│ └── index.js
├── AnimatedSVGBrush/
│ └── index.js
├── AnimatedSVGPropString/
│ └── index.js
├── AnimatedSVGState/
│ └── index.js
├── AnimatedSVGTransform/
│ └── index.js
└── Matrix2D/
└── index.ts
SYMBOL INDEX (37 symbols across 13 files)
FILE: components/AnimatedPath/index.tsx
type AnimatedSvgPathProps (line 7) | interface AnimatedSvgPathProps {
FILE: components/AnimatedSVG/index.tsx
type AnimatedSvgPathBaseProps (line 6) | interface AnimatedSvgPathBaseProps extends PathProps {
class AnimatedSvgPathBase (line 10) | class AnimatedSvgPathBase extends Component<AnimatedSvgPathBaseProps> {
method render (line 17) | render() {
FILE: components/AnimatedSVGPath/index.tsx
type AnimatedSVGPathProps (line 12) | interface AnimatedSVGPathProps {
FILE: components/AnimatedSVGPaths/index.tsx
type CustomSVGPathProps (line 12) | type CustomSVGPathProps = AnimatedSVGPathProps
type AnimatedSvgPathsProps (line 14) | interface AnimatedSvgPathsProps {
FILE: examples/HiSVG/index.js
class HiSVG (line 11) | class HiSVG extends Component {
method render (line 12) | render() {
FILE: examples/IngenuityPreloaderSVG/index.js
class IngenuityPreloaderSVG (line 10) | class IngenuityPreloaderSVG extends Component {
method render (line 11) | render() {
FILE: utils/AnimatedListener/index.js
function recursiveListen (line 33) | function recursiveListen(
function addListenerForAnimated (line 83) | function addListenerForAnimated(
method if (line 113) | if (Array.isArray(listeners)) {
method constructor (line 140) | constructor(id: string, object: Animated.Value | Animated.Interpolation) {
FILE: utils/AnimatedSVG/index.js
function AnimatedSVG (line 9) | function AnimatedSVG (Component, {
FILE: utils/AnimatedSVGBrush/index.js
function extractBrush (line 15) | function extractBrush(colorOrBrush) {
function getPropList (line 47) | function getPropList(nextProps, prevProps) {
function getStrokeDasharray (line 63) | function getStrokeDasharray(strokeDasharray) {
function getStrokeDashoffset (line 74) | function getStrokeDashoffset(nextProps, prevProps) {
constant KEYS (line 83) | const KEYS = ['fill', 'stroke', 'strokeDashoffset'];
function SvgBrushFix (line 85) | function SvgBrushFix(WrappedComponent) {
FILE: utils/AnimatedSVGPropString/index.js
constant KEYS (line 8) | const KEYS = [
function SvgPropStringFix (line 12) | function SvgPropStringFix(WrappedComponent, propKeys = []) {
FILE: utils/AnimatedSVGState/index.js
function createState (line 9) | function createState(props, keys) {
function SvgStateFix (line 19) | function SvgStateFix(WrappedComponent, propToStateKeys = [], { cancelSet...
FILE: utils/AnimatedSVGTransform/index.js
function _universal2axis (line 14) | function _universal2axis(universal, axisX, axisY, defaultValue) {
function universal2axis (line 37) | function universal2axis(key, nextProps, prevProps, defaultValue) {
function createTransformObject (line 43) | function createTransformObject(nextProps, prevProps) {
function createTransformMatrix (line 66) | function createTransformMatrix(props, transform) {
function appendTransform (line 77) | function appendTransform(transform) {
constant UNIVERSAL_KEYS (line 91) | const UNIVERSAL_KEYS = ['origin', 'scale', 'skew', 'translate'];
constant KEYS (line 92) | const KEYS = [...UNIVERSAL_KEYS, 'originX', 'originY', 'scaleX', 'scaleY...
function SvgTransformFix (line 94) | function SvgTransformFix(WrappedComponent, { keepXY } = {}) {
FILE: utils/Matrix2D/index.ts
constant DEG_TO_RAD (line 5) | const DEG_TO_RAD = Math.PI / 180
class Matrix2D (line 27) | class Matrix2D {
method constructor (line 28) | constructor(a, b, c, d, tx, ty) {
Condensed preview — 20 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (49K chars).
[
{
"path": ".gitignore",
"chars": 8,
"preview": ".vscode/"
},
{
"path": "LICENSE",
"chars": 1079,
"preview": "MIT License\n\nCopyright (c) 2017 Jeremy Patrick Pacabis\n\nPermission is hereby granted, free of charge, to any person obta"
},
{
"path": "README.md",
"chars": 9087,
"preview": "# react-native-svg-animations [](https://badge.f"
},
{
"path": "components/AnimatedPath/index.tsx",
"chars": 2347,
"preview": "import React, { useEffect, useState } from 'react'\nimport { Animated, Easing } from 'react-native'\nimport { svgPathPrope"
},
{
"path": "components/AnimatedSVG/index.tsx",
"chars": 696,
"preview": "import React, { Component, Ref } from 'react'\nimport { Path, PathProps } from 'react-native-svg'\n\nimport AnimatedSvg fro"
},
{
"path": "components/AnimatedSVGPath/index.tsx",
"chars": 2798,
"preview": "import React, { useEffect, useState } from 'react'\nimport Svg, { PathProps } from 'react-native-svg'\nimport { Animated, "
},
{
"path": "components/AnimatedSVGPaths/index.tsx",
"chars": 2003,
"preview": "import React from 'react'\nimport Svg, { PathProps } from 'react-native-svg'\nimport { Dimensions } from 'react-native'\nim"
},
{
"path": "examples/HiSVG/d.js",
"chars": 450,
"preview": "export default 'M366.2,204.2c-9.8,0-15-5.6-15-15.1V77.2h-85v28h19.5c9.8,0,8.5,2.1,8.5,11.6v72.4c0,9.5,0.5,15.1-9.3,15.1H"
},
{
"path": "examples/HiSVG/index.js",
"chars": 534,
"preview": "import React, {\n Component,\n} from 'react';\nimport {\n View,\n} from 'react-native';\n\nimport AnimatedSVGPath from '../.."
},
{
"path": "examples/IngenuityPreloaderSVG/d.js",
"chars": 1150,
"preview": "export default preloaderLines = [\n 'M498.465,1L1,288.188',\n 'M600.984,288.188L103.53,1',\n 'M462.988,601V1',\n 'M107.1"
},
{
"path": "examples/IngenuityPreloaderSVG/index.js",
"chars": 555,
"preview": "import React, {\n Component\n} from 'react';\nimport {\n View\n} from 'react-native';\nimport ds from './d';\nimport Animated"
},
{
"path": "index.js",
"chars": 300,
"preview": "import AnimatedSVGPath from './components/AnimatedSVGPath';\nimport AnimatedSVGPaths from './components/AnimatedSVGPaths'"
},
{
"path": "package.json",
"chars": 896,
"preview": "{\n \"name\": \"react-native-svg-animations\",\n \"version\": \"1.0.0\",\n \"description\": \"SVG Animations wrapper for react-nati"
},
{
"path": "utils/AnimatedListener/index.js",
"chars": 4495,
"preview": "// @flow\nimport { Animated } from 'react-native';\n\ntype ResultArray = {\n values: any[],\n listeners: any[]\n};\n\ntype Res"
},
{
"path": "utils/AnimatedSVG/index.js",
"chars": 665,
"preview": "import {\n Animated,\n} from 'react-native';\nimport AnimatedSVGBrush from '../AnimatedSVGBrush';\nimport AnimatedSVGPropSt"
},
{
"path": "utils/AnimatedSVGBrush/index.js",
"chars": 4319,
"preview": "// @flow\n/**\n * Problem: Color props such as fill and stroke cannot be animated through setNativeProps. They can be anim"
},
{
"path": "utils/AnimatedSVGPropString/index.js",
"chars": 887,
"preview": "import React, { Component } from 'react';\n\n/**\n * Problem: Props cannot be animated, too many times you have to do val.t"
},
{
"path": "utils/AnimatedSVGState/index.js",
"chars": 1106,
"preview": "import React, { Component } from 'react';\nimport omit from 'lodash/omit';\n\n/**\n * Problem: Some props cannot be animated"
},
{
"path": "utils/AnimatedSVGTransform/index.js",
"chars": 4048,
"preview": "import React, { Component } from 'react';\nimport omit from 'lodash/omit';\nimport pick from 'lodash/pick';\nimport Matrix2"
},
{
"path": "utils/Matrix2D/index.ts",
"chars": 8826,
"preview": "/**\n * based on\n * https://github.com/CreateJS/EaselJS/blob/631cdffb85eff9413dab43b4676f059b4232d291/src/easeljs/geom/Ma"
}
]
About this extraction
This page contains the full source code of the 73R3WY/react-native-svg-animations GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 20 files (45.2 KB), approximately 13.4k tokens, and a symbol index with 37 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.