UNPKG

react-native-painter

Version:
394 lines (317 loc) 15.4 kB
import React, { useRef } from 'react' import Attributes from './Constants' const getPosition = (arr,index,length)=>{ if(arr !== undefined){ return `${arr[index] * 100}%` } if(length > 0){ let l = length - 1 let sum = 1 / l return index == l ? "100%" : `${(index*sum) * 100}%` } return "0%" } const RadialGradientWeb = React.forwardRef((props,ref)=>{ const myRef = ref ? ref : useRef() const { x, y, w, h, cx, cy, rx, ry, positions, colors, painterKey, viewBox, align, aspect, isChildMask, fill, fillRule, fillOpacity, stroke, strokeOpacity, strokeWidth, strokeStart, strokeEnd, dashArray, dashClipValue, strokeCap, strokeJoin, strokeMiter, shadow, shadowRadius, shadowOffset, shadowOffsetX, shadowOffsetY, shadowPercentageValue, shadowRect, mask, opacity, translateZ, transX, transY, transPercentageValue, rot, rotO, rotOx, rotOy, rotPercentageValue, sc, scX, scY, scO, scOx, scOy, scPercentageValue, style, ...rest } = props //MARK: Props const lx = x === undefined ? 0 : x const ly = y === undefined ? 0 : y const lw = w === undefined ? 0 : w const lh = h === undefined ? 0 : h const centerX = cx === undefined ? 0.5 : cx const centerY = cy === undefined ? 0.5 : cy const radiusX = rx === undefined ? 0.5 : rx const radiusY = ry === undefined ? 0.5 : ry const colorsArr = colors === undefined ? ['white','black'] : colors //MARK : Paintable const isMasking = isChildMask === undefined ? false : isChildMask const mk = mask === undefined ? "" : mask const op = opacity === undefined ? "" : `${opacity}` const dx = transX === undefined ? 0 : transX const dy = transY === undefined ? 0 : transY const scaleX = sc === undefined ? ( scX === undefined ? 1 : scX) : sc const scaleY = sc === undefined ? (scY === undefined ? 1 : scY) : sc const scaleOX = scO === undefined ? ( scOx === undefined ? 0 : scOx) : scO const scaleOY = scO === undefined ? (scOy === undefined ? 0 : scOy) : scO const rotation = rot === undefined ? 0 : rot const rotationOX = rotO === undefined ? ( rotOx === undefined ? 0 : rotOx) : rotO const rotationOY = rotO === undefined ? (rotOy === undefined ? 0 : rotOy) : rotO const transform = `rotate(${rotation} ${rotationOX} ${rotationOY}) translate(${scaleOX} ${scaleOY}) scale(${scaleX} ${scaleY}) translate(${-scaleOX} ${-scaleOY}) translate(${dx} ${dy})` const userKey = painterKey === undefined ? "" : painterKey const keyElemet = Attributes.elements.prefix const keyGradient = `${keyElemet}${Attributes.elements.gradient}${userKey}` return( <g ref={myRef} opacity={op} mask={`url(#${mk})`} transform={transform} curtransform={`${rotation} ${rotationOX} ${rotationOY} ${scaleX} ${scaleY} ${scaleOX} ${scaleOY} ${dx} ${dy}`} curcolors={`${colorsArr.join(';-;')}`} curpositions={`${positions === undefined ? "" : positions.join(' ')}`} curradiusx={radiusX} curradiusy={radiusY} > <svg style={{width:'100%',height:'100%',overflow:'visible'}} viewBox={viewBox} preserveAspectRatio={`${align} ${aspect}`}> <defs> <radialGradient id={keyGradient} gradientUnits="objectBoundingBox" gradientTransform={`translate(0.5 0.5) scale(1,${radiusY/radiusX}) translate(-0.5 -0.5)`} cx={centerX} cy={centerY} r={radiusX} > {colorsArr.map((color,index)=>{ return( <stop key={index} offset={getPosition(positions,index,colorsArr.length)} stopColor={color} /> ) })} </radialGradient> </defs> <rect id={`${keyElemet}${Attributes.elements.fill}${userKey}`} x={lx} y={ly} width={lw} height={lh} fill={`url(#${keyGradient})`}/> </svg> </g> ) }) class RadialGradient extends React.PureComponent{ constructor(props){ super(props) this.currentProps = Object.assign({},props) this.keyElemet = Attributes.elements.prefix this.myRef = React.createRef() this.setNativeProps = this.setNativeProps.bind(this) this.updateProp = this.updateProp.bind(this) this.handleProps = this.handleProps.bind(this) this.handleCommonProps = this.handleCommonProps.bind(this) this.updateAttribute = this.updateAttribute.bind(this) this.getAttribute = this.getAttribute.bind(this) this.getElement = this.getElement.bind(this) } //direct manipulation, experimental setNativeProps(object){ if(this.myRef.current && this.props.painterKey){ let keys = Object.keys(object) for(var i = 0; i < keys.length;i++){ let k = keys[i] let value = object[k] this.updateProp(k,value) } let isStyle = object.hasOwnProperty('style') if(isStyle){ let keysStyle = Object.keys(object.style) for(var i = 0; i < keysStyle.length;i++){ let k = keysStyle[i] let value = object.style[k] this.updateProp(k,value) } } } } updateProp(k,value){ let isProp = this.handleProps(k,value) if(!isProp){ this.handleCommonProps(k,value) } } handleProps(k,value){ switch(k){ case "x": case "y": case "w": case "h": let elfill = this.getElement(Attributes.elements.fill) this.updateAttribute(Attributes[k],value,elfill) return true case "cx": case "cy": this.updateAttribute(Attributes[k],value,this.getElement(Attributes.elements.gradient)) return true case "rx": this.updateAttribute(Attributes.r,value,this.getElement(Attributes.elements.gradient)) let curRy = parseFloat(this.getAttribute(Attributes.curRadiusY,this.myRef.current)) this.updateAttribute(Attributes.gradientTransform ,`translate(0.5 0.5) scale(1,${curRy/value}) translate(-0.5 -0.5)`, this.getElement(Attributes.elements.gradient)) this.updateAttribute(Attributes.curRadiusX,value,this.myRef.current) return true case "ry": let curRx = parseFloat(this.getAttribute(Attributes.curRadiusX,this.myRef.current)) this.updateAttribute(Attributes.gradientTransform ,`translate(0.5 0.5) scale(1,${value/curRx}) translate(-0.5 -0.5)`, this.getElement(Attributes.elements.gradient)) this.updateAttribute(Attributes.curRadiusY,value,this.myRef.current) return true case "colors": let gra = this.getElement(Attributes.elements.gradient) gra.innerHTML = "" if(value.length > 0){ let curPo = this.getAttribute(Attributes.curPositions,this.myRef.current) let pos = curPo.length >= 1 ? curPo.split(' ') : undefined let html = "" for(var i = 0; i < value.length ; i++){ let c = value[i] html += `<stop offset="${getPosition(pos,i,value.length)}" stop-color="${c}" /> \n` } gra.innerHTML = html this.updateAttribute(Attributes.curColors,value.join(';-;'),this.myRef.current) } return true case "positions": let elG = this.getElement(Attributes.elements.gradient) let curColors = this.getAttribute(Attributes.curColors,this.myRef.current) let cols = curColors.length >= 1 ? curColors.split(';-;') : [] elG.innerHTML = "" if(cols.length > 0){ let html = "" for(var i = 0; i < cols.length ; i++){ let c = cols[i] html += `<stop offset="${getPosition(value,i,cols.length)}" stop-color="${c}" /> \n` } elG.innerHTML = html this.updateAttribute(Attributes.curPositions,value.join(' '),this.myRef.current) } return true } return false } handleCommonProps(k,value){ if(k.includes('fill')){ }else if(k.includes('stroke')){ }else if(k.includes('shadow')){ }else if(k === 'opacity'){ this.updateAttribute(Attributes[k],value,this.myRef.current) }else if(k === 'mask'){ this.updateAttribute(Attributes[k],`url(#${value})`,this.myRef.current) }else if(k === 'dashArray'){ }else if(k === 'dashClipValue'){ }//transform else{ var container = this.myRef.current let t = this.getAttribute(Attributes.curTransform,container).split(' ') var valueT = "" var currT = "" switch(k){ case "transX": valueT = `rotate(${t[0]} ${t[1]} ${t[2]}) translate(${t[5]} ${t[6]}) scale(${t[3]} ${t[4]}) translate(${-t[5]} ${-t[6]}) translate(${value} ${t[8]})` currT = `${t[0]} ${t[1]} ${t[2]} ${t[3]} ${t[4]} ${t[5]} ${t[6]} ${value} ${t[8]}` break; case "transY": valueT = `rotate(${t[0]} ${t[1]} ${t[2]}) translate(${t[5]} ${t[6]}) scale(${t[3]} ${t[4]}) translate(${-t[5]} ${-t[6]}) translate(${t[7]} ${value})` currT = `${t[0]} ${t[1]} ${t[2]} ${t[3]} ${t[4]} ${t[5]} ${t[6]} ${t[7]} ${value}` break; case "rot": valueT = `rotate(${value} ${t[1]} ${t[2]}) translate(${t[5]} ${t[6]}) scale(${t[3]} ${t[4]}) translate(${-t[5]} ${-t[6]}) translate(${t[7]} ${t[8]})` currT = `${value} ${t[1]} ${t[2]} ${t[3]} ${t[4]} ${t[5]} ${t[6]} ${t[7]} ${t[8]}` break; case "rotO": valueT = `rotate(${t[0]} ${value} ${value}) translate(${t[5]} ${t[6]}) scale(${t[3]} ${t[4]}) translate(${-t[5]} ${-t[6]}) translate(${t[7]} ${t[8]})` currT = `${t[0]} ${value} ${value} ${t[3]} ${t[4]} ${t[5]} ${t[6]} ${t[7]} ${t[8]}` break; case "rotOx": valueT = `rotate(${t[0]} ${value} ${t[2]}) translate(${t[5]} ${t[6]}) scale(${t[3]} ${t[4]}) translate(${-t[5]} ${-t[6]}) translate(${t[7]} ${t[8]})` currT = `${t[0]} ${value} ${t[2]} ${t[3]} ${t[4]} ${t[5]} ${t[6]} ${t[7]} ${t[8]}` break; case "rotOy": valueT = `rotate(${t[0]} ${t[1]} ${value}) translate(${t[5]} ${t[6]}) scale(${t[3]} ${t[4]}) translate(${-t[5]} ${-t[6]}) translate(${t[7]} ${t[8]})` currT = `${t[0]} ${t[1]} ${value} ${t[3]} ${t[4]} ${t[5]} ${t[6]} ${t[7]} ${t[8]}` break; case "sc": valueT = `rotate(${t[0]} ${t[1]} ${t[2]}) translate(${t[5]} ${t[6]}) scale(${value} ${value}) translate(${-t[5]} ${-t[6]}) translate(${t[7]} ${t[8]})` currT = `${t[0]} ${t[1]} ${t[2]} ${value} ${value} ${t[5]} ${t[6]} ${t[7]} ${t[8]}` break; case "scX": valueT = `rotate(${t[0]} ${t[1]} ${t[2]}) translate(${t[5]} ${t[6]}) scale(${value} ${t[4]}) translate(${-t[5]} ${-t[6]}) translate(${t[7]} ${t[8]})` currT = `${t[0]} ${t[1]} ${t[2]} ${value} ${t[4]} ${t[5]} ${t[6]} ${t[7]} ${t[8]}` break; case "scY": valueT = `rotate(${t[0]} ${t[1]} ${t[2]}) translate(${t[5]} ${t[6]}) scale(${t[3]} ${value}) translate(${-t[5]} ${-t[6]}) translate(${t[7]} ${t[8]})` currT = `${t[0]} ${t[1]} ${t[2]} ${t[3]} ${value} ${t[5]} ${t[6]} ${t[7]} ${t[8]}` break; case "scO": valueT = `rotate(${t[0]} ${t[1]} ${t[2]}) translate(${value} ${value}) scale(${t[3]} ${t[4]}) translate(${-value} ${-value}) translate(${t[7]} ${t[8]})` currT = `${t[0]} ${t[1]} ${t[2]} ${t[3]} ${t[4]} ${value} ${value} ${t[7]} ${t[8]}` break; case "scOx": valueT = `rotate(${t[0]} ${t[1]} ${t[2]}) translate(${value} ${t[6]}) scale(${t[3]} ${t[4]}) translate(${-value} ${-t[6]}) translate(${t[7]} ${t[8]})` currT = `${t[0]} ${t[1]} ${t[2]} ${t[3]} ${t[4]} ${value} ${t[6]} ${t[7]} ${t[8]}` break; case "scOy": valueT = `rotate(${t[0]} ${t[1]} ${t[2]}) translate(${t[5]} ${value}) scale(${t[3]} ${t[4]}) translate(${-t[5]} ${-value}) translate(${t[7]} ${t[8]})` currT = `${t[0]} ${t[1]} ${t[2]} ${t[3]} ${t[4]} ${t[5]} ${value} ${t[7]} ${t[8]}` break; } if(currT.length > 0 && valueT.length > 0 ){ this.updateAttribute(Attributes.transform,valueT,container) this.updateAttribute(Attributes.curTransform,currT,container) } } } getElement(id){ return this.myRef.current.querySelector(`#${this.keyElemet}${id}${this.props.painterKey}`) } updateAttribute(k,value,element){ if(element) element.setAttribute(k,value) } getAttribute(k,element){ if(element) { let v = element.getAttribute(k) return v ? v : "" } return "" } render(){ return <RadialGradientWeb ref={this.myRef} {...this.props} /> } } export default RadialGradient