Skip to content

Commit

Permalink
refactor(): refactor animation in classes (fabricjs#8297)
Browse files Browse the repository at this point in the history
Co-authored-by: kristpregracke <kpregracke@redfoundry.com>
Co-authored-by: ShaMan123 <shacharnen@gmail.com>
Co-authored-by: Shachar <34343793+ShaMan123@users.noreply.github.com>
Co-authored-by: Andrea Bogazzi <andreabogazzi79@gmail.com>
  • Loading branch information
5 people authored and frankrousseau committed Jan 6, 2023
1 parent ec4357c commit 4051296
Show file tree
Hide file tree
Showing 26 changed files with 966 additions and 563 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## [next]

- refactor(TS): `animate` and `AnimationRegistry` to classes [#8297](https://github.com/fabricjs/fabric.js/pull/8297)
BREAKING:
- return animation instance from animate instead of a cancel function and remove `findAnimationByXXX` from `AnimationRegistry`
- change `animateColor` signature to match `animate`, removed `colorEasing`
- fix(Object Stacking): 🔙 refactor logic to support Group 🔝
- chore(TS): migrate Group/ActiveSelection [#8455](https://github.com/fabricjs/fabric.js/pull/8455)
- chore(TS): Migrate smaller mixins to classes (dataurl and serialization ) [#8542](https://github.com/fabricjs/fabric.js/pull/8542)
Expand Down
2 changes: 1 addition & 1 deletion src/canvas/static_canvas.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
TToCanvasElementOptions,
TValidToObjectMethod,
} from '../typedefs';
import { cancelAnimFrame, requestAnimFrame } from '../util/animate';
import { cancelAnimFrame, requestAnimFrame } from '../util/animation';
import {
cleanUpJsdomNode,
getElementOffset,
Expand Down
120 changes: 56 additions & 64 deletions src/color/color.class.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,66 @@
//@ts-nocheck
import { ColorNameMap } from './color_map';
import { reHSLa, reHex, reRGBa } from './constants';
import { hue2rgb, hexify } from './util';

type TColorSource = [number, number, number];
/**
* RGB format
*/
export type TRGBColorSource = [red: number, green: number, blue: number];

/**
* RGBA format
*/
export type TRGBAColorSource = [
red: number,
green: number,
blue: number,
alpha: number
];

type TColorAlphaSource = [number, number, number, number];
export type TColorArg = string | TRGBColorSource | TRGBAColorSource | Color;

/**
* @class Color common color operations
* @tutorial {@link http://fabricjs.com/fabric-intro-part-2/#colors colors}
*/
export class Color {
private _source: TColorAlphaSource;
private _source: TRGBAColorSource;

/**
*
* @param {string} [color] optional in hex or rgb(a) or hsl format or from known color list
*/
constructor(color?: string) {
constructor(color?: TColorArg) {
if (!color) {
// we default to black as canvas does
this.setSource([0, 0, 0, 1]);
} else if (color instanceof Color) {
this.setSource([...color._source]);
} else if (Array.isArray(color)) {
const [r, g, b, a = 1] = color;
this.setSource([r, g, b, a]);
} else {
this._tryParsingColor(color);
this.setSource(this._tryParsingColor(color));
}
}

/**
* @private
* @param {string} [color] Color value to parse
* @returns {TRGBAColorSource}
*/
_tryParsingColor(color?: string) {
protected _tryParsingColor(color: string) {
if (color in ColorNameMap) {
color = ColorNameMap[color];
color = ColorNameMap[color as keyof typeof ColorNameMap];
}

const source =
color === 'transparent'
? [255, 255, 255, 0]
: Color.sourceFromHex(color) ||
return color === 'transparent'
? ([255, 255, 255, 0] as TRGBAColorSource)
: Color.sourceFromHex(color) ||
Color.sourceFromRgb(color) ||
Color.sourceFromHsl(color) || [0, 0, 0, 1]; // color is not recognize let's default to black as canvas does

if (source) {
this.setSource(source);
}
Color.sourceFromHsl(color) ||
// color is not recognized
// we default to black as canvas does
([0, 0, 0, 1] as TRGBAColorSource);
}

/**
Expand All @@ -53,16 +69,16 @@ export class Color {
* @param {Number} r Red color value
* @param {Number} g Green color value
* @param {Number} b Blue color value
* @return {TColorSource} Hsl color
* @return {TRGBColorSource} Hsl color
*/
_rgbToHsl(r: number, g: number, b: number): TColorSource {
_rgbToHsl(r: number, g: number, b: number): TRGBColorSource {
r /= 255;
g /= 255;
b /= 255;
const maxValue = Math.max(r, g, b),
minValue = Math.min(r, g, b);

let h, s;
let h!: number, s: number;
const l = (maxValue + minValue) / 2;

if (maxValue === minValue) {
Expand All @@ -89,17 +105,17 @@ export class Color {

/**
* Returns source of this color (where source is an array representation; ex: [200, 200, 100, 1])
* @return {TColorAlphaSource}
* @return {TRGBAColorSource}
*/
getSource() {
return this._source;
}

/**
* Sets source of this color (where source is an array representation; ex: [200, 200, 100, 1])
* @param {TColorAlphaSource} source
* @param {TRGBAColorSource} source
*/
setSource(source: TColorAlphaSource) {
setSource(source: TRGBAColorSource) {
this._source = source;
}

Expand Down Expand Up @@ -223,20 +239,14 @@ export class Color {
otherColor = new Color(otherColor);
}

const result = [],
alpha = this.getAlpha(),
const [r, g, b, alpha] = this.getSource(),
otherAlpha = 0.5,
source = this.getSource(),
otherSource = otherColor.getSource();

for (let i = 0; i < 3; i++) {
result.push(
Math.round(source[i] * (1 - otherAlpha) + otherSource[i] * otherAlpha)
otherSource = otherColor.getSource(),
[R, G, B] = [r, g, b].map((value, index) =>
Math.round(value * (1 - otherAlpha) + otherSource[index] * otherAlpha)
);
}

result[3] = alpha;
this.setSource(result);
this.setSource([R, G, B, alpha]);
return this;
}

Expand All @@ -259,16 +269,16 @@ export class Color {
* @return {Color}
*/
static fromRgba(color: string): Color {
return Color.fromSource(Color.sourceFromRgb(color));
return new Color(Color.sourceFromRgb(color));
}

/**
* Returns array representation (ex: [100, 100, 200, 1]) of a color that's in RGB or RGBA format
* @memberOf Color
* @param {String} color Color value ex: rgb(0-255,0-255,0-255), rgb(0%-100%,0%-100%,0%-100%)
* @return {TColorAlphaSource | undefined} source
* @return {TRGBAColorSource | undefined} source
*/
static sourceFromRgb(color: string): TColorAlphaSource | undefined {
static sourceFromRgb(color: string): TRGBAColorSource | undefined {
const match = color.match(reRGBa);
if (match) {
const r =
Expand All @@ -281,12 +291,7 @@ export class Color {
(parseInt(match[3], 10) / (/%$/.test(match[3]) ? 100 : 1)) *
(/%$/.test(match[3]) ? 255 : 1);

return [
parseInt(r, 10),
parseInt(g, 10),
parseInt(b, 10),
match[4] ? parseFloat(match[4]) : 1,
];
return [r, g, b, match[4] ? parseFloat(match[4]) : 1];
}
}

Expand All @@ -309,18 +314,18 @@ export class Color {
* @return {Color}
*/
static fromHsla(color: string): Color {
return Color.fromSource(Color.sourceFromHsl(color));
return new Color(Color.sourceFromHsl(color));
}

/**
* Returns array representation (ex: [100, 100, 200, 1]) of a color that's in HSL or HSLA format.
* Adapted from <a href="https://rawgithub.com/mjijackson/mjijackson.github.com/master/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript.html">https://github.com/mjijackson</a>
* @memberOf Color
* @param {String} color Color value ex: hsl(0-360,0%-100%,0%-100%) or hsla(0-360,0%-100%,0%-100%, 0-1)
* @return {TColorAlphaSource | undefined} source
* @return {TRGBAColorSource | undefined} source
* @see http://http://www.w3.org/TR/css3-color/#hsl-color
*/
static sourceFromHsl(color: string): TColorAlphaSource | undefined {
static sourceFromHsl(color: string): TRGBAColorSource | undefined {
const match = color.match(reHSLa);
if (!match) {
return;
Expand All @@ -329,7 +334,7 @@ export class Color {
const h = (((parseFloat(match[1]) % 360) + 360) % 360) / 360,
s = parseFloat(match[2]) / (/%$/.test(match[2]) ? 100 : 1),
l = parseFloat(match[3]) / (/%$/.test(match[3]) ? 100 : 1);
let r, g, b;
let r: number, g: number, b: number;

if (s === 0) {
r = g = b = l;
Expand Down Expand Up @@ -358,17 +363,17 @@ export class Color {
* @return {Color}
*/
static fromHex(color: string): Color {
return Color.fromSource(Color.sourceFromHex(color));
return new Color(Color.sourceFromHex(color));
}

/**
* Returns array representation (ex: [100, 100, 200, 1]) of a color that's in HEX format
* @static
* @memberOf Color
* @param {String} color ex: FF5555 or FF5544CC (RGBa)
* @return {TColorAlphaSource | undefined} source
* @return {TRGBAColorSource | undefined} source
*/
static sourceFromHex(color: string): TColorAlphaSource | undefined {
static sourceFromHex(color: string): TRGBAColorSource | undefined {
if (color.match(reHex)) {
const value = color.slice(color.indexOf('#') + 1),
isShortNotation = value.length === 3 || value.length === 4,
Expand Down Expand Up @@ -396,17 +401,4 @@ export class Color {
];
}
}

/**
* Returns new color object, when given color in array representation (ex: [200, 100, 100, 0.5])
* @static
* @memberOf Color
* @param {TColorSource | TColorAlphaSource} source
* @return {Color}
*/
static fromSource(source: TColorSource | TColorAlphaSource): Color {
const oColor = new Color();
oColor.setSource(source);
return oColor;
}
}
5 changes: 1 addition & 4 deletions src/color/util.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/**
* @private
* @param {Number} p
* @param {Number} q
* @param {Number} t
Expand All @@ -25,9 +24,7 @@ export function hue2rgb(p: number, q: number, t: number): number {
}

/**
* Convert a [0, 255] value to hex
* @param value
* @returns
* Convert a value ∈ [0, 255] to hex
*/
export function hexify(value: number) {
const hexValue = value.toString(16).toUpperCase();
Expand Down

0 comments on commit 4051296

Please sign in to comment.