chnobli 0.1.8 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +9 -5
- package/src/animation/Animation.ts +2 -2
- package/src/animation/public.ts +39 -5
- package/src/chnobli.ts +15 -11
- package/src/property/Property.ts +2 -0
- package/src/property/StyleProperty.ts +2 -2
- package/src/scroll/Scroll.ts +172 -88
- package/src/scroll/index.ts +8 -0
- package/src/scroll/public.ts +23 -12
- package/src/stagger/stagger.ts +28 -14
- package/src/target/ObjectTarget.ts +124 -0
- package/src/target/Target.ts +13 -0
- package/src/tests/properties.test.ts +51 -1
- package/src/timeline/Nested.ts +1 -1
- package/src/timeline/{TimeLine.ts → Timeline.ts} +21 -1
- package/src/timeline/public.ts +168 -47
- package/src/timing/Timing.ts +37 -3
- package/src/utils/internal.ts +6 -3
- package/src/utils/utils.ts +16 -7
- package/src/values/StyleValue.ts +13 -1
- package/tsconfig.json +0 -1
- package/.editorconfig +0 -11
- package/.github/workflows/ci.yaml +0 -34
- package/.prettierignore +0 -4
- package/.prettierrc +0 -6
- package/.vscode/settings.json +0 -4
- package/LICENSE.md +0 -21
- package/README.md +0 -5
- package/auto-docs/easing.js.html +0 -342
- package/auto-docs/fonts/OpenSans-Bold-webfont.eot +0 -0
- package/auto-docs/fonts/OpenSans-Bold-webfont.svg +0 -1830
- package/auto-docs/fonts/OpenSans-Bold-webfont.woff +0 -0
- package/auto-docs/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
- package/auto-docs/fonts/OpenSans-BoldItalic-webfont.svg +0 -1830
- package/auto-docs/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
- package/auto-docs/fonts/OpenSans-Italic-webfont.eot +0 -0
- package/auto-docs/fonts/OpenSans-Italic-webfont.svg +0 -1830
- package/auto-docs/fonts/OpenSans-Italic-webfont.woff +0 -0
- package/auto-docs/fonts/OpenSans-Light-webfont.eot +0 -0
- package/auto-docs/fonts/OpenSans-Light-webfont.svg +0 -1831
- package/auto-docs/fonts/OpenSans-Light-webfont.woff +0 -0
- package/auto-docs/fonts/OpenSans-LightItalic-webfont.eot +0 -0
- package/auto-docs/fonts/OpenSans-LightItalic-webfont.svg +0 -1835
- package/auto-docs/fonts/OpenSans-LightItalic-webfont.woff +0 -0
- package/auto-docs/fonts/OpenSans-Regular-webfont.eot +0 -0
- package/auto-docs/fonts/OpenSans-Regular-webfont.svg +0 -1831
- package/auto-docs/fonts/OpenSans-Regular-webfont.woff +0 -0
- package/auto-docs/global.html +0 -4810
- package/auto-docs/index.html +0 -65
- package/auto-docs/scripts/linenumber.js +0 -25
- package/auto-docs/scripts/prettify/Apache-License-2.0.txt +0 -202
- package/auto-docs/scripts/prettify/lang-css.js +0 -2
- package/auto-docs/scripts/prettify/prettify.js +0 -28
- package/auto-docs/styles/jsdoc-default.css +0 -358
- package/auto-docs/styles/prettify-jsdoc.css +0 -111
- package/auto-docs/styles/prettify-tomorrow.css +0 -132
- package/dist/animation/Animation.d.ts +0 -36
- package/dist/animation/Animation.d.ts.map +0 -1
- package/dist/animation/Animation.js +0 -230
- package/dist/animation/Animation.js.map +0 -1
- package/dist/animation/public.d.ts +0 -58
- package/dist/animation/public.d.ts.map +0 -1
- package/dist/animation/public.js +0 -107
- package/dist/animation/public.js.map +0 -1
- package/dist/chnobli.d.ts +0 -16
- package/dist/chnobli.d.ts.map +0 -1
- package/dist/chnobli.js +0 -63
- package/dist/chnobli.js.map +0 -1
- package/dist/property/BasicProperty.d.ts +0 -38
- package/dist/property/BasicProperty.d.ts.map +0 -1
- package/dist/property/BasicProperty.js +0 -72
- package/dist/property/BasicProperty.js.map +0 -1
- package/dist/property/ClassProperty.d.ts +0 -32
- package/dist/property/ClassProperty.d.ts.map +0 -1
- package/dist/property/ClassProperty.js +0 -108
- package/dist/property/ClassProperty.js.map +0 -1
- package/dist/property/Property.d.ts +0 -13
- package/dist/property/Property.d.ts.map +0 -1
- package/dist/property/Property.js +0 -20
- package/dist/property/Property.js.map +0 -1
- package/dist/property/StyleProperty.d.ts +0 -25
- package/dist/property/StyleProperty.d.ts.map +0 -1
- package/dist/property/StyleProperty.js +0 -221
- package/dist/property/StyleProperty.js.map +0 -1
- package/dist/property/TransformProperty.d.ts +0 -15
- package/dist/property/TransformProperty.d.ts.map +0 -1
- package/dist/property/TransformProperty.js +0 -43
- package/dist/property/TransformProperty.js.map +0 -1
- package/dist/property/TransformXYProperty.d.ts +0 -28
- package/dist/property/TransformXYProperty.d.ts.map +0 -1
- package/dist/property/TransformXYProperty.js +0 -65
- package/dist/property/TransformXYProperty.js.map +0 -1
- package/dist/responsive/ResponsiveEvent.d.ts +0 -17
- package/dist/responsive/ResponsiveEvent.d.ts.map +0 -1
- package/dist/responsive/ResponsiveEvent.js +0 -45
- package/dist/responsive/ResponsiveEvent.js.map +0 -1
- package/dist/responsive/TestEvent.d.ts +0 -11
- package/dist/responsive/TestEvent.d.ts.map +0 -1
- package/dist/responsive/TestEvent.js +0 -26
- package/dist/responsive/TestEvent.js.map +0 -1
- package/dist/scroll/Scroll.d.ts +0 -27
- package/dist/scroll/Scroll.d.ts.map +0 -1
- package/dist/scroll/Scroll.js +0 -132
- package/dist/scroll/Scroll.js.map +0 -1
- package/dist/scroll/ScrollEvent.d.ts +0 -17
- package/dist/scroll/ScrollEvent.d.ts.map +0 -1
- package/dist/scroll/ScrollEvent.js +0 -39
- package/dist/scroll/ScrollEvent.js.map +0 -1
- package/dist/scroll/public.d.ts +0 -7
- package/dist/scroll/public.d.ts.map +0 -1
- package/dist/scroll/public.js +0 -17
- package/dist/scroll/public.js.map +0 -1
- package/dist/stagger/stagger.d.ts +0 -19
- package/dist/stagger/stagger.d.ts.map +0 -1
- package/dist/stagger/stagger.js +0 -41
- package/dist/stagger/stagger.js.map +0 -1
- package/dist/target/BaseTarget.old.d.ts +0 -33
- package/dist/target/BaseTarget.old.d.ts.map +0 -1
- package/dist/target/BaseTarget.old.js +0 -73
- package/dist/target/BaseTarget.old.js.map +0 -1
- package/dist/target/DomTarget.d.ts +0 -41
- package/dist/target/DomTarget.d.ts.map +0 -1
- package/dist/target/DomTarget.js +0 -230
- package/dist/target/DomTarget.js.map +0 -1
- package/dist/target/Target.d.ts +0 -22
- package/dist/target/Target.d.ts.map +0 -1
- package/dist/target/Target.js +0 -21
- package/dist/target/Target.js.map +0 -1
- package/dist/target/TestDomNode.d.ts +0 -14
- package/dist/target/TestDomNode.d.ts.map +0 -1
- package/dist/target/TestDomNode.js +0 -55
- package/dist/target/TestDomNode.js.map +0 -1
- package/dist/timeline/Nested.d.ts +0 -30
- package/dist/timeline/Nested.d.ts.map +0 -1
- package/dist/timeline/Nested.js +0 -51
- package/dist/timeline/Nested.js.map +0 -1
- package/dist/timeline/TimeLine.d.ts +0 -32
- package/dist/timeline/TimeLine.d.ts.map +0 -1
- package/dist/timeline/TimeLine.js +0 -288
- package/dist/timeline/TimeLine.js.map +0 -1
- package/dist/timeline/public.d.ts +0 -135
- package/dist/timeline/public.d.ts.map +0 -1
- package/dist/timeline/public.js +0 -316
- package/dist/timeline/public.js.map +0 -1
- package/dist/timing/AnimationFrameTicker.d.ts +0 -32
- package/dist/timing/AnimationFrameTicker.d.ts.map +0 -1
- package/dist/timing/AnimationFrameTicker.js +0 -134
- package/dist/timing/AnimationFrameTicker.js.map +0 -1
- package/dist/timing/Ease.d.ts +0 -6
- package/dist/timing/Ease.d.ts.map +0 -1
- package/dist/timing/Ease.js +0 -15
- package/dist/timing/Ease.js.map +0 -1
- package/dist/timing/TestTicker.d.ts +0 -19
- package/dist/timing/TestTicker.d.ts.map +0 -1
- package/dist/timing/TestTicker.js +0 -81
- package/dist/timing/TestTicker.js.map +0 -1
- package/dist/timing/Ticker.d.ts +0 -14
- package/dist/timing/Ticker.d.ts.map +0 -1
- package/dist/timing/Ticker.js +0 -2
- package/dist/timing/Ticker.js.map +0 -1
- package/dist/timing/Timing.d.ts +0 -62
- package/dist/timing/Timing.d.ts.map +0 -1
- package/dist/timing/Timing.js +0 -257
- package/dist/timing/Timing.js.map +0 -1
- package/dist/timing/easing.d.ts +0 -158
- package/dist/timing/easing.d.ts.map +0 -1
- package/dist/timing/easing.js +0 -273
- package/dist/timing/easing.js.map +0 -1
- package/dist/utils/Events.d.ts +0 -9
- package/dist/utils/Events.d.ts.map +0 -1
- package/dist/utils/Events.js +0 -35
- package/dist/utils/Events.js.map +0 -1
- package/dist/utils/internal.d.ts +0 -2
- package/dist/utils/internal.d.ts.map +0 -1
- package/dist/utils/internal.js +0 -6
- package/dist/utils/internal.js.map +0 -1
- package/dist/utils/motionpath.d.ts +0 -16
- package/dist/utils/motionpath.d.ts.map +0 -1
- package/dist/utils/motionpath.js +0 -41
- package/dist/utils/motionpath.js.map +0 -1
- package/dist/utils/utils.d.ts +0 -43
- package/dist/utils/utils.d.ts.map +0 -1
- package/dist/utils/utils.js +0 -93
- package/dist/utils/utils.js.map +0 -1
- package/dist/values/ColorValue.d.ts +0 -12
- package/dist/values/ColorValue.d.ts.map +0 -1
- package/dist/values/ColorValue.js +0 -133
- package/dist/values/ColorValue.js.map +0 -1
- package/dist/values/StyleValue.d.ts +0 -40
- package/dist/values/StyleValue.d.ts.map +0 -1
- package/dist/values/StyleValue.js +0 -149
- package/dist/values/StyleValue.js.map +0 -1
- package/dist/values/Value.d.ts +0 -13
- package/dist/values/Value.d.ts.map +0 -1
- package/dist/values/Value.js +0 -38
- package/dist/values/Value.js.map +0 -1
- package/dist/values/defaultcolors.d.ts +0 -2
- package/dist/values/defaultcolors.d.ts.map +0 -1
- package/dist/values/defaultcolors.js +0 -149
- package/dist/values/defaultcolors.js.map +0 -1
- package/docs/INDEX.md +0 -15
- package/jsr.json +0 -9
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chnobli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"author": "Sören Meier <info@soerenmeier.ch>",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"docs": "jsdoc -c jsdoc.conf.json",
|
|
8
8
|
"check": "tsc",
|
|
9
9
|
"lint": "eslint ./src",
|
|
10
|
-
"test": "node --expose-gc
|
|
11
|
-
"test:watch": "node --expose-gc
|
|
10
|
+
"test": "node --expose-gc ../node_modules/.bin/vitest run",
|
|
11
|
+
"test:watch": "node --expose-gc ../node_modules/.bin/vitest",
|
|
12
12
|
"build": "tsc -p tsconfig.build.json",
|
|
13
|
-
"watch": "tsc -w"
|
|
13
|
+
"watch": "tsc -w -p tsconfig.build.json"
|
|
14
14
|
},
|
|
15
15
|
"repository": {
|
|
16
16
|
"type": "git",
|
|
@@ -26,6 +26,10 @@
|
|
|
26
26
|
"import": "./dist/utils/utils.js",
|
|
27
27
|
"types": "./dist/utils/utils.d.ts"
|
|
28
28
|
},
|
|
29
|
+
"./scroll": {
|
|
30
|
+
"import": "./dist/scroll/index.js",
|
|
31
|
+
"types": "./dist/scroll/index.d.ts"
|
|
32
|
+
},
|
|
29
33
|
".": {
|
|
30
34
|
"import": "./dist/chnobli.js",
|
|
31
35
|
"types": "./dist/chnobli.d.ts"
|
|
@@ -41,6 +45,6 @@
|
|
|
41
45
|
},
|
|
42
46
|
"dependencies": {
|
|
43
47
|
"bezier-easing": "^2.1.0",
|
|
44
|
-
"fire": "npm:fire-lib-js@^0.3.0
|
|
48
|
+
"fire": "npm:fire-lib-js@^0.3.0"
|
|
45
49
|
}
|
|
46
50
|
}
|
|
@@ -116,6 +116,7 @@ class PropertyAnimation<V> {
|
|
|
116
116
|
private valueFn: ((pos: number) => ParseableValue) | null;
|
|
117
117
|
|
|
118
118
|
private iniResponsive: any;
|
|
119
|
+
// todo i don't think the types match here?
|
|
119
120
|
private iniFrom: V | null;
|
|
120
121
|
private iniTo: V | null;
|
|
121
122
|
|
|
@@ -166,8 +167,7 @@ class PropertyAnimation<V> {
|
|
|
166
167
|
|
|
167
168
|
// init via responsive fn
|
|
168
169
|
if (this.iniResponsive) {
|
|
169
|
-
|
|
170
|
-
const value = this.iniResponsive((target as any).target);
|
|
170
|
+
const value = this.iniResponsive(target.inner());
|
|
171
171
|
|
|
172
172
|
if (typeof value === 'object') {
|
|
173
173
|
if ('from' in value) from = this.prop.parseValue(value.from);
|
package/src/animation/public.ts
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import { takeProp } from '../utils/internal.js';
|
|
2
2
|
import Timeline from '../timeline/public.js';
|
|
3
|
-
import { staggerMap } from '../stagger/stagger.js';
|
|
3
|
+
import Stagger, { staggerMap } from '../stagger/stagger.js';
|
|
4
|
+
import { Targets } from '../chnobli.js';
|
|
5
|
+
|
|
6
|
+
export type AnimationProps = {
|
|
7
|
+
autoplay?: boolean;
|
|
8
|
+
delay?: number | string | Stagger<number | string>;
|
|
9
|
+
|
|
10
|
+
ease?: (t: number) => number;
|
|
11
|
+
|
|
12
|
+
onStart?: () => void;
|
|
13
|
+
onEnd?: () => void;
|
|
14
|
+
|
|
15
|
+
// other properties
|
|
16
|
+
[key: string]: any;
|
|
17
|
+
};
|
|
4
18
|
|
|
5
19
|
/**
|
|
6
20
|
* The animation consist of a timeline with just one animation
|
|
@@ -12,16 +26,36 @@ import { staggerMap } from '../stagger/stagger.js';
|
|
|
12
26
|
export default class PublicAnimation {
|
|
13
27
|
private _tl: Timeline;
|
|
14
28
|
|
|
15
|
-
constructor(targets:
|
|
29
|
+
constructor(targets: Targets, props: AnimationProps = {}) {
|
|
16
30
|
const autoplay = parseAutoplay(takeProp(props, 'autoplay', true));
|
|
17
|
-
const delay = takeProp(props, 'delay', 0);
|
|
31
|
+
const delay = takeProp<number>(props, 'delay', 0);
|
|
18
32
|
|
|
19
33
|
// we don't wan't the ease and duration on the timeline
|
|
20
|
-
const ease = takeProp(props, 'ease',
|
|
21
|
-
const duration = takeProp
|
|
34
|
+
const ease = takeProp<AnimationProps['ease']>(props, 'ease', undefined);
|
|
35
|
+
const duration = takeProp<number | undefined>(
|
|
36
|
+
props,
|
|
37
|
+
'duration',
|
|
38
|
+
undefined,
|
|
39
|
+
);
|
|
22
40
|
|
|
23
41
|
this._tl = new Timeline(props);
|
|
24
42
|
|
|
43
|
+
// events
|
|
44
|
+
const onStart = takeProp<AnimationProps['onStart']>(
|
|
45
|
+
props,
|
|
46
|
+
'onStart',
|
|
47
|
+
undefined,
|
|
48
|
+
);
|
|
49
|
+
if (onStart) this._tl.on('start', onStart);
|
|
50
|
+
|
|
51
|
+
// events
|
|
52
|
+
const onEnd = takeProp<AnimationProps['onEnd']>(
|
|
53
|
+
props,
|
|
54
|
+
'onEnd',
|
|
55
|
+
undefined,
|
|
56
|
+
);
|
|
57
|
+
if (onEnd) this._tl.on('end', onEnd);
|
|
58
|
+
|
|
25
59
|
props.ease = ease;
|
|
26
60
|
props.duration = duration;
|
|
27
61
|
|
package/src/chnobli.ts
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
import Animation from './animation/public.js';
|
|
1
|
+
import Animation, { AnimationProps } from './animation/public.js';
|
|
2
2
|
import Timeline from './timeline/public.js';
|
|
3
|
-
import
|
|
4
|
-
import
|
|
3
|
+
import Stagger, { type StaggerValue } from './stagger/stagger.js';
|
|
4
|
+
import type { Targets, AnimationTarget } from './target/Target.js';
|
|
5
5
|
|
|
6
|
-
export type {
|
|
6
|
+
export type {
|
|
7
|
+
Animation,
|
|
8
|
+
Timeline,
|
|
9
|
+
Stagger,
|
|
10
|
+
Targets,
|
|
11
|
+
AnimationTarget,
|
|
12
|
+
StaggerValue,
|
|
13
|
+
AnimationProps,
|
|
14
|
+
};
|
|
7
15
|
|
|
8
16
|
// todo maybe add, to, from and fromTo to the animate function
|
|
9
17
|
|
|
@@ -14,8 +22,8 @@ export type { Animation, Timeline, Stagger, Scroll };
|
|
|
14
22
|
*
|
|
15
23
|
*/
|
|
16
24
|
export function animate(
|
|
17
|
-
targets:
|
|
18
|
-
props:
|
|
25
|
+
targets: Targets,
|
|
26
|
+
props: AnimationProps = {},
|
|
19
27
|
): Animation {
|
|
20
28
|
return new Animation(targets, props);
|
|
21
29
|
}
|
|
@@ -24,14 +32,10 @@ export function timeline(props: Record<string, any> = {}): Timeline {
|
|
|
24
32
|
return new Timeline(props);
|
|
25
33
|
}
|
|
26
34
|
|
|
27
|
-
export function stagger(value:
|
|
35
|
+
export function stagger<O>(value: StaggerValue<O>): Stagger<O> {
|
|
28
36
|
return new Stagger(value);
|
|
29
37
|
}
|
|
30
38
|
|
|
31
|
-
export function scroll(props: Record<string, any> = {}): Scroll {
|
|
32
|
-
return new Scroll(props);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
39
|
/*
|
|
36
40
|
|
|
37
41
|
animate(target, {
|
package/src/property/Property.ts
CHANGED
|
@@ -20,6 +20,8 @@ export default interface Property<V, I = V> {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export function newProperty(prop: string, targetType = ''): Property<any> {
|
|
23
|
+
if (targetType === 'object') return new StyleProperty(prop, false);
|
|
24
|
+
|
|
23
25
|
if (targetType !== 'dom')
|
|
24
26
|
throw new Error('only dom is supported as target');
|
|
25
27
|
|
|
@@ -41,13 +41,13 @@ export default class StyleProperty
|
|
|
41
41
|
|
|
42
42
|
private _defaultValue: StyleValue | null;
|
|
43
43
|
|
|
44
|
-
constructor(name: string) {
|
|
44
|
+
constructor(name: string, useDefaults: boolean = true) {
|
|
45
45
|
this.name = name;
|
|
46
46
|
|
|
47
47
|
this.from = null;
|
|
48
48
|
this.to = null;
|
|
49
49
|
|
|
50
|
-
const def = STYLE_PROPS[name];
|
|
50
|
+
const def = useDefaults ? STYLE_PROPS[name] : undefined;
|
|
51
51
|
if (Array.isArray(def)) {
|
|
52
52
|
this._defaultValue = new StyleValue([new Value(def[0], def[1])]);
|
|
53
53
|
this.unit = def[1];
|
package/src/scroll/Scroll.ts
CHANGED
|
@@ -1,9 +1,29 @@
|
|
|
1
|
-
import PublicTimeline from '../timeline/public.js';
|
|
2
|
-
import { takeProp } from '../utils/internal.js';
|
|
1
|
+
import PublicTimeline, { Offset } from '../timeline/public.js';
|
|
3
2
|
import { pageOffset } from '../utils/utils.js';
|
|
4
3
|
import ScrollEvent from './ScrollEvent.js';
|
|
5
4
|
|
|
6
5
|
/*
|
|
6
|
+
run timelines based on the scroll position
|
|
7
|
+
|
|
8
|
+
scroll allows to specify a start and end trigger
|
|
9
|
+
which then makes sure the timeline is always in sync with
|
|
10
|
+
the scroll position
|
|
11
|
+
|
|
12
|
+
{
|
|
13
|
+
start: myDiv,
|
|
14
|
+
// when the top of myDiv is at the top of the viewport
|
|
15
|
+
end: {
|
|
16
|
+
target: myDiv,
|
|
17
|
+
offset: 'bottom',
|
|
18
|
+
view: 'bottom'
|
|
19
|
+
}
|
|
20
|
+
// when the bottom of myDiv is at the bottom of the viewport
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
7
27
|
run animation when in view (start stop resume when different events happen)
|
|
8
28
|
|
|
9
29
|
|
|
@@ -24,57 +44,76 @@ scroll pin (once in trigger zone, elements keeps it position relative to start o
|
|
|
24
44
|
parallax
|
|
25
45
|
*/
|
|
26
46
|
|
|
27
|
-
type
|
|
47
|
+
export type ScrollTrigger =
|
|
48
|
+
| {
|
|
49
|
+
target: HTMLElement;
|
|
50
|
+
offset?: OffsetValue;
|
|
51
|
+
view?: OffsetValue;
|
|
52
|
+
}
|
|
53
|
+
| HTMLElement;
|
|
54
|
+
|
|
55
|
+
export type OffsetValue = 'top' | 'center' | 'bottom' | number;
|
|
56
|
+
|
|
57
|
+
export type ParsedScrollTrigger = {
|
|
28
58
|
target: HTMLElement;
|
|
29
59
|
offset: number;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
export type Start = {
|
|
33
|
-
y: number;
|
|
34
60
|
view: number;
|
|
61
|
+
position: Position;
|
|
35
62
|
};
|
|
36
63
|
|
|
37
|
-
export type
|
|
64
|
+
export type ScrollOffset = {
|
|
65
|
+
// the offset in pixels
|
|
38
66
|
y: number;
|
|
67
|
+
// the offset in percentage (0-1)
|
|
39
68
|
view: number;
|
|
69
|
+
// position
|
|
70
|
+
position: number;
|
|
40
71
|
};
|
|
41
72
|
|
|
42
|
-
export
|
|
43
|
-
private _start: StartEndOffset;
|
|
44
|
-
private _end: StartEndOffset | null;
|
|
45
|
-
private _globalEvent: ScrollEvent;
|
|
73
|
+
export type Position = number | string;
|
|
46
74
|
|
|
47
|
-
|
|
48
|
-
|
|
75
|
+
export default class ScrollTimeline {
|
|
76
|
+
private _initialized: boolean;
|
|
77
|
+
private _globalEvent: ScrollEvent;
|
|
78
|
+
private _rmEvent: () => void;
|
|
49
79
|
|
|
80
|
+
private _triggers: ParsedScrollTrigger[];
|
|
50
81
|
private timelines: PublicTimeline[];
|
|
51
|
-
|
|
52
|
-
private _initialized: boolean;
|
|
82
|
+
offsets: ScrollOffset[];
|
|
53
83
|
|
|
54
|
-
constructor(
|
|
55
|
-
|
|
56
|
-
this._start = parseStart(takeProp(props, 'start', null));
|
|
57
|
-
// { target, offset }
|
|
58
|
-
this._end = parseEnd(takeProp(props, 'end', null));
|
|
84
|
+
constructor() {
|
|
85
|
+
this._initialized = false;
|
|
59
86
|
this._globalEvent = ScrollEvent.global();
|
|
87
|
+
this._rmEvent = this._globalEvent.add(y => this._onScroll(y)).remove;
|
|
60
88
|
|
|
61
|
-
this.
|
|
62
|
-
// px
|
|
63
|
-
y: 0,
|
|
64
|
-
// percentage
|
|
65
|
-
view: parseOffset(takeProp(props, 'startView', 'top')),
|
|
66
|
-
};
|
|
67
|
-
this.end = {
|
|
68
|
-
// px
|
|
69
|
-
y: 0,
|
|
70
|
-
// percentage
|
|
71
|
-
view: parseOffset(takeProp(props, 'endView', 'bottom')),
|
|
72
|
-
};
|
|
73
|
-
|
|
89
|
+
this._triggers = [];
|
|
74
90
|
this.timelines = [];
|
|
91
|
+
this.offsets = [];
|
|
92
|
+
|
|
93
|
+
// this.timeline = timeline;
|
|
94
|
+
// this._triggers = triggers.map(parseTrigger);
|
|
95
|
+
// this.offsets = this._triggers.map(t => {
|
|
96
|
+
// return {
|
|
97
|
+
// y: 0,
|
|
98
|
+
// view: t.view,
|
|
99
|
+
// };
|
|
100
|
+
// });
|
|
101
|
+
|
|
102
|
+
// if (this.offsets.length < 2)
|
|
103
|
+
// throw new Error('scroll timeline needs at least two triggers');
|
|
104
|
+
}
|
|
75
105
|
|
|
76
|
-
|
|
77
|
-
|
|
106
|
+
/**
|
|
107
|
+
* Add a trigger to the timeline
|
|
108
|
+
*
|
|
109
|
+
* Providing an offset at which point the trigger should end
|
|
110
|
+
*
|
|
111
|
+
* If it is the first trigger it is not allowed to be set?
|
|
112
|
+
*/
|
|
113
|
+
add(trigger: ScrollTrigger, position?: Position) {
|
|
114
|
+
this._triggers.push(
|
|
115
|
+
parseTrigger(trigger, position, this._triggers.length),
|
|
116
|
+
);
|
|
78
117
|
}
|
|
79
118
|
|
|
80
119
|
addTimeline(timeline: PublicTimeline) {
|
|
@@ -82,77 +121,113 @@ export default class Scroll {
|
|
|
82
121
|
}
|
|
83
122
|
|
|
84
123
|
init() {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
124
|
+
// todo we need to calculate the position for each timeline
|
|
125
|
+
//
|
|
126
|
+
// calculate the positions and offsets
|
|
127
|
+
// if we are missing one extend them
|
|
128
|
+
|
|
129
|
+
let previousY = -1;
|
|
130
|
+
|
|
131
|
+
this.offsets = this._triggers.map(t => {
|
|
132
|
+
const offset = pageOffset(t.target);
|
|
133
|
+
|
|
134
|
+
const y = offset.top + offset.height * t.offset;
|
|
135
|
+
|
|
136
|
+
if (y < previousY) throw new Error('offsets are not in order');
|
|
137
|
+
|
|
138
|
+
let position;
|
|
139
|
+
if (typeof t.position === 'string') {
|
|
140
|
+
if (this.timelines.length !== 1)
|
|
141
|
+
throw new Error(
|
|
142
|
+
'labels can only be used with one timeline',
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
position = this.timelines[0].labelPosition(t.position);
|
|
146
|
+
} else if (t.position >= 0 || t.position <= 1) {
|
|
147
|
+
position = t.position;
|
|
148
|
+
} else {
|
|
149
|
+
throw new Error('position should be between 0 and 1');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return {
|
|
153
|
+
y,
|
|
154
|
+
view: t.view,
|
|
155
|
+
position,
|
|
156
|
+
};
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
if (this.offsets.length < 1)
|
|
160
|
+
throw new Error('scroll timeline needs at least one trigger');
|
|
161
|
+
|
|
162
|
+
if (this.offsets.length === 1) {
|
|
163
|
+
this.offsets.push({
|
|
164
|
+
y:
|
|
165
|
+
this.offsets[0].y +
|
|
166
|
+
pageOffset(this._triggers[0].target).height,
|
|
167
|
+
view: 1,
|
|
168
|
+
position: 1,
|
|
169
|
+
});
|
|
94
170
|
}
|
|
95
171
|
}
|
|
96
172
|
|
|
97
|
-
_onScroll({ y, height }: { y: number; height: number }) {
|
|
173
|
+
private _onScroll({ y, height }: { y: number; height: number }) {
|
|
98
174
|
if (!this._initialized) {
|
|
99
175
|
this.init();
|
|
100
176
|
this._initialized = true;
|
|
101
177
|
}
|
|
102
178
|
|
|
103
|
-
|
|
104
|
-
|
|
179
|
+
// find the matching offset
|
|
180
|
+
// rolling window
|
|
181
|
+
for (let i = 1; i < this.offsets.length; i++) {
|
|
182
|
+
const start = this.offsets[i - 1];
|
|
183
|
+
const end = this.offsets[i];
|
|
105
184
|
|
|
106
|
-
|
|
107
|
-
|
|
185
|
+
const startY = start.y + height * start.view;
|
|
186
|
+
const endY = end.y + height * end.view;
|
|
108
187
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
188
|
+
const dif = endY - startY;
|
|
189
|
+
const x = 1 - (endY - y) / dif;
|
|
114
190
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
'unknown start property use an html element or an object',
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
let element = null;
|
|
124
|
-
let offset = 'top';
|
|
191
|
+
for (const timeline of this.timelines) {
|
|
192
|
+
// calc pos range
|
|
193
|
+
const pos =
|
|
194
|
+
start.position + (end.position - start.position) * x;
|
|
125
195
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
else if ('target' in val) {
|
|
129
|
-
element = val.target;
|
|
130
|
-
if (typeof val.offset !== 'undefined') offset = val.offset;
|
|
131
|
-
} else {
|
|
132
|
-
throw new Error('start unknown ' + val);
|
|
196
|
+
timeline.seek(pos);
|
|
197
|
+
}
|
|
133
198
|
}
|
|
134
|
-
} else {
|
|
135
|
-
throw new Error('unknown start val');
|
|
136
199
|
}
|
|
137
|
-
|
|
138
|
-
return {
|
|
139
|
-
target: element,
|
|
140
|
-
offset: parseOffset(offset),
|
|
141
|
-
};
|
|
142
200
|
}
|
|
143
201
|
|
|
144
|
-
|
|
202
|
+
/**
|
|
203
|
+
* Parse the start property
|
|
204
|
+
*
|
|
205
|
+
* can be an HTMLElement or an object { target, offset }
|
|
206
|
+
*
|
|
207
|
+
* the default offset is top
|
|
208
|
+
* the default view is top
|
|
209
|
+
*/
|
|
210
|
+
function parseTrigger(
|
|
211
|
+
val: ScrollTrigger,
|
|
212
|
+
position: Position | undefined,
|
|
213
|
+
i: number,
|
|
214
|
+
): ParsedScrollTrigger {
|
|
145
215
|
// might be an object { target, offset }
|
|
146
|
-
if (!val)
|
|
216
|
+
if (!val) {
|
|
217
|
+
throw new Error('unknown property use an html element or an object');
|
|
218
|
+
}
|
|
147
219
|
|
|
148
220
|
let element = null;
|
|
149
|
-
let offset = 'top';
|
|
221
|
+
let offset: OffsetValue = 'top';
|
|
222
|
+
let view: OffsetValue = i == 0 ? 'top' : 'bottom';
|
|
150
223
|
|
|
151
224
|
if (typeof val === 'object') {
|
|
152
|
-
if (val instanceof HTMLElement)
|
|
153
|
-
|
|
225
|
+
if (val instanceof HTMLElement) {
|
|
226
|
+
element = val;
|
|
227
|
+
} else if ('target' in val) {
|
|
154
228
|
element = val.target;
|
|
155
229
|
if (typeof val.offset !== 'undefined') offset = val.offset;
|
|
230
|
+
if (typeof val.view !== 'undefined') view = val.view;
|
|
156
231
|
} else {
|
|
157
232
|
throw new Error('start unknown ' + val);
|
|
158
233
|
}
|
|
@@ -163,21 +238,30 @@ function parseEnd(val: any): StartEndOffset | null {
|
|
|
163
238
|
return {
|
|
164
239
|
target: element,
|
|
165
240
|
offset: parseOffset(offset),
|
|
241
|
+
view: parseOffset(view),
|
|
242
|
+
position: position ?? (i == 0 ? 0 : 1),
|
|
166
243
|
};
|
|
167
244
|
}
|
|
168
245
|
|
|
169
|
-
|
|
246
|
+
/**
|
|
247
|
+
* Parse the offset value
|
|
248
|
+
*
|
|
249
|
+
* can be a string (top, center, bottom) or a number (0-1)
|
|
250
|
+
*
|
|
251
|
+
* 0 = top
|
|
252
|
+
* 0.5 = center
|
|
253
|
+
* 1 = bottom
|
|
254
|
+
*/
|
|
255
|
+
function parseOffset(val: OffsetValue): number {
|
|
170
256
|
if (typeof val === 'string') {
|
|
171
257
|
if (val === 'top') return 0;
|
|
172
|
-
|
|
173
258
|
if (val === 'center') return 0.5;
|
|
174
|
-
|
|
175
259
|
if (val === 'bottom') return 1;
|
|
176
260
|
|
|
177
261
|
throw new Error('unknown view value ' + val);
|
|
178
262
|
}
|
|
179
263
|
|
|
180
|
-
if (typeof val !== 'number') {
|
|
264
|
+
if (typeof val !== 'number' || val < 0 || val > 1) {
|
|
181
265
|
throw new Error(
|
|
182
266
|
'view expecting to be a top/center/bottom or a percent value',
|
|
183
267
|
);
|
package/src/scroll/public.ts
CHANGED
|
@@ -1,20 +1,31 @@
|
|
|
1
|
-
import
|
|
2
|
-
import Scroll from './Scroll.js';
|
|
1
|
+
import { Timeline } from '../chnobli.js';
|
|
2
|
+
// import Scroll from './Scroll.js';
|
|
3
|
+
import ScrollTimeline, { Position, ScrollTrigger } from './Scroll.js';
|
|
3
4
|
|
|
4
|
-
export default class
|
|
5
|
-
private _inner:
|
|
5
|
+
export default class Scroll {
|
|
6
|
+
private _inner: ScrollTimeline;
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
start: el | px
|
|
10
|
-
startView: 'top'
|
|
8
|
+
constructor() {
|
|
9
|
+
this._inner = new ScrollTimeline();
|
|
11
10
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Add a trigger to the timeline
|
|
14
|
+
*
|
|
15
|
+
* Providing an offset at which point the trigger should end
|
|
16
|
+
*/
|
|
17
|
+
add(trigger: ScrollTrigger, position?: Position): this {
|
|
18
|
+
this._inner.add(trigger, position);
|
|
19
|
+
|
|
20
|
+
return this;
|
|
15
21
|
}
|
|
16
22
|
|
|
17
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Add a timeline to the scroll
|
|
25
|
+
*/
|
|
26
|
+
addTimeline(timeline: Timeline): this {
|
|
18
27
|
this._inner.addTimeline(timeline);
|
|
28
|
+
|
|
29
|
+
return this;
|
|
19
30
|
}
|
|
20
31
|
}
|
package/src/stagger/stagger.ts
CHANGED
|
@@ -3,34 +3,48 @@
|
|
|
3
3
|
* allowing to easely offset each target by a few pixels
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
function isStagger(value: any) {
|
|
6
|
+
function isStagger<O>(value: any): value is Stagger<O> {
|
|
7
|
+
const v = value as any;
|
|
8
|
+
|
|
7
9
|
return (
|
|
8
|
-
typeof
|
|
9
|
-
|
|
10
|
-
typeof
|
|
10
|
+
typeof v === 'object' &&
|
|
11
|
+
v !== null &&
|
|
12
|
+
typeof v.__isStagger__ === 'function'
|
|
11
13
|
);
|
|
12
14
|
}
|
|
13
15
|
|
|
14
|
-
export function callStagger(
|
|
15
|
-
|
|
16
|
+
export function callStagger<O>(
|
|
17
|
+
value: O | Stagger<O>,
|
|
18
|
+
i: number,
|
|
19
|
+
length?: number,
|
|
20
|
+
): O {
|
|
21
|
+
if (isStagger(value)) return value.call(i, length);
|
|
16
22
|
|
|
17
23
|
return value;
|
|
18
24
|
}
|
|
19
25
|
|
|
20
|
-
export function staggerMap
|
|
21
|
-
|
|
22
|
-
|
|
26
|
+
export function staggerMap<O, NO>(
|
|
27
|
+
value: O | Stagger<O>,
|
|
28
|
+
fn: (val: O) => NO,
|
|
29
|
+
): NO | Stagger<NO> {
|
|
30
|
+
if (isStagger(value)) {
|
|
31
|
+
return new Stagger((i: number, length?: number) =>
|
|
32
|
+
fn(value.call(i, length)),
|
|
33
|
+
);
|
|
34
|
+
}
|
|
23
35
|
|
|
24
36
|
return fn(value);
|
|
25
37
|
}
|
|
26
38
|
|
|
27
|
-
export
|
|
28
|
-
|
|
39
|
+
export type StaggerValue<O> = (i: number, length?: number) => O;
|
|
40
|
+
|
|
41
|
+
export default class Stagger<O> {
|
|
42
|
+
private fn: StaggerValue<O>;
|
|
29
43
|
|
|
30
44
|
/**
|
|
31
45
|
* @ignore
|
|
32
46
|
*/
|
|
33
|
-
constructor(value:
|
|
47
|
+
constructor(value: StaggerValue<O>) {
|
|
34
48
|
if (typeof value === 'function') {
|
|
35
49
|
this.fn = value;
|
|
36
50
|
return;
|
|
@@ -40,8 +54,8 @@ export default class Stagger {
|
|
|
40
54
|
throw new Error('unknown stagger value ' + value);
|
|
41
55
|
}
|
|
42
56
|
|
|
43
|
-
call(
|
|
44
|
-
return this.fn(
|
|
57
|
+
call(i: number, length?: number): O {
|
|
58
|
+
return this.fn(i, length);
|
|
45
59
|
}
|
|
46
60
|
|
|
47
61
|
/**
|