mirror of
https://github.com/alexfoxy/lax.js.git
synced 2026-04-24 03:01:10 -04:00
Compare commits
18 Commits
dev
...
ts-upgrade
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
33e026efc5 | ||
|
|
489ca6d3f1 | ||
|
|
ec5180c890 | ||
|
|
3d3afe50dc | ||
|
|
ac9f55c864 | ||
|
|
6f97153302 | ||
|
|
5934da75ca | ||
|
|
c11bf52ec4 | ||
|
|
d96e295da8 | ||
|
|
6b7317dfcf | ||
|
|
06ca48f3b4 | ||
|
|
33812bd064 | ||
|
|
b223f14885 | ||
|
|
06ad981bf9 | ||
|
|
d76581ca49 | ||
|
|
87cd7d1efc | ||
|
|
e68947bf7c | ||
|
|
fe62c7698c |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
node_modules/
|
||||
.DS_Store
|
||||
LaxLogo.sketch
|
||||
LaxLogo.sketch
|
||||
tsconfig.tsbuildinfo
|
||||
2
docs/lib/lax.min.js
vendored
2
docs/lib/lax.min.js
vendored
File diff suppressed because one or more lines are too long
102
lib/lax.d.ts
vendored
Normal file
102
lib/lax.d.ts
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
import { DriverOptions, LaxPresetFn, ElementOptions, DriverTransforms } from './types';
|
||||
declare class Lax {
|
||||
private drivers;
|
||||
private elements;
|
||||
private frame;
|
||||
private debug;
|
||||
windowWidth: number;
|
||||
windowHeight: number;
|
||||
presets: {
|
||||
fadeIn: LaxPresetFn;
|
||||
fadeOut: LaxPresetFn;
|
||||
fadeInOut: LaxPresetFn;
|
||||
scaleIn: LaxPresetFn;
|
||||
scaleOut: LaxPresetFn;
|
||||
scaleInOut: LaxPresetFn;
|
||||
slideX: LaxPresetFn;
|
||||
slideY: LaxPresetFn;
|
||||
jiggle: LaxPresetFn;
|
||||
seesaw: LaxPresetFn;
|
||||
zigzag: LaxPresetFn;
|
||||
hueRotate: LaxPresetFn;
|
||||
spin: LaxPresetFn;
|
||||
flipX: LaxPresetFn;
|
||||
flipY: LaxPresetFn;
|
||||
blurIn: LaxPresetFn;
|
||||
blurOut: LaxPresetFn;
|
||||
blurInOut: LaxPresetFn;
|
||||
};
|
||||
private debugData;
|
||||
init: () => void;
|
||||
onWindowResize: () => void;
|
||||
onAnimationFrame: (e: DOMHighResTimeStamp) => void;
|
||||
addDriver: (name: string, getValueFn: () => number, options?: DriverOptions) => void;
|
||||
removeDriver: (name: string) => void;
|
||||
findAndAddElements: () => void;
|
||||
addElements: (selector: string, transforms: DriverTransforms, options?: ElementOptions) => void;
|
||||
removeElements: (selector: string) => void;
|
||||
addElement: (domElement: HTMLElement | Element, transforms: DriverTransforms, options?: ElementOptions) => void;
|
||||
removeElement: (domElement: HTMLElement | Element) => void;
|
||||
}
|
||||
export declare const laxInstance: Lax;
|
||||
declare const lax: {
|
||||
addElements: (selector: string, transforms: DriverTransforms, options?: ElementOptions) => void;
|
||||
removeElements: (selector: string) => void;
|
||||
removeElement: (domElement: HTMLElement | Element) => void;
|
||||
addElement: (domElement: HTMLElement | Element, transforms: DriverTransforms, options?: ElementOptions) => void;
|
||||
init: () => void;
|
||||
addDriver: (name: string, getValueFn: () => number, options?: DriverOptions) => void;
|
||||
removeDriver: (name: string) => void;
|
||||
presets: {
|
||||
fadeIn: LaxPresetFn;
|
||||
fadeOut: LaxPresetFn;
|
||||
fadeInOut: LaxPresetFn;
|
||||
scaleIn: LaxPresetFn;
|
||||
scaleOut: LaxPresetFn;
|
||||
scaleInOut: LaxPresetFn;
|
||||
slideX: LaxPresetFn;
|
||||
slideY: LaxPresetFn;
|
||||
jiggle: LaxPresetFn;
|
||||
seesaw: LaxPresetFn;
|
||||
zigzag: LaxPresetFn;
|
||||
hueRotate: LaxPresetFn;
|
||||
spin: LaxPresetFn;
|
||||
flipX: LaxPresetFn;
|
||||
flipY: LaxPresetFn;
|
||||
blurIn: LaxPresetFn;
|
||||
blurOut: LaxPresetFn;
|
||||
blurInOut: LaxPresetFn;
|
||||
};
|
||||
};
|
||||
declare global {
|
||||
namespace NodeJS {
|
||||
interface Global {
|
||||
lax: typeof lax;
|
||||
}
|
||||
}
|
||||
interface Window {
|
||||
lax: typeof lax;
|
||||
}
|
||||
}
|
||||
export default lax;
|
||||
export declare const addDriver: (name: string, getValueFn: () => number, options?: DriverOptions) => void, addElement: (domElement: HTMLElement | Element, transforms: DriverTransforms, options?: ElementOptions) => void, addElements: (selector: string, transforms: DriverTransforms, options?: ElementOptions) => void, removeDriver: (name: string) => void, removeElement: (domElement: HTMLElement | Element) => void, removeElements: (selector: string) => void, init: () => void, presets: {
|
||||
fadeIn: LaxPresetFn;
|
||||
fadeOut: LaxPresetFn;
|
||||
fadeInOut: LaxPresetFn;
|
||||
scaleIn: LaxPresetFn;
|
||||
scaleOut: LaxPresetFn;
|
||||
scaleInOut: LaxPresetFn;
|
||||
slideX: LaxPresetFn;
|
||||
slideY: LaxPresetFn;
|
||||
jiggle: LaxPresetFn;
|
||||
seesaw: LaxPresetFn;
|
||||
zigzag: LaxPresetFn;
|
||||
hueRotate: LaxPresetFn;
|
||||
spin: LaxPresetFn;
|
||||
flipX: LaxPresetFn;
|
||||
flipY: LaxPresetFn;
|
||||
blurIn: LaxPresetFn;
|
||||
blurOut: LaxPresetFn;
|
||||
blurInOut: LaxPresetFn;
|
||||
};
|
||||
//# sourceMappingURL=lax.d.ts.map
|
||||
1
lib/lax.d.ts.map
Normal file
1
lib/lax.d.ts.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"lax.d.ts","sourceRoot":"","sources":["../src/lax.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,gBAAgB,EAAkE,MAAM,SAAS,CAAA;AA2ftJ,cAAM,GAAG;IACP,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,QAAQ,CAAwB;IACxC,OAAO,CAAC,KAAK,CAAI;IAEjB,OAAO,CAAC,KAAK,CAAQ;IAErB,WAAW,SAAI;IACf,YAAY,SAAI;IAChB,OAAO;;;;;;;;;;;;;;;;;;;MAAa;IAEpB,OAAO,CAAC,SAAS,CAGhB;IAED,IAAI,aAQH;IAED,cAAc,aASb;IAED,gBAAgB,MAAO,mBAAmB,UA4BzC;IAED,SAAS,SAAU,MAAM,cAAc,MAAM,MAAM,YAAW,aAAa,UAI1E;IAED,YAAY,SAAU,MAAM,UAE3B;IAED,kBAAkB,aAwBjB;IAED,WAAW,aAAc,MAAM,cAAc,gBAAgB,YAAY,cAAc,UAMtF;IAED,cAAc,aAAc,MAAM,UAEjC;IAED,UAAU,eAAgB,WAAW,GAAG,OAAO,cAAc,gBAAgB,YAAY,cAAc,UAEtG;IAED,aAAa,eAAgB,WAAW,GAAG,OAAO,UAEjD;CACF;AAED,eAAO,MAAM,WAAW,KAAY,CAAA;AACpC,QAAA,MAAM,GAAG;4BAtBkB,MAAM,cAAc,gBAAgB,YAAY,cAAc;+BAQ3D,MAAM;gCAQL,WAAW,GAAG,OAAO;6BAJxB,WAAW,GAAG,OAAO,cAAc,gBAAgB,YAAY,cAAc;;sBAhDpF,MAAM,cAAc,MAAM,MAAM,YAAW,aAAa;yBAMrD,MAAM;;;;;;;;;;;;;;;;;;;;;CA6D7B,CAAA;AAGD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM,CAAC;QACf,UAAU,MAAM;YACd,GAAG,EAAE,OAAO,GAAG,CAAA;SAChB;KACF;IACD,UAAU,MAAM;QACd,GAAG,EAAE,OAAO,GAAG,CAAA;KAChB;CACF;AAWD,eAAe,GAAG,CAAA;AAClB,eAAO,MAAQ,SAAS,SA3FH,MAAM,cAAc,MAAM,MAAM,YAAW,aAAa,WA2FnD,UAAU,eA3CR,WAAW,GAAG,OAAO,cAAc,gBAAgB,YAAY,cAAc,WA2CnE,WAAW,aAvDtB,MAAM,cAAc,gBAAgB,YAAY,cAAc,WAuDtC,YAAY,SArFvC,MAAM,WAqFmC,aAAa,eAvC/C,WAAW,GAAG,OAAO,WAuC4B,cAAc,aA/ChE,MAAM,WA+C4D,IAAI,cAAE,OAAO;;;;;;;;;;;;;;;;;;;CAAQ,CAAA"}
|
||||
1254
lib/lax.js
1254
lib/lax.js
File diff suppressed because it is too large
Load Diff
1
lib/lax.js.map
Normal file
1
lib/lax.js.map
Normal file
File diff suppressed because one or more lines are too long
2
lib/lax.min.js
vendored
2
lib/lax.min.js
vendored
File diff suppressed because one or more lines are too long
Binary file not shown.
1
lib/lax.min.js.map
Normal file
1
lib/lax.min.js.map
Normal file
File diff suppressed because one or more lines are too long
72
lib/types.d.ts
vendored
Normal file
72
lib/types.d.ts
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
export interface DriverOptions {
|
||||
inertiaEnabled?: boolean;
|
||||
frameStep?: number;
|
||||
}
|
||||
export interface StyleObject {
|
||||
[key: string]: any;
|
||||
}
|
||||
export declare type LaxPresetName = "fadeIn" | "fadeOut" | "fadeInOut" | "scaleIn" | "scaleOut" | "scaleInOut" | "slideX" | "slideY" | "jiggle" | "seesaw" | "zigzag" | "hueRotate" | "spin" | "flipX" | "flipY" | "blurIn" | "blurOut" | "blurInOut";
|
||||
export declare type LaxPresetFn = (x: number | string, y: number | string) => LaxPresetStyleProps;
|
||||
export declare type easingOptions = "easeInQuad" | "easeOutQuad" | "easeInOutQuad" | "easeInCubic" | "easeOutCubic" | "easeInOutCubic" | "easeInQuart" | "easeOutQuart" | "easeInOutQuart" | "easeInQuint" | "easeOutQuint" | "easeInOutQuint" | "easeOutBounce" | "easeInBounce" | "easeOutBack" | "easeInBack";
|
||||
export declare type specialValues = "screenWidth" | "screenHeight" | "pageWidth" | "pageHeight" | "elWidth" | "elHeight" | "elInY" | "elOutY" | "elCenterY" | "elInX" | "elOutX" | "elCenterX" | "index";
|
||||
export declare enum cssValues {
|
||||
"opacity" = "opacity",
|
||||
"scaleX" = "scaleX",
|
||||
"scaleY" = "scaleY",
|
||||
"scale" = "scale",
|
||||
"skewX" = "skewX",
|
||||
"skewY" = "skewY",
|
||||
"skew" = "skew",
|
||||
"rotateX" = "rotateX",
|
||||
"rotateY" = "rotateY",
|
||||
"rotate" = "rotate",
|
||||
"translateX" = "translateX",
|
||||
"translateY" = "translateY",
|
||||
"translateZ" = "translateZ",
|
||||
"blur" = "blur",
|
||||
"hue-rotate" = "hue-rotate",
|
||||
"brightness" = "brightness"
|
||||
}
|
||||
export interface LaxStyleMapOptions {
|
||||
modValue?: number | undefined;
|
||||
frameStep?: number;
|
||||
inertia?: number;
|
||||
inertiaMode?: "normal" | "absolute";
|
||||
cssUnit?: string;
|
||||
cssFn?(value: number, domElement: HTMLElement | Element): number | string;
|
||||
easing?: easingOptions;
|
||||
}
|
||||
export declare type LaxStyleMap = [
|
||||
Array<number | specialValues | string>,
|
||||
Array<number | specialValues | string>,
|
||||
LaxStyleMapOptions?
|
||||
];
|
||||
export interface LaxStyleProps extends LaxPresetStyleProps {
|
||||
"presets"?: Array<LaxPresetName>;
|
||||
}
|
||||
export interface LaxPresetStyleProps {
|
||||
"opacity"?: LaxStyleMap;
|
||||
"scaleX"?: LaxStyleMap;
|
||||
"scaleY"?: LaxStyleMap;
|
||||
"scale"?: LaxStyleMap;
|
||||
"skewX"?: LaxStyleMap;
|
||||
"skewY"?: LaxStyleMap;
|
||||
"skew"?: LaxStyleMap;
|
||||
"rotateX"?: LaxStyleMap;
|
||||
"rotateY"?: LaxStyleMap;
|
||||
"rotate"?: LaxStyleMap;
|
||||
"translateX"?: LaxStyleMap;
|
||||
"translateY"?: LaxStyleMap;
|
||||
"translateZ"?: LaxStyleMap;
|
||||
"blur"?: LaxStyleMap;
|
||||
"hue-rotate"?: LaxStyleMap;
|
||||
"brightness"?: LaxStyleMap;
|
||||
}
|
||||
export interface ElementOptions {
|
||||
style?: StyleObject;
|
||||
onUpdate?(driverValues: any, domElement: HTMLElement | Element): void;
|
||||
}
|
||||
export interface DriverTransforms {
|
||||
[key: string]: LaxStyleProps | LaxPresetStyleProps;
|
||||
}
|
||||
//# sourceMappingURL=types.d.ts.map
|
||||
1
lib/types.d.ts.map
Normal file
1
lib/types.d.ts.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
||||
23
lib/types.js
Normal file
23
lib/types.js
Normal file
@@ -0,0 +1,23 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.cssValues = void 0;
|
||||
var cssValues;
|
||||
(function (cssValues) {
|
||||
cssValues["opacity"] = "opacity";
|
||||
cssValues["scaleX"] = "scaleX";
|
||||
cssValues["scaleY"] = "scaleY";
|
||||
cssValues["scale"] = "scale";
|
||||
cssValues["skewX"] = "skewX";
|
||||
cssValues["skewY"] = "skewY";
|
||||
cssValues["skew"] = "skew";
|
||||
cssValues["rotateX"] = "rotateX";
|
||||
cssValues["rotateY"] = "rotateY";
|
||||
cssValues["rotate"] = "rotate";
|
||||
cssValues["translateX"] = "translateX";
|
||||
cssValues["translateY"] = "translateY";
|
||||
cssValues["translateZ"] = "translateZ";
|
||||
cssValues["blur"] = "blur";
|
||||
cssValues["hue-rotate"] = "hue-rotate";
|
||||
cssValues["brightness"] = "brightness";
|
||||
})(cssValues = exports.cssValues || (exports.cssValues = {}));
|
||||
//# sourceMappingURL=types.js.map
|
||||
1
lib/types.js.map
Normal file
1
lib/types.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";;;AA+DA,IAAY,SAiBX;AAjBD,WAAY,SAAS;IACnB,gCAAmB,CAAA;IACnB,8BAAiB,CAAA;IACjB,8BAAiB,CAAA;IACjB,4BAAe,CAAA;IACf,4BAAe,CAAA;IACf,4BAAe,CAAA;IACf,0BAAa,CAAA;IACb,gCAAmB,CAAA;IACnB,gCAAmB,CAAA;IACnB,8BAAiB,CAAA;IACjB,sCAAyB,CAAA;IACzB,sCAAyB,CAAA;IACzB,sCAAyB,CAAA;IACzB,0BAAa,CAAA;IACb,sCAAyB,CAAA;IACzB,sCAAyB,CAAA;AAC3B,CAAC,EAjBW,SAAS,GAAT,iBAAS,KAAT,iBAAS,QAiBpB"}
|
||||
11
package.json
11
package.json
@@ -1,14 +1,18 @@
|
||||
{
|
||||
"name": "lax.js",
|
||||
"version": "2.0.3",
|
||||
"version": "2.1.0",
|
||||
"scripts": {
|
||||
"build": "babel src -d lib && uglifyjs lib/lax.js -o lib/lax.min.js -c -m && gzip -c lib/lax.min.js > lib/lax.min.js.gz && cp lib/lax.min.js docs/lib/lax.min.js"
|
||||
"prebuild-ts": "tsc",
|
||||
"build-ts": "uglifyjs ./lib/lax.js --source-map -o ./lib/lax.min.js -c -m && gzip -c ./lib/lax.min.js > ./lib/lax.min.js.gz && cp ./lib/lax.min.js ./docs/lib/lax.min.js",
|
||||
"dev": "tsc --watch"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.12.1",
|
||||
"@babel/core": "^7.12.3",
|
||||
"@babel/plugin-proposal-class-properties": "^7.12.1",
|
||||
"@babel/preset-env": "^7.12.1",
|
||||
"@types/node": "^14.14.25",
|
||||
"typescript": "^4.1.3",
|
||||
"uglify-js": "^3.9.4"
|
||||
},
|
||||
"description": "Simple & lightweight (<4kb gzipped) vanilla JavaScript library to create smooth & beautiful animations when you scroll.",
|
||||
@@ -18,7 +22,8 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/alexfoxy/lax.js"
|
||||
},
|
||||
"main": "lib/lax.min.js",
|
||||
"main": "lib/lax.js",
|
||||
"types": "lib/lax.d.ts",
|
||||
"keywords": [
|
||||
"javascript",
|
||||
"lax",
|
||||
|
||||
616
src/lax.js
616
src/lax.js
@@ -1,616 +0,0 @@
|
||||
(() => {
|
||||
const inOutMap = (y = 30) => {
|
||||
return ["elInY+elHeight", `elCenterY-${y}`, "elCenterY", `elCenterY+${y}`, "elOutY-elHeight"]
|
||||
}
|
||||
|
||||
const laxPresets = {
|
||||
fadeInOut: (y = 30, str = 0) => ({
|
||||
"opacity": [
|
||||
inOutMap(y),
|
||||
[str, 1, 1, 1, str]
|
||||
],
|
||||
}),
|
||||
fadeIn: (y = 'elCenterY', str = 0) => ({
|
||||
"opacity": [
|
||||
["elInY+elHeight", y],
|
||||
[str, 1],
|
||||
],
|
||||
}),
|
||||
fadeOut: (y = 'elCenterY', str = 0) => ({
|
||||
"opacity": [
|
||||
[y, "elOutY-elHeight"],
|
||||
[1, str],
|
||||
],
|
||||
}),
|
||||
blurInOut: (y = 100, str = 20) => ({
|
||||
"blur": [
|
||||
inOutMap(y),
|
||||
[str, 0, 0, 0, str],
|
||||
],
|
||||
}),
|
||||
blurIn: (y = 'elCenterY', str = 20) => ({
|
||||
"blur": [
|
||||
["elInY+elHeight", y],
|
||||
[str, 0],
|
||||
],
|
||||
}),
|
||||
blurOut: (y = 'elCenterY', str = 20) => ({
|
||||
"opacity": [
|
||||
[y, "elOutY-elHeight"],
|
||||
[0, str],
|
||||
],
|
||||
}),
|
||||
scaleInOut: (y = 100, str = 0.6) => ({
|
||||
"scale": [
|
||||
inOutMap(y),
|
||||
[str, 1, 1, 1, str],
|
||||
],
|
||||
}),
|
||||
scaleIn: (y = 'elCenterY', str = 0.6) => ({
|
||||
"scale": [
|
||||
["elInY+elHeight", y],
|
||||
[str, 1],
|
||||
],
|
||||
}),
|
||||
scaleOut: (y = 'elCenterY', str = 0.6) => ({
|
||||
"scale": [
|
||||
[y, "elOutY-elHeight"],
|
||||
[1, str],
|
||||
],
|
||||
}),
|
||||
slideX: (y = 0, str = 500) => ({
|
||||
"translateX": [
|
||||
['elInY', y],
|
||||
[0, str],
|
||||
],
|
||||
}),
|
||||
slideY: (y = 0, str = 500) => ({
|
||||
"translateY": [
|
||||
['elInY', y],
|
||||
[0, str],
|
||||
],
|
||||
}),
|
||||
spin: (y = 1000, str = 360) => ({
|
||||
"rotate": [
|
||||
[0, y],
|
||||
[0, str],
|
||||
{
|
||||
modValue: y,
|
||||
}
|
||||
],
|
||||
}),
|
||||
flipX: (y = 1000, str = 360) => ({
|
||||
"rotateX": [
|
||||
[0, y],
|
||||
[0, str],
|
||||
{
|
||||
modValue: y
|
||||
}
|
||||
],
|
||||
}),
|
||||
flipY: (y = 1000, str = 360) => ({
|
||||
"rotateY": [
|
||||
[0, y],
|
||||
[0, str],
|
||||
{
|
||||
modValue: y
|
||||
}
|
||||
],
|
||||
}),
|
||||
jiggle: (y = 50, str = 40) => ({
|
||||
"skewX": [
|
||||
[0, y * 1, y * 2, y * 3, y * 4],
|
||||
[0, str, 0, -str, 0],
|
||||
{
|
||||
modValue: y * 4,
|
||||
}
|
||||
],
|
||||
}),
|
||||
seesaw: (y = 50, str = 40) => ({
|
||||
"skewY": [
|
||||
[0, y * 1, y * 2, y * 3, y * 4],
|
||||
[0, str, 0, -str, 0],
|
||||
{
|
||||
modValue: y * 4,
|
||||
}
|
||||
],
|
||||
}),
|
||||
zigzag: (y = 100, str = 100) => ({
|
||||
"translateX": [
|
||||
[0, y * 1, y * 2, y * 3, y * 4],
|
||||
[0, str, 0, -str, 0],
|
||||
{
|
||||
modValue: y * 4,
|
||||
}
|
||||
],
|
||||
}),
|
||||
hueRotate: (y = 600, str = 360) => ({
|
||||
"hue-rotate": [
|
||||
[0, y],
|
||||
[0, str],
|
||||
{
|
||||
modValue: y,
|
||||
}
|
||||
],
|
||||
}),
|
||||
}
|
||||
|
||||
const laxInstance = (() => {
|
||||
const transformKeys = ["perspective", "scaleX", "scaleY", "scale", "skewX", "skewY", "skew", "rotateX", "rotateY", "rotate"]
|
||||
const filterKeys = ["blur", "hue-rotate", "brightness"]
|
||||
const translate3dKeys = ["translateX", "translateY", "translateZ"]
|
||||
|
||||
const pxUnits = ["perspective", "border-radius", "blur", "translateX", "translateY", "translateZ"]
|
||||
const degUnits = ["hue-rotate", "rotate", "rotateX", "rotateY", "skew", "skewX", "skewY"]
|
||||
|
||||
function getArrayValues(arr, windowWidth) {
|
||||
if (Array.isArray(arr)) return arr
|
||||
|
||||
const keys = Object.keys(arr).map(x => parseInt(x)).sort((a, b) => a > b ? 1 : -1)
|
||||
|
||||
let retKey = keys[keys.length - 1]
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const key = keys[i]
|
||||
if (windowWidth < key) {
|
||||
retKey = key
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return arr[retKey]
|
||||
}
|
||||
|
||||
function lerp(start, end, t) {
|
||||
return start * (1 - t) + end * t
|
||||
}
|
||||
|
||||
function invlerp(a, b, v) {
|
||||
return (v - a) / (b - a)
|
||||
}
|
||||
|
||||
function interpolate(arrA, arrB, v, easingFn) {
|
||||
let k = 0
|
||||
|
||||
arrA.forEach((a) => {
|
||||
if (a < v) k++
|
||||
})
|
||||
|
||||
if (k <= 0) {
|
||||
return arrB[0]
|
||||
}
|
||||
|
||||
if (k >= arrA.length) {
|
||||
return arrB[arrA.length - 1]
|
||||
}
|
||||
|
||||
const j = k - 1
|
||||
|
||||
let vector = invlerp(arrA[j], arrA[k], v)
|
||||
if (easingFn) vector = easingFn(vector)
|
||||
const lerpVal = lerp(arrB[j], arrB[k], vector)
|
||||
return lerpVal
|
||||
}
|
||||
|
||||
const easings = {
|
||||
easeInQuad: t => t * t,
|
||||
easeOutQuad: t => t * (2 - t),
|
||||
easeInOutQuad: t => t < .5 ? 2 * t * t : -1 + (4 - 2 * t) * t,
|
||||
easeInCubic: t => t * t * t,
|
||||
easeOutCubic: t => (--t) * t * t + 1,
|
||||
easeInOutCubic: t => t < .5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1,
|
||||
easeInQuart: t => t * t * t * t,
|
||||
easeOutQuart: t => 1 - (--t) * t * t * t,
|
||||
easeInOutQuart: t => t < .5 ? 8 * t * t * t * t : 1 - 8 * (--t) * t * t * t,
|
||||
easeInQuint: t => t * t * t * t * t,
|
||||
easeOutQuint: t => 1 + (--t) * t * t * t * t,
|
||||
easeInOutQuint: t => t < .5 ? 16 * t * t * t * t * t : 1 + 16 * (--t) * t * t * t * t,
|
||||
easeOutBounce: t => {
|
||||
const n1 = 7.5625
|
||||
const d1 = 2.75
|
||||
|
||||
if (t < 1 / d1) {
|
||||
return n1 * t * t
|
||||
} else if (t < 2 / d1) {
|
||||
return n1 * (t -= 1.5 / d1) * t + 0.75
|
||||
} else if (t < 2.5 / d1) {
|
||||
return n1 * (t -= 2.25 / d1) * t + 0.9375
|
||||
} else {
|
||||
return n1 * (t -= 2.625 / d1) * t + 0.984375
|
||||
}
|
||||
},
|
||||
easeInBounce: t => {
|
||||
return 1 - easings.easeOutBounce(1 - t)
|
||||
},
|
||||
easeOutBack: t => {
|
||||
const c1 = 1.70158
|
||||
const c3 = c1 + 1
|
||||
|
||||
return 1 + c3 * Math.pow(t - 1, 3) + c1 * Math.pow(t - 1, 2)
|
||||
},
|
||||
easeInBack: t => {
|
||||
const c1 = 1.70158
|
||||
const c3 = c1 + 1
|
||||
|
||||
return c3 * t * t * t - c1 * t * t
|
||||
},
|
||||
}
|
||||
|
||||
function flattenStyles(styles) {
|
||||
const flattenedStyles = {
|
||||
transform: '',
|
||||
filter: ''
|
||||
}
|
||||
|
||||
const translate3dValues = {
|
||||
translateX: 0.00001,
|
||||
translateY: 0.00001,
|
||||
translateZ: 0.00001
|
||||
}
|
||||
|
||||
Object.keys(styles).forEach((key) => {
|
||||
const val = styles[key]
|
||||
const unit = pxUnits.includes(key) ? 'px' : (degUnits.includes(key) ? 'deg' : '')
|
||||
|
||||
if (translate3dKeys.includes(key)) {
|
||||
translate3dValues[key] = val
|
||||
} else if (transformKeys.includes(key)) {
|
||||
flattenedStyles.transform += `${key}(${val}${unit}) `
|
||||
} else if (filterKeys.includes(key)) {
|
||||
flattenedStyles.filter += `${key}(${val}${unit}) `
|
||||
} else {
|
||||
flattenedStyles[key] = `${val}${unit} `
|
||||
}
|
||||
})
|
||||
|
||||
flattenedStyles.transform = `translate3d(${translate3dValues.translateX}px, ${translate3dValues.translateY}px, ${translate3dValues.translateZ}px) ${flattenedStyles.transform}`
|
||||
|
||||
return flattenedStyles
|
||||
}
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY#Notes
|
||||
function getScrollPosition() {
|
||||
const supportPageOffset = window.pageXOffset !== undefined
|
||||
const isCSS1Compat = ((document.compatMode || '') === 'CSS1Compat')
|
||||
|
||||
const x = supportPageOffset ? window.pageXOffset : isCSS1Compat ? document.documentElement.scrollLeft : document.body.scrollLeft
|
||||
const y = supportPageOffset ? window.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop
|
||||
|
||||
return [y, x]
|
||||
}
|
||||
|
||||
function parseValue(val, { width, height, x, y }, index) {
|
||||
if (typeof val === 'number') {
|
||||
return val
|
||||
}
|
||||
|
||||
const pageHeight = document.body.scrollHeight
|
||||
const pageWidth = document.body.scrollWidth
|
||||
const screenWidth = window.innerWidth
|
||||
const screenHeight = window.innerHeight
|
||||
const [scrollTop, scrollLeft] = getScrollPosition()
|
||||
|
||||
const left = x + scrollLeft
|
||||
const right = left + width
|
||||
const top = y + scrollTop
|
||||
const bottom = top + height
|
||||
|
||||
return Function(`return ${val
|
||||
.replace(/screenWidth/g, screenWidth)
|
||||
.replace(/screenHeight/g, screenHeight)
|
||||
.replace(/pageHeight/g, pageHeight)
|
||||
.replace(/pageWidth/g, pageWidth)
|
||||
.replace(/elWidth/g, width)
|
||||
.replace(/elHeight/g, height)
|
||||
.replace(/elInY/g, top - screenHeight)
|
||||
.replace(/elOutY/g, bottom)
|
||||
.replace(/elCenterY/g, top + (height / 2) - (screenHeight / 2))
|
||||
.replace(/elInX/g, left - screenWidth)
|
||||
.replace(/elOutX/g, right)
|
||||
.replace(/elCenterX/g, left + (width / 2) - (screenWidth / 2))
|
||||
.replace(/index/g, index)
|
||||
}`)()
|
||||
}
|
||||
|
||||
class LaxDriver {
|
||||
getValueFn
|
||||
name = ''
|
||||
lastValue = 0
|
||||
frameStep = 1
|
||||
m1 = 0
|
||||
|
||||
m2 = 0
|
||||
inertia = 0
|
||||
inertiaEnabled = false
|
||||
|
||||
|
||||
constructor(name, getValueFn, options = {}) {
|
||||
this.name = name
|
||||
this.getValueFn = getValueFn
|
||||
|
||||
Object.keys(options).forEach((key) => {
|
||||
this[key] = options[key]
|
||||
})
|
||||
|
||||
this.lastValue = this.getValueFn(0)
|
||||
}
|
||||
|
||||
getValue = (frame) => {
|
||||
let value = this.lastValue
|
||||
|
||||
if (frame % this.frameStep === 0) {
|
||||
value = this.getValueFn(frame)
|
||||
}
|
||||
|
||||
if (this.inertiaEnabled) {
|
||||
const delta = value - this.lastValue
|
||||
const damping = 0.8
|
||||
|
||||
this.m1 = this.m1 * damping + delta * (1 - damping)
|
||||
this.m2 = this.m2 * damping + this.m1 * (1 - damping)
|
||||
this.inertia = Math.round(this.m2 * 5000) / 15000
|
||||
}
|
||||
|
||||
this.lastValue = value
|
||||
return [this.lastValue, this.inertia]
|
||||
}
|
||||
}
|
||||
|
||||
class LaxElement {
|
||||
domElement
|
||||
transformsData
|
||||
styles = {}
|
||||
selector = ''
|
||||
|
||||
groupIndex = 0
|
||||
laxInstance
|
||||
|
||||
onUpdate
|
||||
|
||||
constructor(selector, laxInstance, domElement, transformsData, groupIndex = 0, options = {}) {
|
||||
this.selector = selector
|
||||
this.laxInstance = laxInstance
|
||||
this.domElement = domElement
|
||||
this.transformsData = transformsData
|
||||
this.groupIndex = groupIndex
|
||||
|
||||
const { style = {}, onUpdate } = options
|
||||
|
||||
Object.keys(style).forEach(key => {
|
||||
domElement.style.setProperty(key, style[key])
|
||||
})
|
||||
|
||||
if (onUpdate) this.onUpdate = onUpdate
|
||||
|
||||
this.calculateTransforms()
|
||||
}
|
||||
|
||||
update = (driverValues, frame) => {
|
||||
const { transforms } = this
|
||||
|
||||
const styles = {}
|
||||
|
||||
for (let driverName in transforms) {
|
||||
const styleBindings = transforms[driverName]
|
||||
|
||||
if (!driverValues[driverName]) {
|
||||
console.error("No lax driver with name: ", driverName)
|
||||
}
|
||||
|
||||
const [value, inertiaValue] = driverValues[driverName]
|
||||
|
||||
for (let key in styleBindings) {
|
||||
const [arr1, arr2, options = {}] = styleBindings[key]
|
||||
const { modValue, frameStep = 1, easing, inertia, inertiaMode, cssFn, cssUnit = '' } = options
|
||||
|
||||
const easingFn = easings[easing]
|
||||
|
||||
if (frame % frameStep === 0) {
|
||||
const v = modValue ? value % modValue : value
|
||||
|
||||
let interpolatedValue = interpolate(arr1, arr2, v, easingFn)
|
||||
|
||||
if (inertia) {
|
||||
let inertiaExtra = inertiaValue * inertia
|
||||
if (inertiaMode === 'absolute') inertiaExtra = Math.abs((inertiaExtra))
|
||||
interpolatedValue += inertiaExtra
|
||||
}
|
||||
|
||||
const unit = cssUnit || pxUnits.includes(key) ? 'px' : (degUnits.includes(key) ? 'deg' : '')
|
||||
const dp = unit === 'px' ? 0 : 3
|
||||
const val = interpolatedValue.toFixed(dp)
|
||||
styles[key] = cssFn ? cssFn(val, this.domElement) : val + cssUnit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.applyStyles(styles)
|
||||
if (this.onUpdate) this.onUpdate(driverValues, this.domElement)
|
||||
}
|
||||
|
||||
calculateTransforms = () => {
|
||||
this.transforms = {}
|
||||
const windowWidth = this.laxInstance.windowWidth
|
||||
|
||||
for (let driverName in this.transformsData) {
|
||||
let styleBindings = this.transformsData[driverName]
|
||||
|
||||
const parsedStyleBindings = {}
|
||||
|
||||
const { presets = [] } = styleBindings
|
||||
|
||||
presets.forEach((presetString) => {
|
||||
|
||||
const [presetName, y, str] = presetString.split(":")
|
||||
|
||||
const presetFn = window.lax.presets[presetName]
|
||||
|
||||
if (!presetFn) {
|
||||
console.error("Lax preset cannot be found with name: ", presetName)
|
||||
} else {
|
||||
const preset = presetFn(y, str)
|
||||
|
||||
Object.keys(preset).forEach((key) => {
|
||||
styleBindings[key] = preset[key]
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
delete styleBindings.presets
|
||||
|
||||
for (let key in styleBindings) {
|
||||
let [arr1 = [-1e9, 1e9], arr2 = [-1e9, 1e9], options = {}] = styleBindings[key]
|
||||
|
||||
const saveTransform = this.domElement.style.transform
|
||||
this.domElement.style.removeProperty("transform")
|
||||
const bounds = this.domElement.getBoundingClientRect()
|
||||
this.domElement.style.transform = saveTransform
|
||||
|
||||
const parsedArr1 = getArrayValues(arr1, windowWidth).map(i => parseValue(i, bounds, this.groupIndex))
|
||||
const parsedArr2 = getArrayValues(arr2, windowWidth).map(i => parseValue(i, bounds, this.groupIndex))
|
||||
|
||||
parsedStyleBindings[key] = [parsedArr1, parsedArr2, options]
|
||||
}
|
||||
|
||||
this.transforms[driverName] = parsedStyleBindings
|
||||
}
|
||||
}
|
||||
|
||||
applyStyles = (styles) => {
|
||||
const mergedStyles = flattenStyles(styles)
|
||||
|
||||
Object.keys(mergedStyles).forEach((key) => {
|
||||
this.domElement.style.setProperty(key, mergedStyles[key])
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
class Lax {
|
||||
drivers = []
|
||||
elements = []
|
||||
frame = 0
|
||||
|
||||
debug = false
|
||||
|
||||
windowWidth = 0
|
||||
windowHeight = 0
|
||||
presets = laxPresets
|
||||
|
||||
debugData = {
|
||||
frameLengths: []
|
||||
}
|
||||
|
||||
init = () => {
|
||||
this.findAndAddElements()
|
||||
|
||||
window.requestAnimationFrame(this.onAnimationFrame)
|
||||
this.windowWidth = document.body.clientWidth
|
||||
this.windowHeight = document.body.clientHeight
|
||||
|
||||
window.onresize = this.onWindowResize
|
||||
}
|
||||
|
||||
onWindowResize = () => {
|
||||
const changed = document.body.clientWidth !== this.windowWidth ||
|
||||
document.body.clientHeight !== this.windowHeight
|
||||
|
||||
if (changed) {
|
||||
this.windowWidth = document.body.clientWidth
|
||||
this.windowHeight = document.body.clientHeight
|
||||
this.elements.forEach(el => el.calculateTransforms())
|
||||
}
|
||||
}
|
||||
|
||||
onAnimationFrame = (e) => {
|
||||
if (this.debug) {
|
||||
this.debugData.frameStart = Date.now()
|
||||
}
|
||||
|
||||
const driverValues = {}
|
||||
|
||||
this.drivers.forEach((driver) => {
|
||||
driverValues[driver.name] = driver.getValue(this.frame)
|
||||
})
|
||||
|
||||
this.elements.forEach((element) => {
|
||||
element.update(driverValues, this.frame)
|
||||
})
|
||||
|
||||
if (this.debug) {
|
||||
this.debugData.frameLengths.push(Date.now() - this.debugData.frameStart)
|
||||
}
|
||||
|
||||
if (this.frame % 60 === 0 && this.debug) {
|
||||
const averageFrameTime = Math.ceil((this.debugData.frameLengths.reduce((a, b) => a + b, 0) / 60))
|
||||
console.log(`Average frame calculation time: ${averageFrameTime}ms`)
|
||||
this.debugData.frameLengths = []
|
||||
}
|
||||
|
||||
this.frame++
|
||||
|
||||
window.requestAnimationFrame(this.onAnimationFrame)
|
||||
}
|
||||
|
||||
addDriver = (name, getValueFn, options = {}) => {
|
||||
this.drivers.push(
|
||||
new LaxDriver(name, getValueFn, options)
|
||||
)
|
||||
}
|
||||
|
||||
removeDriver = (name) => {
|
||||
this.drivers = this.drivers.filter(driver => driver.name !== name)
|
||||
}
|
||||
|
||||
findAndAddElements = () => {
|
||||
this.elements = []
|
||||
const elements = document.querySelectorAll(".lax")
|
||||
|
||||
elements.forEach((domElement) => {
|
||||
const driverName = "scrollY"
|
||||
const presets = []
|
||||
|
||||
domElement.classList.forEach((className) => {
|
||||
if (className.includes("lax_preset")) {
|
||||
const preset = className.replace("lax_preset_", "")
|
||||
presets.push(preset)
|
||||
}
|
||||
})
|
||||
|
||||
const transforms = {
|
||||
[driverName]: {
|
||||
presets
|
||||
}
|
||||
}
|
||||
|
||||
this.elements.push(new LaxElement('.lax', this, domElement, transforms, 0, {}))
|
||||
})
|
||||
}
|
||||
|
||||
addElements = (selector, transforms, options) => {
|
||||
const domElements = options.domElements || document.querySelectorAll(selector)
|
||||
|
||||
domElements.forEach((domElement, i) => {
|
||||
this.elements.push(new LaxElement(selector, this, domElement, transforms, i, options))
|
||||
})
|
||||
}
|
||||
|
||||
removeElements = (selector) => {
|
||||
this.elements = this.elements.filter(element => element.selector !== selector)
|
||||
}
|
||||
|
||||
addElement = (domElement, transforms, options) => {
|
||||
this.elements.push(new LaxElement('', this, domElement, transforms, 0, options))
|
||||
}
|
||||
|
||||
removeElement = (domElement) => {
|
||||
this.elements = this.elements.filter(element => element.domElement !== domElement)
|
||||
}
|
||||
}
|
||||
|
||||
return new Lax()
|
||||
})()
|
||||
|
||||
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined')
|
||||
module.exports = laxInstance
|
||||
else
|
||||
window.lax = laxInstance
|
||||
})()
|
||||
666
src/lax.ts
Normal file
666
src/lax.ts
Normal file
@@ -0,0 +1,666 @@
|
||||
import { DriverOptions, LaxPresetFn, ElementOptions, DriverTransforms, LaxPresetName, LaxStyleProps, LaxStyleMap, LaxPresetStyleProps } from './types'
|
||||
|
||||
const isPresetName = (presetName: string): presetName is LaxPresetName => [
|
||||
"fadeIn",
|
||||
"fadeOut",
|
||||
"fadeInOut",
|
||||
"scaleIn",
|
||||
"scaleOut",
|
||||
"scaleInOut",
|
||||
"slideX",
|
||||
"slideY",
|
||||
"jiggle",
|
||||
"seesaw",
|
||||
"zigzag",
|
||||
"hueRotate",
|
||||
"spin",
|
||||
"flipX",
|
||||
"flipY",
|
||||
"blurIn",
|
||||
"blurOut",
|
||||
"blurInOut"
|
||||
].indexOf(presetName) !== -1 ? true : false
|
||||
|
||||
const inOutMap = (y: number | string = 30) => {
|
||||
return ["elInY+elHeight", `elCenterY-${y}`, "elCenterY", `elCenterY+${y}`, "elOutY-elHeight"]
|
||||
}
|
||||
|
||||
const laxPresets: { [key in LaxPresetName]: LaxPresetFn } = {
|
||||
fadeInOut: (y = 30, str = 0) => ({
|
||||
"opacity": [
|
||||
inOutMap(y),
|
||||
[str, 1, 1, 1, str]
|
||||
],
|
||||
}),
|
||||
fadeIn: (y = 'elCenterY', str = 0) => ({
|
||||
"opacity": [
|
||||
["elInY+elHeight", y],
|
||||
[str, 1],
|
||||
],
|
||||
}),
|
||||
fadeOut: (y = 'elCenterY', str = 0) => ({
|
||||
"opacity": [
|
||||
[y, "elOutY-elHeight"],
|
||||
[1, str],
|
||||
],
|
||||
}),
|
||||
blurInOut: (y = 100, str = 20) => ({
|
||||
"blur": [
|
||||
inOutMap(y),
|
||||
[str, 0, 0, 0, str],
|
||||
],
|
||||
}),
|
||||
blurIn: (y = 'elCenterY', str = 20) => ({
|
||||
"blur": [
|
||||
["elInY+elHeight", y],
|
||||
[str, 0],
|
||||
],
|
||||
}),
|
||||
blurOut: (y = 'elCenterY', str = 20) => ({
|
||||
"opacity": [
|
||||
[y, "elOutY-elHeight"],
|
||||
[0, str],
|
||||
],
|
||||
}),
|
||||
scaleInOut: (y = 100, str = 0.6) => ({
|
||||
"scale": [
|
||||
inOutMap(y),
|
||||
[str, 1, 1, 1, str],
|
||||
],
|
||||
}),
|
||||
scaleIn: (y = 'elCenterY', str = 0.6) => ({
|
||||
"scale": [
|
||||
["elInY+elHeight", y],
|
||||
[str, 1],
|
||||
],
|
||||
}),
|
||||
scaleOut: (y = 'elCenterY', str = 0.6) => ({
|
||||
"scale": [
|
||||
[y, "elOutY-elHeight"],
|
||||
[1, str],
|
||||
],
|
||||
}),
|
||||
slideX: (y = 0, str = 500) => ({
|
||||
"translateX": [
|
||||
['elInY', y],
|
||||
[0, str],
|
||||
],
|
||||
}),
|
||||
slideY: (y = 0, str = 500) => ({
|
||||
"translateY": [
|
||||
['elInY', y],
|
||||
[0, str],
|
||||
],
|
||||
}),
|
||||
spin: (y: number = 1000, str: number = 360) => ({
|
||||
"rotate": [
|
||||
[0, y],
|
||||
[0, str],
|
||||
{
|
||||
modValue: y,
|
||||
}
|
||||
],
|
||||
}),
|
||||
flipX: (y: number = 1000, str: number = 360) => ({
|
||||
"rotateX": [
|
||||
[0, y],
|
||||
[0, str],
|
||||
{
|
||||
modValue: y
|
||||
}
|
||||
],
|
||||
}),
|
||||
flipY: (y: number = 1000, str: number = 360) => ({
|
||||
"rotateY": [
|
||||
[0, y],
|
||||
[0, str],
|
||||
{
|
||||
modValue: y
|
||||
}
|
||||
],
|
||||
}),
|
||||
jiggle: (y: number = 50, str: number = 40) => ({
|
||||
"skewX": [
|
||||
[0, y * 1, y * 2, y * 3, y * 4],
|
||||
[0, str, 0, -str, 0],
|
||||
{
|
||||
modValue: y * 4,
|
||||
}
|
||||
],
|
||||
}),
|
||||
seesaw: (y: number = 50, str: number = 40) => ({
|
||||
"skewY": [
|
||||
[0, y * 1, y * 2, y * 3, y * 4],
|
||||
[0, str, 0, -str, 0],
|
||||
{
|
||||
modValue: y * 4,
|
||||
}
|
||||
],
|
||||
}),
|
||||
zigzag: (y: number = 100, str: number = 100) => ({
|
||||
"translateX": [
|
||||
[0, y * 1, y * 2, y * 3, y * 4],
|
||||
[0, str, 0, -str, 0],
|
||||
{
|
||||
modValue: y * 4,
|
||||
}
|
||||
],
|
||||
}),
|
||||
hueRotate: (y: number = 600, str: number = 360) => ({
|
||||
"hue-rotate": [
|
||||
[0, y],
|
||||
[0, str],
|
||||
{
|
||||
modValue: y,
|
||||
}
|
||||
],
|
||||
}),
|
||||
}
|
||||
const transformKeys = ["perspective", "scaleX", "scaleY", "scale", "skewX", "skewY", "skew", "rotateX", "rotateY", "rotate"]
|
||||
const filterKeys = ["blur", "hue-rotate", "brightness"]
|
||||
const translate3dKeys = ["translateX", "translateY", "translateZ"]
|
||||
const pxUnits = ["perspective", "border-radius", "blur", "translateX", "translateY", "translateZ"]
|
||||
const degUnits = ["hue-rotate", "rotate", "rotateX", "rotateY", "skew", "skewX", "skewY"]
|
||||
|
||||
function getArrayValues(arr: Array<number>, windowWidth: number) {
|
||||
if (Array.isArray(arr)) return arr
|
||||
|
||||
const keys = Object.keys(arr).map(x => parseInt(x)).sort((a, b) => a > b ? 1 : -1)
|
||||
|
||||
let retKey = keys[keys.length - 1]
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const key = keys[i]
|
||||
if (windowWidth < key) {
|
||||
retKey = key
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return arr[retKey]
|
||||
}
|
||||
|
||||
function lerp(start: number, end: number, t: number) {
|
||||
return start * (1 - t) + end * t
|
||||
}
|
||||
|
||||
function invlerp(a: number, b: number, v: number) {
|
||||
return (v - a) / (b - a)
|
||||
}
|
||||
|
||||
function interpolate(arrA: number[], arrB: number[], v: number, easingFn: (vector: any) => any) {
|
||||
let k = 0
|
||||
|
||||
arrA.forEach((a: number) => {
|
||||
if (a < v) k++
|
||||
})
|
||||
|
||||
if (k <= 0) {
|
||||
return arrB[0]
|
||||
}
|
||||
|
||||
if (k >= arrA.length) {
|
||||
return arrB[arrA.length - 1]
|
||||
}
|
||||
|
||||
const j = k - 1
|
||||
|
||||
let vector = invlerp(arrA[j], arrA[k], v)
|
||||
if (easingFn) vector = easingFn(vector)
|
||||
const lerpVal = lerp(arrB[j], arrB[k], vector)
|
||||
return lerpVal
|
||||
}
|
||||
|
||||
const easings = {
|
||||
easeInQuad: (t: number) => t * t,
|
||||
easeOutQuad: (t: number) => t * (2 - t),
|
||||
easeInOutQuad: (t: number) => t < .5 ? 2 * t * t : -1 + (4 - 2 * t) * t,
|
||||
easeInCubic: (t: number) => t * t * t,
|
||||
easeOutCubic: (t: number) => (--t) * t * t + 1,
|
||||
easeInOutCubic: (t: number) => t < .5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1,
|
||||
easeInQuart: (t: number) => t * t * t * t,
|
||||
easeOutQuart: (t: number) => 1 - (--t) * t * t * t,
|
||||
easeInOutQuart: (t: number) => t < .5 ? 8 * t * t * t * t : 1 - 8 * (--t) * t * t * t,
|
||||
easeInQuint: (t: number) => t * t * t * t * t,
|
||||
easeOutQuint: (t: number) => 1 + (--t) * t * t * t * t,
|
||||
easeInOutQuint: (t: number) => t < .5 ? 16 * t * t * t * t * t : 1 + 16 * (--t) * t * t * t * t,
|
||||
easeOutBounce: (t: number) => {
|
||||
const n1 = 7.5625
|
||||
const d1 = 2.75
|
||||
|
||||
if (t < 1 / d1) {
|
||||
return n1 * t * t
|
||||
} else if (t < 2 / d1) {
|
||||
return n1 * (t -= 1.5 / d1) * t + 0.75
|
||||
} else if (t < 2.5 / d1) {
|
||||
return n1 * (t -= 2.25 / d1) * t + 0.9375
|
||||
} else {
|
||||
return n1 * (t -= 2.625 / d1) * t + 0.984375
|
||||
}
|
||||
},
|
||||
easeInBounce: (t: number) => {
|
||||
return 1 - easings.easeOutBounce(1 - t)
|
||||
},
|
||||
easeOutBack: (t: number) => {
|
||||
const c1 = 1.70158
|
||||
const c3 = c1 + 1
|
||||
|
||||
return 1 + c3 * Math.pow(t - 1, 3) + c1 * Math.pow(t - 1, 2)
|
||||
},
|
||||
easeInBack: (t: number) => {
|
||||
const c1 = 1.70158
|
||||
const c3 = c1 + 1
|
||||
|
||||
return c3 * t * t * t - c1 * t * t
|
||||
},
|
||||
}
|
||||
|
||||
function flattenStyles(styles: Partial<{ [key in (keyof LaxStyleProps) | "transform" | "filter"]: number | string }>) {
|
||||
const flattenedStyles = {
|
||||
transform: '',
|
||||
filter: ''
|
||||
}
|
||||
|
||||
const translate3dValues = {
|
||||
translateX: 0.00001,
|
||||
translateY: 0.00001,
|
||||
translateZ: 0.00001
|
||||
}
|
||||
|
||||
Object.keys(styles).forEach((key: Partial<keyof LaxStyleProps>) => {
|
||||
const val = styles[key]
|
||||
const unit = pxUnits.includes(key) ? 'px' : (degUnits.includes(key) ? 'deg' : '')
|
||||
|
||||
if (translate3dKeys.includes(key)) {
|
||||
translate3dValues[<keyof typeof translate3dValues>key] = <number>val // this was very annoying to get right but I think this should work properly
|
||||
} else if (transformKeys.includes(key)) {
|
||||
flattenedStyles.transform += `${key}(${val}${unit}) `
|
||||
} else if (filterKeys.includes(key)) {
|
||||
flattenedStyles.filter += `${key}(${val}${unit}) `
|
||||
} else {
|
||||
flattenedStyles[<keyof typeof flattenedStyles>key] = `${val}${unit} `
|
||||
}
|
||||
})
|
||||
|
||||
flattenedStyles.transform = `translate3d(${translate3dValues.translateX}px, ${translate3dValues.translateY}px, ${translate3dValues.translateZ}px) ${flattenedStyles.transform}`
|
||||
|
||||
return flattenedStyles
|
||||
}
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY#Notes
|
||||
function getScrollPosition() {
|
||||
const supportPageOffset = window.pageXOffset !== undefined
|
||||
const isCSS1Compat = ((document.compatMode || '') === 'CSS1Compat')
|
||||
|
||||
const x = supportPageOffset ? window.pageXOffset : isCSS1Compat ? document.documentElement.scrollLeft : document.body.scrollLeft
|
||||
const y = supportPageOffset ? window.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop
|
||||
|
||||
return [y, x]
|
||||
}
|
||||
type boxData = { width: number, height: number, x: number, y: number }
|
||||
function parseValue(val: number | string, { width, height, x, y }: boxData, index: number) {
|
||||
if (typeof val === 'number') {
|
||||
return val
|
||||
}
|
||||
if (typeof val === 'string') {
|
||||
const pageHeight = document.body.scrollHeight
|
||||
const pageWidth = document.body.scrollWidth
|
||||
const screenWidth = window.innerWidth
|
||||
const screenHeight = window.innerHeight
|
||||
const [scrollTop, scrollLeft] = getScrollPosition()
|
||||
|
||||
const left = x + scrollLeft
|
||||
const right = left + width
|
||||
const top = y + scrollTop
|
||||
const bottom = top + height
|
||||
|
||||
return Function(`return ${val
|
||||
.replace(/screenWidth/g, String(screenWidth))
|
||||
.replace(/screenHeight/g, String(screenHeight))
|
||||
.replace(/pageHeight/g, String(pageHeight))
|
||||
.replace(/pageWidth/g, String(pageWidth))
|
||||
.replace(/elWidth/g, String(width))
|
||||
.replace(/elHeight/g, String(height))
|
||||
.replace(/elInY/g, String(top - screenHeight))
|
||||
.replace(/elOutY/g, String(bottom))
|
||||
.replace(/elCenterY/g, String(top + (height / 2) - (screenHeight / 2)))
|
||||
.replace(/elInX/g, String(left - screenWidth))
|
||||
.replace(/elOutX/g, String(right))
|
||||
.replace(/elCenterX/g, String(left + (width / 2) - (screenWidth / 2)))
|
||||
.replace(/index/g, String(index))
|
||||
}`)()
|
||||
}
|
||||
}
|
||||
class LaxDriver {
|
||||
getValueFn
|
||||
name = ''
|
||||
lastValue = 0
|
||||
frameStep = 1
|
||||
m1 = 0
|
||||
|
||||
m2 = 0
|
||||
inertia = 0
|
||||
inertiaEnabled = false
|
||||
|
||||
|
||||
constructor(name: string, getValueFn: (frame?: number) => number, options: DriverOptions = {}) {
|
||||
this.name = name
|
||||
this.getValueFn = getValueFn
|
||||
|
||||
this.inertiaEnabled = options.inertiaEnabled
|
||||
this.frameStep = options.frameStep
|
||||
|
||||
this.lastValue = this.getValueFn(0)
|
||||
}
|
||||
|
||||
getValue = (frame: number) => {
|
||||
let value = this.lastValue
|
||||
|
||||
if (frame % this.frameStep === 0) {
|
||||
value = this.getValueFn(frame)
|
||||
}
|
||||
|
||||
if (this.inertiaEnabled) {
|
||||
const delta = value - this.lastValue
|
||||
const damping = 0.8
|
||||
|
||||
this.m1 = this.m1 * damping + delta * (1 - damping)
|
||||
this.m2 = this.m2 * damping + this.m1 * (1 - damping)
|
||||
this.inertia = Math.round(this.m2 * 5000) / 15000
|
||||
}
|
||||
|
||||
this.lastValue = value
|
||||
return [this.lastValue, this.inertia]
|
||||
}
|
||||
}
|
||||
|
||||
class LaxElement {
|
||||
domElement
|
||||
transformsData
|
||||
styles = {}
|
||||
selector = ''
|
||||
|
||||
groupIndex = 0
|
||||
laxInstance
|
||||
|
||||
onUpdate
|
||||
transforms: DriverTransforms
|
||||
|
||||
constructor(selector: string, laxInstance: Lax, domElement: HTMLElement, transformsData: DriverTransforms, groupIndex = 0, options: ElementOptions = {}) {
|
||||
this.selector = selector
|
||||
this.laxInstance = laxInstance
|
||||
this.domElement = domElement
|
||||
this.transformsData = transformsData
|
||||
this.groupIndex = groupIndex
|
||||
|
||||
const { style = {}, onUpdate } = options
|
||||
|
||||
Object.keys(style).forEach(key => {
|
||||
domElement.style.setProperty(key, style[key])
|
||||
})
|
||||
|
||||
if (onUpdate) this.onUpdate = onUpdate
|
||||
|
||||
this.calculateTransforms()
|
||||
}
|
||||
|
||||
update = (driverValues: { [key: string]: Array<number> }, frame: number) => {
|
||||
const { transforms } = this
|
||||
|
||||
const styles: { [key in keyof LaxStyleProps]: string | number } = {}
|
||||
|
||||
for (let driverName in transforms) {
|
||||
const styleBindings = transforms[driverName]
|
||||
|
||||
if (!driverValues[driverName]) {
|
||||
console.error("No lax driver with name: ", driverName)
|
||||
}
|
||||
const [value, inertiaValue] = driverValues[driverName]
|
||||
let key: keyof LaxStyleProps
|
||||
for (key in styleBindings) {
|
||||
if (key !== "presets") {
|
||||
const [arr1, arr2, options = {}] = styleBindings[key]
|
||||
const { modValue, frameStep = 1, easing, inertia, inertiaMode, cssFn, cssUnit = '' } = options
|
||||
|
||||
const easingFn = easings[easing]
|
||||
|
||||
if (frame % frameStep === 0) {
|
||||
const v = modValue ? value % modValue : value
|
||||
|
||||
let interpolatedValue = interpolate(<number[]>arr1, <number[]>arr2, v, easingFn) // because this function is only used internally, this casting is valid
|
||||
|
||||
if (inertia) {
|
||||
let inertiaExtra = inertiaValue * inertia
|
||||
if (inertiaMode === 'absolute') inertiaExtra = Math.abs((inertiaExtra))
|
||||
interpolatedValue += inertiaExtra
|
||||
}
|
||||
|
||||
const unit = cssUnit || pxUnits.includes(key) ? 'px' : (degUnits.includes(key) ? 'deg' : '')
|
||||
const dp = unit === 'px' ? 0 : 3
|
||||
const val = unit === 'px' ? Number.parseFloat(interpolatedValue.toFixed(dp)) : interpolatedValue
|
||||
styles[key] = cssFn ? cssFn(val, this.domElement) : val + cssUnit
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
this.applyStyles(styles)
|
||||
if (this.onUpdate) this.onUpdate(driverValues, this.domElement)
|
||||
}
|
||||
|
||||
calculateTransforms = () => {
|
||||
this.transforms = {}
|
||||
const windowWidth = this.laxInstance.windowWidth
|
||||
let driverName: keyof DriverTransforms
|
||||
for (driverName in this.transformsData) {
|
||||
let styleBindings: LaxStyleProps = this.transformsData[driverName]
|
||||
|
||||
const parsedStyleBindings: { [key in keyof LaxStyleProps]: LaxStyleMap } = {}
|
||||
|
||||
const { presets = <Array<string>>[] } = styleBindings
|
||||
|
||||
presets.forEach((presetString) => {
|
||||
|
||||
const [presetName, y, str] = presetString.split(":")
|
||||
|
||||
const presetFn: LaxPresetFn = window["lax"].presets[<keyof LaxPresetFn>presetName]
|
||||
|
||||
if (!presetFn) {
|
||||
console.error("Lax preset cannot be found with name: ", presetName)
|
||||
} else {
|
||||
const preset = presetFn(y, str)
|
||||
|
||||
Object.keys(preset).forEach((key: keyof LaxPresetStyleProps) => {
|
||||
styleBindings[key] = preset[key]
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
delete styleBindings.presets
|
||||
let key: keyof LaxStyleProps
|
||||
for (key in styleBindings) {
|
||||
if (key !== "presets") { // should always be true in here, but typescript wants to be 100% sure
|
||||
let [arr1 = [-1e9, 1e9], arr2 = [-1e9, 1e9], options = {}] = styleBindings[key]
|
||||
|
||||
const saveTransform = this.domElement.style.transform
|
||||
this.domElement.style.removeProperty("transform")
|
||||
const bounds = this.domElement.getBoundingClientRect()
|
||||
this.domElement.style.transform = saveTransform
|
||||
|
||||
const parsedArr1 = getArrayValues(<Array<number>>arr1, windowWidth).map(i => parseValue(i, bounds, this.groupIndex)) // should always work here
|
||||
const parsedArr2 = getArrayValues(<Array<number>>arr2, windowWidth).map(i => parseValue(i, bounds, this.groupIndex)) // should always work here
|
||||
|
||||
parsedStyleBindings[key] = [parsedArr1, parsedArr2, options]
|
||||
}
|
||||
}
|
||||
this.transforms[driverName] = parsedStyleBindings
|
||||
}
|
||||
}
|
||||
|
||||
applyStyles = (styles: { [key in keyof LaxStyleProps]: number | string }) => {
|
||||
const mergedStyles = flattenStyles(styles)
|
||||
|
||||
Object.keys(mergedStyles).forEach((key: "transform" | "filter") => {
|
||||
this.domElement.style.setProperty(key, mergedStyles[key])
|
||||
})
|
||||
}
|
||||
}
|
||||
class Lax {
|
||||
private drivers = <LaxDriver[]>[]
|
||||
private elements: Array<LaxElement> = []
|
||||
private frame = 0
|
||||
|
||||
private debug = false
|
||||
|
||||
windowWidth = 0
|
||||
windowHeight = 0
|
||||
presets = laxPresets
|
||||
|
||||
private debugData = {
|
||||
frameLengths: <Array<number>>[],
|
||||
frameStart: 0
|
||||
}
|
||||
|
||||
init = () => {
|
||||
this.findAndAddElements()
|
||||
|
||||
window.requestAnimationFrame(this.onAnimationFrame)
|
||||
this.windowWidth = document.body.clientWidth
|
||||
this.windowHeight = document.body.clientHeight
|
||||
|
||||
window.onresize = this.onWindowResize
|
||||
}
|
||||
|
||||
onWindowResize = () => {
|
||||
const changed = document.body.clientWidth !== this.windowWidth ||
|
||||
document.body.clientHeight !== this.windowHeight
|
||||
|
||||
if (changed) {
|
||||
this.windowWidth = document.body.clientWidth
|
||||
this.windowHeight = document.body.clientHeight
|
||||
this.elements.forEach(el => el.calculateTransforms())
|
||||
}
|
||||
}
|
||||
|
||||
onAnimationFrame = (e: DOMHighResTimeStamp) => {
|
||||
if (this.debug) {
|
||||
this.debugData["frameStart"] = Date.now()
|
||||
}
|
||||
|
||||
const driverValues: { [key: string]: Array<number> } = {}
|
||||
|
||||
this.drivers.forEach((driver) => {
|
||||
driverValues[driver.name] = driver.getValue(this.frame)
|
||||
})
|
||||
|
||||
this.elements.forEach((element) => {
|
||||
element.update(driverValues, this.frame)
|
||||
})
|
||||
|
||||
if (this.debug) {
|
||||
this.debugData.frameLengths.push(Date.now() - this.debugData["frameStart"])
|
||||
}
|
||||
|
||||
if (this.frame % 60 === 0 && this.debug) {
|
||||
const averageFrameTime = Math.ceil((this.debugData.frameLengths.reduce((a, b) => a + b, 0) / 60))
|
||||
console.log(`Average frame calculation time: ${averageFrameTime}ms`)
|
||||
this.debugData.frameLengths = []
|
||||
}
|
||||
|
||||
this.frame++
|
||||
|
||||
window.requestAnimationFrame(this.onAnimationFrame)
|
||||
}
|
||||
|
||||
addDriver = (name: string, getValueFn: () => number, options: DriverOptions = {}) => {
|
||||
this.drivers.push(
|
||||
new LaxDriver(name, getValueFn, options)
|
||||
)
|
||||
}
|
||||
|
||||
removeDriver = (name: string) => {
|
||||
this.drivers = this.drivers.filter(driver => driver.name !== name)
|
||||
}
|
||||
|
||||
findAndAddElements = () => {
|
||||
this.elements = []
|
||||
const elements = document.querySelectorAll(".lax")
|
||||
|
||||
elements.forEach((domElement: HTMLElement | Element) => {
|
||||
const driverName = "scrollY"
|
||||
const presets: Array<LaxPresetName> = []
|
||||
|
||||
domElement.classList.forEach((className) => {
|
||||
if (className.includes("lax_preset")) {
|
||||
const preset = className.replace("lax_preset_", "")
|
||||
if (isPresetName(preset))
|
||||
presets.push(preset)
|
||||
}
|
||||
})
|
||||
|
||||
const transforms = {
|
||||
[driverName]: {
|
||||
presets
|
||||
}
|
||||
}
|
||||
|
||||
this.elements.push(new LaxElement('.lax', this, <HTMLElement>domElement, transforms, 0))
|
||||
})
|
||||
}
|
||||
|
||||
addElements = (selector: string, transforms: DriverTransforms, options?: ElementOptions) => {
|
||||
const domElements = options.domElements || document.querySelectorAll(selector)
|
||||
|
||||
domElements.forEach((domElement, i) => {
|
||||
this.elements.push(new LaxElement(selector, this, <HTMLElement>domElement, transforms, i, options))
|
||||
})
|
||||
}
|
||||
|
||||
removeElements = (selector: string) => {
|
||||
this.elements = this.elements.filter(element => element.selector !== selector)
|
||||
}
|
||||
|
||||
addElement = (domElement: HTMLElement | Element, transforms: DriverTransforms, options?: ElementOptions) => {
|
||||
this.elements.push(new LaxElement('', this, <HTMLElement>domElement, transforms, 0, options))
|
||||
}
|
||||
|
||||
removeElement = (domElement: HTMLElement | Element) => {
|
||||
this.elements = this.elements.filter(element => element.domElement !== domElement)
|
||||
}
|
||||
}
|
||||
|
||||
export const laxInstance = new Lax()
|
||||
const lax = {
|
||||
addElements: laxInstance.addElements,
|
||||
removeElements: laxInstance.removeElements,
|
||||
removeElement: laxInstance.removeElement,
|
||||
addElement: laxInstance.addElement,
|
||||
init: laxInstance.init,
|
||||
addDriver: laxInstance.addDriver,
|
||||
removeDriver: laxInstance.removeDriver,
|
||||
presets: laxInstance.presets,
|
||||
}
|
||||
// needed because window, and global don't have lax on them initially
|
||||
|
||||
declare global {
|
||||
namespace NodeJS {
|
||||
interface Global {
|
||||
lax: typeof lax
|
||||
}
|
||||
}
|
||||
interface Window {
|
||||
lax: typeof lax
|
||||
}
|
||||
};
|
||||
|
||||
(() => {
|
||||
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined')
|
||||
module.exports = lax
|
||||
else if (window)
|
||||
window.lax = lax
|
||||
else if (global)
|
||||
global["lax"] = lax
|
||||
})()
|
||||
|
||||
export default lax
|
||||
export const { addDriver, addElement, addElements, removeDriver, removeElement, removeElements, init, presets } = lax
|
||||
130
src/types.ts
Normal file
130
src/types.ts
Normal file
@@ -0,0 +1,130 @@
|
||||
export interface DriverOptions {
|
||||
inertiaEnabled?: boolean
|
||||
frameStep?: number
|
||||
}
|
||||
export interface StyleObject {
|
||||
[key: string]: any
|
||||
}
|
||||
export type LaxPresetName =
|
||||
"fadeIn" |
|
||||
"fadeOut" |
|
||||
"fadeInOut" |
|
||||
"scaleIn" |
|
||||
"scaleOut" |
|
||||
"scaleInOut" |
|
||||
"slideX" |
|
||||
"slideY" |
|
||||
"jiggle" |
|
||||
"seesaw" |
|
||||
"zigzag" |
|
||||
"hueRotate" |
|
||||
"spin" |
|
||||
"flipX" |
|
||||
"flipY" |
|
||||
"blurIn" |
|
||||
"blurOut" |
|
||||
"blurInOut"
|
||||
|
||||
|
||||
export type LaxPresetFn = (x: number | string, y: number | string) => LaxPresetStyleProps
|
||||
|
||||
export type easingOptions =
|
||||
"easeInQuad" |
|
||||
"easeOutQuad" |
|
||||
"easeInOutQuad" |
|
||||
"easeInCubic" |
|
||||
"easeOutCubic" |
|
||||
"easeInOutCubic" |
|
||||
"easeInQuart" |
|
||||
"easeOutQuart" |
|
||||
"easeInOutQuart" |
|
||||
"easeInQuint" |
|
||||
"easeOutQuint" |
|
||||
"easeInOutQuint" |
|
||||
"easeOutBounce" |
|
||||
"easeInBounce" |
|
||||
"easeOutBack" |
|
||||
"easeInBack"
|
||||
|
||||
export type specialValues =
|
||||
"screenWidth" |
|
||||
"screenHeight" |
|
||||
"pageWidth" |
|
||||
"pageHeight" |
|
||||
"elWidth" |
|
||||
"elHeight" |
|
||||
"elInY" |
|
||||
"elOutY" |
|
||||
"elCenterY" |
|
||||
"elInX" |
|
||||
"elOutX" |
|
||||
"elCenterX" |
|
||||
"index"
|
||||
|
||||
export enum cssValues {
|
||||
"opacity" = `opacity`,
|
||||
"scaleX" = "scaleX",
|
||||
"scaleY" = "scaleY",
|
||||
"scale" = "scale",
|
||||
"skewX" = "skewX",
|
||||
"skewY" = "skewY",
|
||||
"skew" = "skew",
|
||||
"rotateX" = "rotateX",
|
||||
"rotateY" = "rotateY",
|
||||
"rotate" = "rotate",
|
||||
"translateX" = `translateX`,
|
||||
"translateY" = "translateY",
|
||||
"translateZ" = "translateZ",
|
||||
"blur" = "blur",
|
||||
"hue-rotate" = "hue-rotate",
|
||||
"brightness" = "brightness"
|
||||
}
|
||||
export interface LaxStyleMapOptions {
|
||||
modValue?: number | undefined
|
||||
frameStep?: number
|
||||
inertia?: number
|
||||
inertiaMode?: "normal" | "absolute"
|
||||
cssUnit?: string
|
||||
cssFn?(value: number, domElement: HTMLElement | Element): number | string
|
||||
easing?: easingOptions
|
||||
}
|
||||
export type LaxStyleMap = [
|
||||
Array<number | specialValues | string>,
|
||||
Array<number | specialValues | string>,
|
||||
LaxStyleMapOptions?
|
||||
]
|
||||
export interface LaxStyleProps extends LaxPresetStyleProps {
|
||||
"presets"?: Array<LaxPresetName>
|
||||
}
|
||||
|
||||
export interface LaxPresetStyleProps {
|
||||
"opacity"?: LaxStyleMap
|
||||
"scaleX"?: LaxStyleMap
|
||||
"scaleY"?: LaxStyleMap
|
||||
"scale"?: LaxStyleMap
|
||||
"skewX"?: LaxStyleMap
|
||||
"skewY"?: LaxStyleMap
|
||||
"skew"?: LaxStyleMap
|
||||
"rotateX"?: LaxStyleMap
|
||||
"rotateY"?: LaxStyleMap
|
||||
"rotate"?: LaxStyleMap
|
||||
"translateX"?: LaxStyleMap
|
||||
"translateY"?: LaxStyleMap
|
||||
"translateZ"?: LaxStyleMap
|
||||
"blur"?: LaxStyleMap
|
||||
"hue-rotate"?: LaxStyleMap
|
||||
"brightness"?: LaxStyleMap
|
||||
}
|
||||
|
||||
|
||||
export interface ElementOptions {
|
||||
style?: StyleObject
|
||||
domElements?: Array<HTMLElement | Element>
|
||||
onUpdate?(driverValues: any, domElement: HTMLElement | Element): void
|
||||
}
|
||||
type DriverName = string
|
||||
export interface DriverTransforms {
|
||||
[key: string]: LaxStyleProps | LaxPresetStyleProps
|
||||
}
|
||||
|
||||
|
||||
20
tsconfig.json
Normal file
20
tsconfig.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES5",
|
||||
"lib": ["es5", "es6", "es2017", "dom"],
|
||||
"module": "CommonJS",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": true,
|
||||
"strict": false,
|
||||
"composite": true,
|
||||
"noImplicitAny": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"rootDir": "src",
|
||||
"outDir": "lib"
|
||||
},
|
||||
"include": [
|
||||
"./src/**/*"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user