Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(): BREAKING Animation removing byValue, removing fxStraigthen. #8547

Merged
merged 29 commits into from
Jan 9, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
1cdfea3
small removals
asturur Dec 30, 2022
2fe7cbb
small removals
asturur Dec 30, 2022
47f3cfe
fix tests
asturur Dec 30, 2022
1cdd49d
added parkinglot
asturur Dec 30, 2022
fe59b48
renames and color easing as a const
asturur Dec 30, 2022
a73bf6d
prettier and changelog
asturur Dec 30, 2022
6b66b47
prettier again
asturur Dec 30, 2022
86dc5be
Merge branch 'master' into small-animation-preferences
asturur Jan 1, 2023
9cca498
merged conflicts
asturur Jan 3, 2023
7687271
better comments
asturur Jan 3, 2023
2c7b22c
removed by Value
asturur Jan 3, 2023
cd52d71
prettier
asturur Jan 3, 2023
64c968e
removed misc.ts
asturur Jan 3, 2023
dd3c2a0
Update CHANGELOG.md
asturur Jan 3, 2023
b17f989
Merge branch 'master' into small-animation-preferences
asturur Jan 6, 2023
5a72663
Update test/unit/animation.js
asturur Jan 6, 2023
c23dce3
simpler types
ShaMan123 Jan 7, 2023
0dd3a08
Update animation.ts
ShaMan123 Jan 7, 2023
85bd8ee
fix(): animation types by overload
ShaMan123 Jan 7, 2023
2c5c818
Merge branch 'master' into small-animation-preferences
ShaMan123 Jan 7, 2023
ff05bc3
fix(): make types align with logic
ShaMan123 Jan 7, 2023
aba89e2
future proofing: use freeze instead of concat
ShaMan123 Jan 7, 2023
b50b98f
Update AnimationBase.ts
ShaMan123 Jan 7, 2023
0c0e746
Update animation.js
ShaMan123 Jan 7, 2023
ef30290
Update animation.js
ShaMan123 Jan 7, 2023
25605ce
fix(): `changeRatio` for opacity anim
ShaMan123 Jan 8, 2023
1541b5a
rename: changeRatio => valueProgress
ShaMan123 Jan 8, 2023
5eef243
Update animation.js
ShaMan123 Jan 8, 2023
1201289
Merge branch 'master' into small-animation-preferences
asturur Jan 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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/animation';
import { cancelAnimFrame, requestAnimFrame } from '../util/animation/AnimationFrameProvider';
import {
cleanUpJsdomNode,
getElementOffset,
Expand Down
58 changes: 58 additions & 0 deletions src/parkinglot/straighten.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// @ts-nocheck
import { noop } from "../constants";
import { FabricObject } from "../shapes/Object/FabricObject";
import { TDegree } from "../typedefs";
import { animate } from "../util/animation/animate";

Object.assign(FabricObject.prototype, {
/**
* @private
* @return {Number} angle value
*/
_getAngleValueForStraighten(this: FabricObject) {
const angle = this.angle % 360;
if (angle > 0) {
return Math.round((angle - 1) / 90) * 90;
}
return Math.round(angle / 90) * 90;
},

/**
* Straightens an object (rotating it from current angle to one of 0, 90, 180, 270, etc. depending on which is closer)
*/
straighten(this: FabricObject) {
this.rotate(this._getAngleValueForStraighten());
},

/**
* Same as {@link straighten} but with animation
* @param {Object} callbacks Object with callback functions
* @param {Function} [callbacks.onComplete] Invoked on completion
* @param {Function} [callbacks.onChange] Invoked on every step of animation
*/
fxStraighten(
this: FabricObject,
callbacks: {
onChange?(value: TDegree): any;
onComplete?(): any;
} = {}
) {
const onComplete = callbacks.onComplete || noop,
onChange = callbacks.onChange || noop;

return animate({
target: this,
startValue: this.angle,
endValue: this._getAngleValueForStraighten(),
duration: this.FX_DURATION,
onChange: (value: TDegree) => {
this.rotate(value);
onChange(value);
},
onComplete: () => {
this.setCoords();
onComplete();
},
});
}
});
146 changes: 20 additions & 126 deletions src/shapes/Object/AnimatableObject.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { TColorArg } from '../../color/color.class';
import { noop } from '../../constants';
import { ObjectEvents } from '../../EventTypeDefs';
import { TDegree } from '../../typedefs';
import {
animate,
animateColor,
AnimationOptions,
ColorAnimationOptions,
} from '../../util/animation';
} from '../../util/animation/animate';
import type { AnimationOptions, ColorAnimationOptions } from '../../util/animation/types';
import { ArrayAnimation } from '../../util/animation/ArrayAnimation';
import type { ColorAnimation } from '../../util/animation/ColorAnimation';
import type { ValueAnimation } from '../../util/animation/ValueAnimation';
import { StackedObject } from './StackedObject';
Expand All @@ -19,21 +17,12 @@ type TAnimationOptions<T extends number | TColorArg> = T extends number
export abstract class AnimatableObject<
EventSpec extends ObjectEvents = ObjectEvents
> extends StackedObject<EventSpec> {
/**
* Animation duration (in ms) for fx* methods
* @type Number
* @default
*/
FX_DURATION: number;

/**
* List of properties to consider for animating colors.
* @type String[]
*/
colorProperties: string[];

abstract rotate(deg: TDegree): void;

/**
* Animates object's properties
* @param {String|Object} property Property to animate (if string) or properties to animate (if object)
Expand All @@ -45,45 +34,16 @@ export abstract class AnimatableObject<
*
* object.animate({ left: ..., top: ... });
* object.animate({ left: ..., top: ... }, { duration: ... });
*
* As string — one property
* Supports +=N and -=N for animating N units in a given direction
*
* object.animate('left', ...);
* object.animate('left', ..., { duration: ... });
*
* Example of +=/-=
* object.animate('right', '-=50');
* object.animate('top', '+=50', { duration: ... });
*/
animate<T extends number | TColorArg>(
key: string,
toValue: T,
options?: Partial<TAnimationOptions<T>>
): (ColorAnimation | ValueAnimation)[];
animate<T extends number | TColorArg>(
animatable: Record<string, T>,
options?: Partial<TAnimationOptions<T>>
): (ColorAnimation | ValueAnimation)[];
animate<T extends number | TColorArg, S extends string | Record<string, T>>(
arg0: S,
arg1: S extends string ? T : Partial<TAnimationOptions<T>>,
arg2?: S extends string ? Partial<TAnimationOptions<T>> : never
): (ColorAnimation | ValueAnimation)[] {
const animatable = (
typeof arg0 === 'string' ? { [arg0]: arg1 } : arg0
) as Record<string, T>;
const keys = Object.keys(animatable);
const options = (typeof arg0 === 'string' ? arg2 : arg1) as Partial<
TAnimationOptions<T>
>;
return keys.map((key, index) =>
): (ColorAnimation | ValueAnimation | ArrayAnimation)[] {
return Object.entries(animatable).map(([key, endValue]) =>
this._animate(
key,
animatable[key],
index === keys.length - 1
? options
: { ...options, onChange: undefined, onComplete: undefined }
endValue,
options,
)
);
}
Expand All @@ -96,37 +56,21 @@ export abstract class AnimatableObject<
*/
_animate<T extends number | TColorArg>(
key: string,
to: T,
endValue: T,
options: Partial<TAnimationOptions<T>> = {}
) {
const path = key.split('.');
const propIsColor = this.colorProperties.includes(path[path.length - 1]);
const currentValue = path.reduce((deep: any, key) => deep[key], this);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line handled the key path dot notation using key.split('.')

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i just moved it down, we need to execute it only if startValue is not passed.


if (!propIsColor && typeof to === 'string') {
// check for things like +=50
// which should animate so that the thing moves by 50 units in the positive direction
to = to.includes('=')
? currentValue + parseFloat(to.replace('=', ''))
: parseFloat(to);
}

const { byValue, easing, duration, abort, startValue, onChange, onComplete } = options;
const animationOptions = {
target: this,
startValue:
options.startValue ??
// backward compat
(options as any).from ??
currentValue,
endValue: to,
// `byValue` takes precedence over `endValue`
byValue:
options.byValue ??
// backward compat
(options as any).by,
easing: options.easing,
duration: options.duration,
abort: options.abort?.bind(this),
// path.reduce... is the current value in case start value isn't provided
startValue: startValue ?? path.reduce((deep: any, key) => deep[key], this),
endValue,
byValue,
easing,
duration,
abort: abort?.bind(this),
onChange: (
value: string | number,
valueRatio: number,
Expand All @@ -138,19 +82,19 @@ export abstract class AnimatableObject<
}
return deep[key];
}, this);
options.onChange &&
onChange &&
// @ts-expect-error generic callback arg0 is wrong
options.onChange(value, valueRatio, durationRatio);
onChange(value, valueRatio, durationRatio);
},
onComplete: (
value: string | number,
valueRatio: number,
durationRatio: number
) => {
this.setCoords();
options.onComplete &&
onComplete &&
// @ts-expect-error generic callback arg0 is wrong
options.onComplete(value, valueRatio, durationRatio);
onComplete(value, valueRatio, durationRatio);
},
} as TAnimationOptions<T>;

Expand All @@ -160,54 +104,4 @@ export abstract class AnimatableObject<
return animate(animationOptions as AnimationOptions);
}
}

/**
* @private
* @return {Number} angle value
*/
protected _getAngleValueForStraighten() {
const angle = this.angle % 360;
if (angle > 0) {
return Math.round((angle - 1) / 90) * 90;
}
return Math.round(angle / 90) * 90;
}

/**
* Straightens an object (rotating it from current angle to one of 0, 90, 180, 270, etc. depending on which is closer)
*/
straighten() {
this.rotate(this._getAngleValueForStraighten());
}

/**
* Same as {@link straighten} but with animation
* @param {Object} callbacks Object with callback functions
* @param {Function} [callbacks.onComplete] Invoked on completion
* @param {Function} [callbacks.onChange] Invoked on every step of animation
*/
fxStraighten(
callbacks: {
onChange?(value: TDegree): any;
onComplete?(): any;
} = {}
) {
const onComplete = callbacks.onComplete || noop,
onChange = callbacks.onChange || noop;

return animate({
target: this,
startValue: this.angle,
endValue: this._getAngleValueForStraighten(),
duration: this.FX_DURATION,
onChange: (value: TDegree) => {
this.rotate(value);
onChange(value);
},
onComplete: () => {
this.setCoords();
onComplete();
},
});
}
}
3 changes: 1 addition & 2 deletions src/shapes/Object/Object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import type {
TCacheCanvasDimensions,
} from '../../typedefs';
import { classRegistry } from '../../util/class_registry';
import { runningAnimations } from '../../util/animation';
import { runningAnimations } from '../../util/animation/AnimationRegistry';
import { clone } from '../../util/lang_object';
import { capitalize } from '../../util/lang_string';
import { capValue } from '../../util/misc/capValue';
Expand Down Expand Up @@ -2118,7 +2118,6 @@ export const fabricObjectDefaultValues = {
clipPath: undefined,
inverted: false,
absolutePositioned: false,
FX_DURATION: 500,
};

Object.assign(FabricObject.prototype, fabricObjectDefaultValues);
Expand Down
5 changes: 0 additions & 5 deletions src/util/animation/index.ts

This file was deleted.

8 changes: 4 additions & 4 deletions src/util/misc/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,13 @@ import {
} from '../dom_misc';
import { isTransparent } from './isTransparent';
import { mergeClipPaths } from './mergeClipPaths';
import * as ease from '../animation/easing';
import {
animate,
animateColor,
ease,
requestAnimFrame,
cancelAnimFrame,
} from '../animation';
} from '../animation/animate';
import { requestAnimFrame,
cancelAnimFrame, } from '../animation/AnimationFrameProvider';
import { createClass } from '../lang_class';
import { classRegistry } from '../class_registry';

Expand Down