import Taro from '@tarojs/api' ; author leeenx
  class StyleSheet { constructor ( ) { this . $style = document . createElement ( 'style' ) ; } $style : HTMLStyleElement ; sheet ? : CSSStyleSheet | null ; appendStyleSheet = ( ) => { this . $style ?. setAttribute ( 'type' , 'text/css' ) ; this . $style ?. setAttribute ( 'data-type' , 'Taro' ) ; document . getElementsByTagName ( 'head' ) [ 0 ] . appendChild ( this . $style ) ; this . sheet = this . $style ?. sheet ; if ( this . sheet && ! ( 'insertRule' in this . sheet ) ) { console . warn ( '当前浏览器不支持 stylesheet.insertRule 接口' ) ; } } ; add = ( cssText , index = 0 ) => { if ( this . sheet === null ) { this . appendStyleSheet ( ) ; } this . sheet ?. insertRule ( cssText , index ) ; } ; } const styleSheet = new StyleSheet ( ) ; let TRANSITION_END = 'transitionend' ; let TRANSFORM = 'transform' ; const $detect = document . createElement ( 'div' ) ; $detect . style . cssText = '-webkit-animation-name:webkit;-moz-animation-name:moz;-ms-animation-name:ms;animation-name:standard;' ; if ( $detect . style [ 'animation-name' ] === 'standard' ) { TRANSITION_END = 'transitionend' ; TRANSFORM = 'transform' ; } else if ( $detect . style [ '-webkit-animation-name' ] === 'webkit' ) { TRANSITION_END = 'webkitTransitionEnd' ; TRANSFORM = '-webkit-transform' ; } else if ( $detect . style [ '-moz-animation-name' ] === 'moz' ) { TRANSITION_END = 'mozTransitionEnd' ; TRANSFORM = '-moz-transform' ; } else if ( $detect . style [ '-ms-animation-name' ] === 'ms' ) { TRANSITION_END = 'msTransitionEnd' ; TRANSFORM = '-ms-transform' ; } let animId = 0 ; interface IAnimationAttr { duration : number ; delay : number ; timingFunction : string ; transformOrigin : string ; } class Animation implements Taro . Animation { unit : string ; id : number ; DEFAULT : IAnimationAttr ; constructor ( { duration = 400 , delay = 0 , timingFunction = 'linear' , transformOrigin = '50% 50% 0' , unit = 'px' } = { } ) { this . setDefault ( duration , delay , timingFunction , transformOrigin ) ; this . unit = unit ; let animAttr = 'animation' ; this . id = ++ animId ; document . body . addEventListener ( TRANSITION_END , ( e ) => { const target = e . target as HTMLElement ; if ( target . getAttribute ( animAttr ) === null ) { animAttr = 'data-animation' ; } const animData = target . getAttribute ( animAttr ) ; if ( animData === null ) return ; const [ animName , animPath ] = animData . split ( '__' ) ; if ( animName === `taro-h5-poly-fill/${ this . id }/create-animation` ) { const [ animIndex , __stepIndex = 0 ] = animPath . split ( '--' ) ; const stepIndex = Number ( __stepIndex ) ; const animStepsCount = this . animationMap [ `${ animName }__${ animIndex }` ] ; const animStepsMaxIndex = animStepsCount - 1 ; if ( stepIndex < animStepsMaxIndex ) { target . setAttribute ( animAttr , `${ animName }__${ animIndex }--${ stepIndex + 1 }` ) ; if ( animAttr === 'animation' ) { target . setAttribute ( 'data-animation' , `${ animName }__${ animIndex }--${ stepIndex + 1 }` ) ; } } } } ) ; } transformUnit ( ... args ) { const ret = [ ] ; args . forEach ( each => { ret . push ( isNaN ( each ) ? each : `${ each }${ this . unit }` ) ; } ) ; return ret ; } setDefault ( duration , delay , timingFunction , transformOrigin ) { this . DEFAULT = { duration , delay , timingFunction , transformOrigin } ; } rules : string [ ] = [ ] ; transform = [ `${ TRANSFORM }:` ] ; steps : string [ ] = [ ] ; animationMap = { } ; animationMapCount = 0 ; matrix ( a , b , c , d , tx , ty ) { this . transform . push ( `matrix(${ a }, ${ b }, ${ c }, ${ d }, ${ tx }, ${ ty })` ) ; return this ; } matrix3d ( a1 , b1 , c1 , d1 , a2 , b2 , c2 , d2 , a3 , b3 , c3 , d3 , a4 , b4 , c4 , d4 ) { this . transform . push ( `matrix3d(${ a1 }, ${ b1 }, ${ c1 }, ${ d1 }, ${ a2 }, ${ b2 }, ${ c2 }, ${ d2 }, ${ a3 }, ${ b3 }, ${ c3 }, ${ d3 }, ${ a4 }, ${ b4 }, ${ c4 }, ${ d4 })` ) ; return this ; } rotate ( angle ) { this . transform . push ( `rotate(${ angle }deg)` ) ; return this ; } rotate3d ( x , y ? , z ? , angle ? ) { if ( typeof y !== 'number' ) { this . transform . push ( `rotate3d(${ x })` ) ; } else { this . transform . push ( `rotate3d(${ x }, ${ y || 0 }, ${ z || 0 }, ${ angle || 0 }deg)` ) ; } return this ; } rotateX ( angle ) { this . transform . push ( `rotateX(${ angle }deg)` ) ; return this ; } rotateY ( angle ) { this . transform . push ( `rotateY(${ angle }deg)` ) ; return this ; } rotateZ ( angle ) { this . transform . push ( `rotateZ(${ angle }deg)` ) ; return this ; } scale ( x , y ) { this . transform . push ( `scale(${ x }, ${ y })` ) ; return this ; } scale3d ( x , y , z ) { this . transform . push ( `scale3d(${ x }, ${ y }, ${ z })` ) ; return this ; } scaleX ( scale ) { this . transform . push ( `scaleX(${ scale })` ) ; return this ; } scaleY ( scale ) { this . transform . push ( `scaleY(${ scale })` ) ; return this ; } scaleZ ( scale ) { this . transform . push ( `scaleZ(${ scale })` ) ; return this ; } skew ( x , y ) { this . transform . push ( `skew(${ x }, ${ y })` ) ; return this ; } skewX ( angle ) { this . transform . push ( `skewX(${ angle })` ) ; return this ; } skewY ( angle ) { this . transform . push ( `skewY(${ angle })` ) ; return this ; } translate ( x , y ) { [ x , y ] = this . transformUnit ( x , y ) ; this . transform . push ( `translate(${ x }, ${ y })` ) ; return this ; } translate3d ( x , y , z ) { [ x , y , z ] = this . transformUnit ( x , y , z ) ; this . transform . push ( `translate3d(${ x }, ${ y }, ${ z })` ) ; return this ; } translateX ( translate ) { [ translate ] = this . transformUnit ( translate ) ; this . transform . push ( `translateX(${ translate })` ) ; return this ; } translateY ( translate ) { [ translate ] = this . transformUnit ( translate ) ; this . transform . push ( `translateY(${ translate })` ) ; return this ; } translateZ ( translate ) { [ translate ] = this . transformUnit ( translate ) ; this . transform . push ( `translateZ(${ translate })` ) ; return this ; } opacity ( value ) { this . rules . push ( `opacity: ${ value }` ) ; return this ; } backgroundColor ( value ) { this . rules . push ( `background-color: ${ value }` ) ; return this ; } width ( value ) { [ value ] = this . transformUnit ( value ) ; this . rules . push ( `width: ${ value }` ) ; return this ; } height ( value ) { [ value ] = this . transformUnit ( value ) ; this . rules . push ( `height: ${ value }` ) ; return this ; } top ( value ) { [ value ] = this . transformUnit ( value ) ; this . rules . push ( `top: ${ value }` ) ; return this ; } right ( value ) { [ value ] = this . transformUnit ( value ) ; this . rules . push ( `right: ${ value }` ) ; return this ; } bottom ( value ) { [ value ] = this . transformUnit ( value ) ; this . rules . push ( `bottom: ${ value }` ) ; return this ; } left ( value ) { [ value ] = this . transformUnit ( value ) ; this . rules . push ( `left: ${ value }` ) ; return this ; } step ( arg = { } ) { const { DEFAULT } = this ; const { duration = DEFAULT . duration , delay = DEFAULT . delay , timingFunction = DEFAULT . timingFunction , transformOrigin = DEFAULT . transformOrigin } = arg ; this . steps . push ( [ this . rules . map ( rule => `${ rule }!important` ) . join ( ';' ) , `${ this . transform . join ( ' ' ) }!important` , `${ TRANSFORM }-origin: ${ transformOrigin }` , `transition: all ${ duration }ms ${ timingFunction } ${ delay }ms` ] . filter ( item => item !== '' && item !== `${ TRANSFORM }:` ) . join ( ';' ) ) ; this . rules = [ ] ; this . transform = [ `${ TRANSFORM }:` ] ; return this as Taro . Animation ; } createAnimationData ( ) { const animIndex = `taro-h5-poly-fill/${ this . id }/create-animation__${ this . animationMapCount ++ }` ; this . animationMap [ animIndex ] = this . steps . length ; this . steps . forEach ( ( step , index ) => { const selector = index === 0 ? `[animation="${ animIndex }"], [data-animation="${ animIndex }"]` : `[animation="${ animIndex }--${ index }"], [data-animation="${ animIndex }--${ index }"]` ; styleSheet . add ( `${ selector } { ${ step } }` ) ; } ) ; this . steps = [ ] ; return animIndex ; } export ( ) { return this . createAnimationData ( ) as unknown as ReturnType < Taro . Animation [ 'export' ] > ; } } export const createAnimation = ( option ) => { return new Animation ( option ) ; } ;