react-native-svg
Version:
SVG library for react-native
78 lines (68 loc) • 2.12 kB
JavaScript
import React, { Children } from 'react';
import extractColor from './extractColor';
import extractOpacity from './extractOpacity';
import extractTransform from './extractTransform';
import units from '../units';
const percentReg = /^([+\-]?\d+(?:\.\d+)?(?:[eE][+\-]?\d+)?)(%?)$/;
function percentToFloat(percent) {
if (typeof percent === 'number') {
return percent;
}
if (
typeof percent === 'object' &&
typeof percent.__getAnimatedValue === 'function'
) {
return percent.__getAnimatedValue();
}
const matched = typeof percent === 'string' && percent.match(percentReg);
if (!matched) {
console.warn(`"${percent}" is not a valid number or percentage string.`);
return 0;
}
return matched[2] ? matched[1] / 100 : +matched[1];
}
const offsetComparator = (object, other) => object[0] - other[0];
export default function extractGradient(props, parent) {
const { id, children, gradientTransform, transform, gradientUnits } = props;
if (!id) {
return null;
}
const stops = [];
const childArray = Children.map(children, child =>
React.cloneElement(child, {
parent,
}),
);
const l = childArray.length;
for (let i = 0; i < l; i++) {
const {
props: { offset, stopColor, stopOpacity },
} = childArray[i];
const offsetNumber = percentToFloat(offset || 0);
const color = stopColor && extractColor(stopColor);
if (typeof color !== 'number' || isNaN(offsetNumber)) {
console.warn(
`"${stopColor}" is not a valid color or "${offset}" is not a valid offset`,
);
continue;
}
const alpha = Math.round(extractOpacity(stopOpacity) * 255);
stops.push([offsetNumber, (color & 0x00ffffff) | (alpha << 24)]);
}
stops.sort(offsetComparator);
const gradient = [];
const k = stops.length;
for (let j = 0; j < k; j++) {
const s = stops[j];
gradient.push(s[0], s[1]);
}
return {
name: id,
gradient,
children: childArray,
gradientUnits: units[gradientUnits] || 0,
gradientTransform: extractTransform(
gradientTransform || transform || props,
),
};
}