feat: Add cubic easing and improve oscillation motion

- `src/types/area.ts`: cubic easing 함수 타입 추가
- `package.json`: 버전 1.1.0에서 1.2.0으로 업데이트
- `src/engine/AnimationLoop.ts`: 왕복 모션 로직을 sin 함수 기반으로 개선하여 자연스러운 좌우/상하 왕복 구현
- `src/utils/easing.ts`: easeInCubic, easeOutCubic 함수 추가
This commit is contained in:
BaekRyang 2025-11-26 13:48:21 +09:00
parent 4db9839f28
commit 317c7c5c92
10 changed files with 34 additions and 50 deletions

2
dist/index.d.mts vendored
View File

@ -11,7 +11,7 @@ interface Point {
/** /**
* *
*/ */
type EasingFunction = 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | 'easeInQuad' | 'easeOutQuad'; type EasingFunction = 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | 'easeInQuad' | 'easeOutQuad' | 'easeInCubic' | 'easeOutCubic';
/** /**
* *
*/ */

2
dist/index.d.ts vendored
View File

@ -11,7 +11,7 @@ interface Point {
/** /**
* *
*/ */
type EasingFunction = 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | 'easeInQuad' | 'easeOutQuad'; type EasingFunction = 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | 'easeInQuad' | 'easeOutQuad' | 'easeInCubic' | 'easeOutCubic';
/** /**
* *
*/ */

18
dist/index.js vendored
View File

@ -248,7 +248,9 @@ var easingFunctions = {
easeOut: (t) => t * (2 - t), easeOut: (t) => t * (2 - t),
easeInOut: (t) => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t, easeInOut: (t) => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t,
easeInQuad: (t) => t * t, easeInQuad: (t) => t * t,
easeOutQuad: (t) => t * (2 - t) easeOutQuad: (t) => t * (2 - t),
easeInCubic: (t) => t * t * t,
easeOutCubic: (t) => 1 - Math.pow(1 - t, 3)
}; };
var applyEasing = (progress, easingType) => { var applyEasing = (progress, easingType) => {
const clampedProgress = Math.max(0, Math.min(1, progress)); const clampedProgress = Math.max(0, Math.min(1, progress));
@ -351,19 +353,11 @@ var AnimationLoop = class {
y: Math.sin(angle * direction) * radius y: Math.sin(angle * direction) * radius
}; };
} else { } else {
if (easedProgress < 0.5) { const oscillation = Math.sin(easedProgress * Math.PI * 2);
const t = easedProgress * 2;
dragVector = { dragVector = {
x: baseVector.x * t, x: baseVector.x * oscillation,
y: baseVector.y * t y: baseVector.y * oscillation
}; };
} else {
const t = (easedProgress - 0.5) * 2;
dragVector = {
x: baseVector.x * (1 - t),
y: baseVector.y * (1 - t)
};
}
} }
return { return {
...area, ...area,

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

18
dist/index.mjs vendored
View File

@ -188,7 +188,9 @@ var easingFunctions = {
easeOut: (t) => t * (2 - t), easeOut: (t) => t * (2 - t),
easeInOut: (t) => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t, easeInOut: (t) => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t,
easeInQuad: (t) => t * t, easeInQuad: (t) => t * t,
easeOutQuad: (t) => t * (2 - t) easeOutQuad: (t) => t * (2 - t),
easeInCubic: (t) => t * t * t,
easeOutCubic: (t) => 1 - Math.pow(1 - t, 3)
}; };
var applyEasing = (progress, easingType) => { var applyEasing = (progress, easingType) => {
const clampedProgress = Math.max(0, Math.min(1, progress)); const clampedProgress = Math.max(0, Math.min(1, progress));
@ -291,19 +293,11 @@ var AnimationLoop = class {
y: Math.sin(angle * direction) * radius y: Math.sin(angle * direction) * radius
}; };
} else { } else {
if (easedProgress < 0.5) { const oscillation = Math.sin(easedProgress * Math.PI * 2);
const t = easedProgress * 2;
dragVector = { dragVector = {
x: baseVector.x * t, x: baseVector.x * oscillation,
y: baseVector.y * t y: baseVector.y * oscillation
}; };
} else {
const t = (easedProgress - 0.5) * 2;
dragVector = {
x: baseVector.x * (1 - t),
y: baseVector.y * (1 - t)
};
}
} }
return { return {
...area, ...area,

2
dist/index.mjs.map vendored

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
{ {
"name": "@baekryang/responsive-image-canvas", "name": "@baekryang/responsive-image-canvas",
"version": "1.1.0", "version": "1.2.0",
"publishConfig": { "publishConfig": {
"registry": "https://git.bnovalab.com/api/packages/baekryang/npm/" "registry": "https://git.bnovalab.com/api/packages/baekryang/npm/"
}, },

View File

@ -51,22 +51,13 @@ export class AnimationLoop {
y: Math.sin(angle * direction) * radius, y: Math.sin(angle * direction) * radius,
}; };
} else { } else {
// 일반 왕복 모션 // 일반 왕복 모션 (sin 기반으로 진짜 좌↔우/상↔하 왕복)
if (easedProgress < 0.5) { // sin(0)=0 → sin(π/2)=1 → sin(π)=0 → sin(3π/2)=-1 → sin(2π)=0
// 0.0 -> 0.5: 0에서 baseVector로 보간 const oscillation = Math.sin(easedProgress * Math.PI * 2);
const t = easedProgress * 2;
dragVector = { dragVector = {
x: baseVector.x * t, x: baseVector.x * oscillation,
y: baseVector.y * t, y: baseVector.y * oscillation,
}; };
} else {
// 0.5 -> 1.0: baseVector에서 0으로 보간
const t = (easedProgress - 0.5) * 2;
dragVector = {
x: baseVector.x * (1 - t),
y: baseVector.y * (1 - t),
};
}
} }
return { return {

View File

@ -15,7 +15,9 @@ export type EasingFunction =
| 'easeOut' | 'easeOut'
| 'easeInOut' | 'easeInOut'
| 'easeInQuad' | 'easeInQuad'
| 'easeOutQuad'; | 'easeOutQuad'
| 'easeInCubic'
| 'easeOutCubic';
/** /**
* *

View File

@ -14,6 +14,9 @@ const easingFunctions: Record<EasingFunction, EasingFunc> = {
easeInQuad: (t) => t * t, easeInQuad: (t) => t * t,
easeOutQuad: (t) => t * (2 - t), easeOutQuad: (t) => t * (2 - t),
easeInCubic: (t) => t * t * t,
easeOutCubic: (t) => 1 - Math.pow(1 - t, 3),
}; };
/** /**