kasaframe 0.1.5 → 0.1.7
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/NOTICE +13 -0
- package/README.md +2 -2
- package/docs/AGENTS.md +1 -0
- package/package.json +1 -1
- package/packages/adapters/src/project.ts +2 -0
- package/packages/check/package.json +1 -0
- package/packages/check/src/check.ts +8 -2
- package/packages/check/src/rules/frames.ts +4 -5
- package/packages/cli/src/commands/direct.ts +24 -4
- package/packages/cli/src/commands/make.ts +15 -5
- package/packages/cli/src/commands/render.ts +34 -7
- package/packages/cli/src/mix.ts +66 -4
- package/packages/cli/src/segments.ts +1 -1
- package/packages/cli/src/sfx.ts +429 -0
- package/packages/core/src/frame.ts +7 -4
- package/packages/core/src/index.ts +3 -1
- package/packages/core/src/project.ts +19 -0
- package/packages/core/src/sfx.ts +70 -0
- package/packages/director/src/assemble.ts +15 -6
- package/packages/director/src/fallback.ts +14 -2
- package/packages/director/src/index.ts +1 -1
- package/packages/director/src/pattern.ts +2 -0
- package/packages/director/src/patterns/fill/cells.ts +5 -2
- package/packages/director/src/scene.ts +17 -5
- package/packages/director/src/transitions.ts +21 -8
- package/packages/motion/src/enter.ts +7 -1
- package/packages/motion/src/impact.ts +5 -2
- package/packages/motion/src/moves/dress.ts +15 -2
- package/packages/motion/src/moves/menu.ts +11 -5
- package/packages/motion/src/transition.ts +3 -1
- package/packages/motion/src/transition3d/index.ts +3 -1
- package/packages/motion/src/transition3d/live.ts +5 -3
- package/packages/patterns/src/bars/rank.ts +6 -7
- package/packages/patterns/src/before-after/shrink.ts +3 -4
- package/packages/patterns/src/before-after/strike.ts +4 -5
- package/packages/patterns/src/code/terminal.ts +25 -16
- package/packages/patterns/src/end/lockup.ts +13 -10
- package/packages/patterns/src/end/slam.ts +14 -8
- package/packages/patterns/src/hook-number/counter.ts +15 -9
- package/packages/patterns/src/hook-number/slam.ts +6 -8
- package/packages/patterns/src/kit.ts +364 -59
- package/packages/patterns/src/limit/gauge.ts +19 -13
- package/packages/patterns/src/quote/karaoke.ts +17 -12
- package/packages/patterns/src/sfx.ts +80 -0
- package/packages/patterns/src/steps/path.ts +15 -7
- package/packages/patterns/src/term-reveal/chips.ts +24 -10
- package/packages/patterns/src/term-reveal/expand.ts +17 -13
- package/packages/patterns/src/timeline/axis.ts +79 -25
- package/packages/patterns/src/title/mask.ts +15 -10
- package/packages/patterns/src/title/slam.ts +1 -1
- package/packages/patterns/src/types.ts +1 -0
- package/packages/plan/src/brief.ts +5 -2
- package/packages/themes/src/index.ts +22 -0
- package/packages/themes/src/slots.ts +32 -2
- package/packages/themes/src/types.ts +28 -0
- package/sfx/README.md +82 -0
- package/sfx/click/appear.wav +0 -0
- package/sfx/click/burst.wav +0 -0
- package/sfx/click/drop.wav +0 -0
- package/sfx/click/end.wav +0 -0
- package/sfx/click/hop.wav +0 -0
- package/sfx/click/land.wav +0 -0
- package/sfx/click/select.wav +0 -0
- package/sfx/click/stick.wav +0 -0
- package/sfx/click/tick.wav +0 -0
- package/sfx/click/type.wav +0 -0
- package/sfx/click/whoosh.wav +0 -0
- package/sfx/pop/appear.wav +0 -0
- package/sfx/pop/burst.wav +0 -0
- package/sfx/pop/drop.wav +0 -0
- package/sfx/pop/end.wav +0 -0
- package/sfx/pop/hop.wav +0 -0
- package/sfx/pop/land.wav +0 -0
- package/sfx/pop/select.wav +0 -0
- package/sfx/pop/stick.wav +0 -0
- package/sfx/pop/tick.wav +0 -0
- package/sfx/pop/type.wav +0 -0
- package/sfx/pop/whoosh.wav +0 -0
- package/sfx/tags.json +545 -0
- package/sfx/ui/appear.wav +0 -0
- package/sfx/ui/burst.wav +0 -0
- package/sfx/ui/drop.wav +0 -0
- package/sfx/ui/end.wav +0 -0
- package/sfx/ui/hop.wav +0 -0
- package/sfx/ui/land.wav +0 -0
- package/sfx/ui/select.wav +0 -0
- package/sfx/ui/stick.wav +0 -0
- package/sfx/ui/tick.wav +0 -0
- package/sfx/ui/type.wav +0 -0
- package/sfx/ui/whoosh.wav +0 -0
- package/themes/kawaii-sticker/effects.ts +15 -3
- package/themes/kawaii-sticker/theme.json +1 -0
- package/themes/og-measure/THEME.md +13 -2
- package/themes/og-measure/effects.ts +76 -59
- package/themes/og-measure/sample/scenes/end.ts +2 -2
- package/themes/og-measure/sample/scenes/gather.ts +2 -10
- package/themes/og-measure/sample/scenes/models.ts +2 -10
- package/themes/og-measure/sample/scenes/one.ts +2 -1
- package/themes/og-measure/sample/scenes/price.ts +4 -16
- package/themes/og-measure/slots.ts +29 -0
- package/themes/og-measure/still.png +0 -0
- package/themes/og-measure/style.json +3 -0
- package/themes/og-measure/theme.json +15 -1
- package/themes/og-measure/variants/snow-blue.json +3 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { applyStyle, clamp, combine, spring } from "@kasaframe/core";
|
|
2
2
|
import { fitSize, textEm } from "@kasaframe/motion/moves";
|
|
3
|
-
import { area, beatStops, fitOnce, glider, moving, node, riseName, slotsOf } from "../kit.ts";
|
|
3
|
+
import { area, beatStops, dwells, fitOnce, followSpoken, glider, moving, node, reread, riseName, sayTimes, slotsOf } from "../kit.ts";
|
|
4
4
|
import type { Pattern } from "../types.ts";
|
|
5
5
|
|
|
6
6
|
export interface EndContent {
|
|
@@ -12,12 +12,12 @@ export interface EndContent {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* 끝 카드 — 로고가 앉고 이름이 글자마다
|
|
15
|
+
* 끝 카드 — 로고가 앉고 이름이 글자마다 서고 한 줄·주소가 찍힌다. 한 줄·주소가 있으면 짚개가 이름부터 짚는다(머무는 테마는 목소리가 한 줄·주소를 말할 때만 그리로).
|
|
16
16
|
*/
|
|
17
17
|
const pattern: Pattern<EndContent> = {
|
|
18
18
|
id: "end.lockup",
|
|
19
19
|
type: "end",
|
|
20
|
-
does: "로고가 앉고 이름이 서고 한 줄·주소가
|
|
20
|
+
does: "로고가 앉고 이름이 서고 한 줄·주소가 찍히면, 짚개가 이름부터 짚는다",
|
|
21
21
|
energy: ["low", "mid"],
|
|
22
22
|
family: "mask",
|
|
23
23
|
camera: ["none"],
|
|
@@ -57,14 +57,17 @@ const pattern: Pattern<EndContent> = {
|
|
|
57
57
|
const logoAt = 0;
|
|
58
58
|
const nameAt = logo ? 0.15 : kit.first ? -0.2 : 0;
|
|
59
59
|
const nameEnd = nameAt + each * (count - 1) + 0.3;
|
|
60
|
-
|
|
60
|
+
// 머무는 짚개 테마는 한 줄·주소를 목소리가 그것을 말할 때 찍는다(못 들으면 이름이 선 뒤부터 장면 끝 무렵까지 고르게). 찍힐 때마다(없으면
|
|
61
|
+
// 이름이 서면) 카메라가 그쪽으로 다가간다 — 끝 카드가 일찍 다 서고 남은 시간이 비지 않게. 훑는 테마는 이름이 서자마자 잇달아 찍는다
|
|
61
62
|
const lineDur = line ? clamp([...c.line!].length * 0.03, 0.25, 0.6) : 0;
|
|
62
|
-
const urlAt = lineAt + lineDur;
|
|
63
63
|
const urlDur = url ? clamp([...c.url!].length * 0.03, 0.25, 0.6) : 0;
|
|
64
|
-
|
|
65
|
-
const
|
|
64
|
+
const [lineAt, urlWant] = dwells(kit, ctx) ? sayTimes(kit, [c.line, c.url], nameEnd, Math.max(nameEnd + 0.3, ctx.dur - 0.9)) : [nameEnd, nameEnd + lineDur];
|
|
65
|
+
const urlAt = Math.max(urlWant, lineAt + lineDur);
|
|
66
|
+
followSpoken(kit, ctx, line || url ? [...(line ? [{ at: lineAt, el: line }] : []), ...(url ? [{ at: urlAt, el: url }] : [])] : [{ at: nameEnd, el: name }]);
|
|
67
|
+
// 짚개는 이름이 서면 이름·한 줄·주소를 짚는다(짚기 방식은 테마 짚음). 한 줄·주소가 없고 훑는 테마면 이름 글자를 박마다 다시 짚는다
|
|
68
|
+
const point = glider(host, [{ el: name, text: c.title }, ...(line ? [{ el: line, text: c.line }] : []), ...(url ? [{ el: url, text: c.url }] : [])], { kit, ctx, from: nameEnd - 0.15 });
|
|
69
|
+
const again = !line && !url && !dwells(kit, ctx) ? beatStops(kit.hits, nameEnd - 0.15, ctx.dur) : null;
|
|
66
70
|
const fit = fitOnce(name, w * 0.86, h * (vertical ? 0.18 : 0.3), c.title);
|
|
67
|
-
const stops = beatStops(kit.hits, nameEnd - 0.15, ctx.dur);
|
|
68
71
|
|
|
69
72
|
const writeLine = line ? slots.write(line, { ctx, text: c.line!, at: lineAt, dur: lineDur, seed: `${kit.seed}:line` }) : null;
|
|
70
73
|
const writeUrl = url ? slots.write(url, { ctx, text: c.url!, at: urlAt, dur: urlDur, seed: `${kit.seed}:url` }) : null;
|
|
@@ -74,8 +77,8 @@ const pattern: Pattern<EndContent> = {
|
|
|
74
77
|
moving("end.lockup", ctx);
|
|
75
78
|
if (logo && logoLand) applyStyle(logo, combine({ scale: spring(t - logoAt, { from: 0.6, to: 1, stiffness: 280, damping: 16 }) }, logoLand(t)));
|
|
76
79
|
fit();
|
|
77
|
-
paintName(t, { riseAt: nameAt, each, fill: 0 });
|
|
78
|
-
point(t
|
|
80
|
+
paintName(t, { riseAt: nameAt, each, fill: 0, up: again ? reread(t, again) : undefined });
|
|
81
|
+
point(t);
|
|
79
82
|
writeLine?.(t);
|
|
80
83
|
writeUrl?.(t);
|
|
81
84
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { applyStyle, clamp, combine, spring } from "@kasaframe/core";
|
|
2
2
|
import { fitSize, textEm } from "@kasaframe/motion/moves";
|
|
3
|
-
import { area, beatStops, cameraOk, fitOnce, glider, moving, node, sceneDrop, slam, slotsOf } from "../kit.ts";
|
|
3
|
+
import { area, beatStops, cameraOk, dwells, fitOnce, followSpoken, glider, moving, node, readOver, reread, sayTimes, sceneDrop, slam, slotsOf } from "../kit.ts";
|
|
4
4
|
import type { EndContent } from "./lockup.ts";
|
|
5
5
|
import type { Pattern } from "../types.ts";
|
|
6
6
|
|
|
@@ -60,14 +60,19 @@ const pattern: Pattern<EndContent> = {
|
|
|
60
60
|
const at = di !== null ? ctx.beats.drop(di) : (hits.find((b) => b >= 0.1) ?? 0.12);
|
|
61
61
|
const dropPaint = di !== null && slots.drop ? slots.drop(burst, { ctx, drop: di }) : null;
|
|
62
62
|
if (di === null && kit.stage && cameraOk(ctx)) kit.stage.camera.impact(at, { amount: 0.04 });
|
|
63
|
-
|
|
64
|
-
const
|
|
63
|
+
// 머무는 짚개 테마는 한 줄·주소를 자막·목소리가 말하는 순간에 붙이고, 카메라가 이름에서 그쪽으로 서지 않고 다가간다 — 쾅 뒤 다 선 끝 카드가 3초 넘게 섰다
|
|
64
|
+
const dwell = dwells(kit, ctx);
|
|
65
|
+
const [lineAt, urlAt] = dwell
|
|
66
|
+
? sayTimes(kit, [c.line, c.url], at + 0.2, Math.max(at + 0.2, ctx.dur - 1))
|
|
67
|
+
: [at + 0.2, at + 0.2 + (c.line ? 0.35 : 0)];
|
|
68
|
+
if (dwell) followSpoken(kit, ctx, [{ at, el: stage }, ...(lineEl ? [{ at: lineAt, el: lineEl }] : []), ...(urlEl ? [{ at: urlAt, el: urlEl }] : [])], { reach: 0.25, zoom: 1.05 });
|
|
65
69
|
const writeLine = lineEl ? slots.write(lineEl, { ctx, text: c.line!, at: lineAt, dur: 0.35, seed: `${kit.seed}:line` }) : null;
|
|
66
70
|
const writeUrl = urlEl ? slots.write(urlEl, { ctx, text: c.url!, at: urlAt, dur: 0.3, seed: `${kit.seed}:url` }) : null;
|
|
67
71
|
const landed = slots.land(name, { ctx, at, seed: `${kit.seed}:land` });
|
|
68
|
-
//
|
|
69
|
-
const point = glider(host, [stage, ...(lineEl ? [lineEl] : []), ...(urlEl ? [urlEl] : [])], {
|
|
70
|
-
const
|
|
72
|
+
// 앉으면 짚개가 이름·한 줄·주소를 짚는다(짚기 방식은 테마 짚음). 한 줄·주소가 없고 훑는 테마면 이름 글을 박마다 다시 짚는다
|
|
73
|
+
const point = glider(host, [{ el: stage, text: c.title }, ...(lineEl ? [{ el: lineEl, text: c.line }] : []), ...(urlEl ? [{ el: urlEl, text: c.url }] : [])], { kit, ctx, from: at + 0.2 });
|
|
74
|
+
const again = line || dwell ? null : readOver(name, c.title, ctx);
|
|
75
|
+
const againStops = again ? beatStops(kit.hits, at + 0.2, ctx.dur) : [];
|
|
71
76
|
|
|
72
77
|
return (t: number) => {
|
|
73
78
|
moving("end.slam", ctx);
|
|
@@ -78,8 +83,9 @@ const pattern: Pattern<EndContent> = {
|
|
|
78
83
|
// 쾅 전엔 외곽선 이름을 왼쪽부터 짚어 자리를 알린다 — 앉은 뒤엔 꽉 찬 이름을 마지막 프레임까지 짚는다
|
|
79
84
|
ghost.style.opacity = t < at ? "0.16" : "0";
|
|
80
85
|
ghost.style.clipPath = t < at ? `inset(0 ${((1 - clamp(t / Math.max(0.1, at - 0.16))) * 100).toFixed(2)}% 0 0)` : "";
|
|
81
|
-
point(t
|
|
82
|
-
|
|
86
|
+
point(t);
|
|
87
|
+
again?.(reread(t, againStops));
|
|
88
|
+
if (line) line.style.visibility = t >= Math.min(lineAt, urlAt) ? "visible" : "hidden";
|
|
83
89
|
writeLine?.(t);
|
|
84
90
|
writeUrl?.(t);
|
|
85
91
|
if (urlEl) applyStyle(urlEl, t >= urlAt ? { scale: spring(t - urlAt, { from: 0.5, to: 1, stiffness: 320, damping: 14 }) } : { opacity: 0 });
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { applyStyle, clamp } from "@kasaframe/core";
|
|
2
2
|
import { textEm } from "@kasaframe/motion/moves";
|
|
3
|
-
import { area,
|
|
3
|
+
import { area, decimalsOf, dwells, fitOnce, followSpoken, glider, moving, node, odometer, sayTimes, slotsOf, timesSign } from "../kit.ts";
|
|
4
4
|
import type { HookNumber } from "./roll.ts";
|
|
5
|
+
import { rollCues } from "../sfx.ts";
|
|
5
6
|
import type { Pattern } from "../types.ts";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
|
-
* 계수기 — 숫자 자리마다 판이 서고 주행계 띠가 굴러 값에 앉는다(끝자리 띠가 연속으로 구르고 윗자리는 올림 때만).
|
|
9
|
-
*
|
|
9
|
+
* 계수기 — 숫자 자리마다 판이 서고 주행계 띠가 굴러 값에 앉는다(끝자리 띠가 연속으로 구르고 윗자리는 올림 때만). 목소리가 그 값을 말할 때(못 들으면 장면 끝 무렵) 앉는다.
|
|
10
|
+
* 앉으면 짚개가 숫자부터 짚는다(머무는 테마는 목소리가 라벨·단위를 말할 때만 그리로). 롤(roll)이 「값이 바뀐다」라면 이쪽은 「센다」.
|
|
10
11
|
*/
|
|
11
12
|
const pattern: Pattern<HookNumber> = {
|
|
12
13
|
id: "hook-number.counter",
|
|
13
14
|
type: "hook-number",
|
|
14
|
-
does: "숫자 자리마다 판이 서고 주행계 띠가 굴러 값에
|
|
15
|
+
does: "숫자 자리마다 판이 서고 주행계 띠가 굴러 값에 앉으면, 짚개가 숫자부터 짚는다",
|
|
15
16
|
energy: ["low", "mid"],
|
|
16
17
|
family: "flap",
|
|
17
18
|
camera: ["none"],
|
|
@@ -69,11 +70,15 @@ const pattern: Pattern<HookNumber> = {
|
|
|
69
70
|
// 라벨 폭은 글꼴마다 다르다(고정폭 테마는 빈칸까지 한 칸) — 글자 수 어림 대신 그 글꼴로 재서 안전 영역 폭 92% 안에
|
|
70
71
|
const fitLabel = fitOnce(label, w * 0.92, labelPx, c.label);
|
|
71
72
|
|
|
72
|
-
|
|
73
|
+
// 머무는 짚개 테마는 라벨을 목소리가 그것을 말할 때 세우고, 숫자는 그 값을 말할 때까지(못 들으면 장면 끝 무렵까지) 고른 빠르기로 센다 —
|
|
74
|
+
// 처음 2초에 다 서고 남은 시간이 비지 않게. 앉으면 카메라가 숫자 쪽으로 다가간다. 훑는 테마는 2.4초 안에 앉고 남은 시간을 짚개가 진다
|
|
75
|
+
const spread = dwells(kit, ctx);
|
|
76
|
+
const [labelAt, valueAt] = spread ? sayTimes(kit, [c.label, c.value.toFixed(dec)], 0, Math.max(1.2, ctx.dur - 0.9)) : [0, Math.min(2.4, ctx.dur - 0.6)];
|
|
77
|
+
const land = clamp(valueAt, Math.min(1.2, ctx.dur - 0.6), ctx.dur - 0.6);
|
|
78
|
+
followSpoken(kit, ctx, [{ at: land, el: board }]);
|
|
73
79
|
// 배수 기호 하나를 칸으로 짚으면 색 네모 안 × — 닫기 단추로 읽힌다
|
|
74
|
-
const point = glider(host, [board, label, ...(unitEl && !times ? [unitEl] : [])], {
|
|
75
|
-
const
|
|
76
|
-
const writeLabel = slots.write(label, { ctx, text: c.label, at: 0, dur: 0.35, seed: `${kit.seed}:l` });
|
|
80
|
+
const point = glider(host, [{ el: board, text: c.value.toFixed(dec) }, { el: label, text: c.label }, ...(unitEl && !times ? [{ el: unitEl, text: unit }] : [])], { kit, ctx, from: land + 0.15 });
|
|
81
|
+
const writeLabel = slots.write(label, { ctx, text: c.label, at: Math.min(labelAt, land - 0.2), dur: 0.35, seed: `${kit.seed}:l` });
|
|
77
82
|
const landed = slots.land(board, { ctx, at: land, seed: `${kit.seed}:land` });
|
|
78
83
|
// 출처는 앉은 뒤에 찍고 장면 끝 0.35초 전에 다 찍는다 — 테마 글 찍기가 마지막 글자를 앉힐 틈(끝 프레임에 덜 찍힌 글자가 안 남게)
|
|
79
84
|
const srcDur = clamp([...srcText].length * 0.035, 0.3, 0.9);
|
|
@@ -87,13 +92,14 @@ const pattern: Pattern<HookNumber> = {
|
|
|
87
92
|
writeSource?.(t);
|
|
88
93
|
// 고른 빠르기로 센다 — 감속하면 끝자리 띠가 서서 그 사이가 멈춘 화면이 된다
|
|
89
94
|
const p = clamp((t - 0.1) / (land - 0.1));
|
|
95
|
+
rollCues(t, { at: 0.1, dur: land - 0.1, p: (u) => u });
|
|
90
96
|
const v = from + (c.value - from) * p;
|
|
91
97
|
if (odo) odo(p >= 1 ? c.value : v);
|
|
92
98
|
num.style.visibility = odo && t < land ? "visible" : "hidden";
|
|
93
99
|
plain.style.visibility = !odo || t >= land ? "visible" : "hidden";
|
|
94
100
|
if (!odo) plain.textContent = (p >= 1 ? c.value : v).toFixed(dec).padStart(template.length, " ");
|
|
95
101
|
applyStyle(board, landed(t));
|
|
96
|
-
point(t
|
|
102
|
+
point(t);
|
|
97
103
|
};
|
|
98
104
|
},
|
|
99
105
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { applyStyle, clamp, combine } from "@kasaframe/core";
|
|
2
2
|
import { textEm } from "@kasaframe/motion/moves";
|
|
3
|
-
import { area,
|
|
3
|
+
import { area, cameraOk, decimalsOf, factRoll, fitOnce, glider, moving, node, sceneDrop, slam, slotsOf } from "../kit.ts";
|
|
4
4
|
import type { HookNumber } from "./roll.ts";
|
|
5
5
|
import type { Pattern } from "../types.ts";
|
|
6
6
|
|
|
@@ -61,13 +61,11 @@ const pattern: Pattern<HookNumber> = {
|
|
|
61
61
|
if (di === null && kit.stage && cameraOk(ctx)) kit.stage.camera.impact(at, { amount: 0.04 });
|
|
62
62
|
const writeLabel = slots.write(label, { ctx, text: c.label, at: 0, dur: labelDur, seed: `${kit.seed}:l` });
|
|
63
63
|
const landed = slots.land(row, { ctx, at, seed: `${kit.seed}:land` });
|
|
64
|
-
// 짚개 — 쾅 전엔 라벨
|
|
65
|
-
const before = glider(host, [labelBox, ghostRow], {
|
|
66
|
-
const after = glider(host, [numBox, labelBox], {
|
|
67
|
-
const preStops = beatStops(kit.hits, labelDur, at - 0.2);
|
|
64
|
+
// 짚개 — 쾅 전엔 라벨(무엇의 숫자인가)과 외곽선 자리, 쾅 뒤엔 숫자와 라벨. 짚기 방식(박마다 훑기·요점에 머묾)은 테마 짚음이 고른다
|
|
65
|
+
const before = glider(host, [{ el: labelBox, text: c.label }, { el: ghostRow }], { kit, ctx, from: labelDur, to: at - 0.2, until: at - 0.16 });
|
|
66
|
+
const after = glider(host, [{ el: numBox, text }, { el: labelBox, text: c.label }], { kit, ctx, from: at + 0.25 });
|
|
68
67
|
// 라벨은 그 글꼴로 재서 안전 영역 폭 92% 안에
|
|
69
68
|
const fitLabel = fitOnce(labelBox, w * 0.92, labelPx, c.label);
|
|
70
|
-
const postStops = beatStops(kit.hits, at + 0.25, ctx.dur);
|
|
71
69
|
|
|
72
70
|
return (t: number) => {
|
|
73
71
|
moving("hook-number.slam", ctx);
|
|
@@ -81,8 +79,8 @@ const pattern: Pattern<HookNumber> = {
|
|
|
81
79
|
ghostRow.style.left = `${row.offsetLeft}px`;
|
|
82
80
|
ghostRow.style.top = `${row.offsetTop}px`;
|
|
83
81
|
}
|
|
84
|
-
before(t
|
|
85
|
-
after(t
|
|
82
|
+
before(t);
|
|
83
|
+
after(t);
|
|
86
84
|
if (s) applyStyle(host, s.shake);
|
|
87
85
|
};
|
|
88
86
|
},
|