UNPKG

fabric

Version:

Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.

75 lines (71 loc) 2.17 kB
import { Color } from '../../color/Color'; import type { TRGBAColorSource } from '../../color/typedefs'; import { halfPI } from '../../constants'; import { capValue } from '../misc/capValue'; import { AnimationBase } from './AnimationBase'; import type { ColorAnimationOptions, TEasingFunction, TOnAnimationChangeCallback, } from './types'; const defaultColorEasing: TEasingFunction = ( timeElapsed, startValue, byValue, duration, ) => { const durationProgress = 1 - Math.cos((timeElapsed / duration) * halfPI); return startValue + byValue * durationProgress; }; const wrapColorCallback = <R>( callback?: TOnAnimationChangeCallback<string, R>, ) => callback && ((rgba: TRGBAColorSource, valueProgress: number, durationProgress: number) => callback(new Color(rgba).toRgba(), valueProgress, durationProgress)); export class ColorAnimation extends AnimationBase<TRGBAColorSource> { constructor({ startValue, endValue, easing = defaultColorEasing, onChange, onComplete, abort, ...options }: ColorAnimationOptions) { const startColor = new Color(startValue).getSource(); const endColor = new Color(endValue).getSource(); super({ ...options, startValue: startColor, byValue: endColor.map( (value, i) => value - startColor[i], ) as TRGBAColorSource, easing, onChange: wrapColorCallback(onChange), onComplete: wrapColorCallback(onComplete), abort: wrapColorCallback(abort), }); } protected calculate(timeElapsed: number) { const [r, g, b, a] = this.startValue.map((value, i) => this.easing(timeElapsed, value, this.byValue[i], this.duration, i), ) as TRGBAColorSource; const value = [ ...[r, g, b].map(Math.round), capValue(0, a, 1), ] as TRGBAColorSource; return { value, valueProgress: // to correctly calculate the change ratio we must find a changed value value .map((p, i) => this.byValue[i] !== 0 ? Math.abs((p - this.startValue[i]) / this.byValue[i]) : 0, ) .find((p) => p !== 0) || 0, }; } }