Add a hold trigger that trails the pointer
- SpriteEffectTrigger에 hold 추가 - 포인터가 영역 안에 머무는 동안 그 자리에서 계속 방출 - 매니저가 hover 영역을 따로 잡아 방출 중심을 포인터 위치로 넘김 (마우스는 올려두기만 해도, 터치는 누르는 동안) - 버전 1.7.0으로 올림
This commit is contained in:
parent
8188d8d79e
commit
692f9b1260
11
dist/index.d.mts
vendored
11
dist/index.d.mts
vendored
@ -143,8 +143,13 @@ interface AnimationTicker {
|
|||||||
resume: () => void;
|
resume: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 이펙트 트리거 타입 */
|
/**
|
||||||
type SpriteEffectTrigger = 'ambient' | 'touch';
|
* 이펙트 트리거 타입
|
||||||
|
* - ambient: 영역 중심에서 계속 방출
|
||||||
|
* - touch: 영역에 새로 닿는 순간 한 번 터짐
|
||||||
|
* - hold: 포인터가 영역 안에 머무는 동안 포인터 자리에서 계속 방출 (트레일)
|
||||||
|
*/
|
||||||
|
type SpriteEffectTrigger = 'ambient' | 'touch' | 'hold';
|
||||||
/** 블렌드 모드 */
|
/** 블렌드 모드 */
|
||||||
type SpriteBlendMode = 'normal' | 'additive';
|
type SpriteBlendMode = 'normal' | 'additive';
|
||||||
/**
|
/**
|
||||||
@ -242,7 +247,7 @@ interface SpriteEffectConfig {
|
|||||||
blendMode?: SpriteBlendMode;
|
blendMode?: SpriteBlendMode;
|
||||||
/** 최대 파티클 수 */
|
/** 최대 파티클 수 */
|
||||||
maxParticles: number;
|
maxParticles: number;
|
||||||
/** ambient: 초당 방출 수 */
|
/** ambient·hold: 초당 방출 수 */
|
||||||
emitRate?: number;
|
emitRate?: number;
|
||||||
/** touch: 터치 시 방출 수 */
|
/** touch: 터치 시 방출 수 */
|
||||||
burstCount?: number;
|
burstCount?: number;
|
||||||
|
|||||||
11
dist/index.d.ts
vendored
11
dist/index.d.ts
vendored
@ -143,8 +143,13 @@ interface AnimationTicker {
|
|||||||
resume: () => void;
|
resume: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 이펙트 트리거 타입 */
|
/**
|
||||||
type SpriteEffectTrigger = 'ambient' | 'touch';
|
* 이펙트 트리거 타입
|
||||||
|
* - ambient: 영역 중심에서 계속 방출
|
||||||
|
* - touch: 영역에 새로 닿는 순간 한 번 터짐
|
||||||
|
* - hold: 포인터가 영역 안에 머무는 동안 포인터 자리에서 계속 방출 (트레일)
|
||||||
|
*/
|
||||||
|
type SpriteEffectTrigger = 'ambient' | 'touch' | 'hold';
|
||||||
/** 블렌드 모드 */
|
/** 블렌드 모드 */
|
||||||
type SpriteBlendMode = 'normal' | 'additive';
|
type SpriteBlendMode = 'normal' | 'additive';
|
||||||
/**
|
/**
|
||||||
@ -242,7 +247,7 @@ interface SpriteEffectConfig {
|
|||||||
blendMode?: SpriteBlendMode;
|
blendMode?: SpriteBlendMode;
|
||||||
/** 최대 파티클 수 */
|
/** 최대 파티클 수 */
|
||||||
maxParticles: number;
|
maxParticles: number;
|
||||||
/** ambient: 초당 방출 수 */
|
/** ambient·hold: 초당 방출 수 */
|
||||||
emitRate?: number;
|
emitRate?: number;
|
||||||
/** touch: 터치 시 방출 수 */
|
/** touch: 터치 시 방출 수 */
|
||||||
burstCount?: number;
|
burstCount?: number;
|
||||||
|
|||||||
19
dist/index.js
vendored
19
dist/index.js
vendored
@ -503,6 +503,7 @@ var SpriteEffectInstance = class {
|
|||||||
* 매 프레임 업데이트
|
* 매 프레임 업데이트
|
||||||
* @param deltaTime 초 단위 프레임 시간
|
* @param deltaTime 초 단위 프레임 시간
|
||||||
* @param emitCenter 방출 중심 (정규화 좌표 0-1)
|
* @param emitCenter 방출 중심 (정규화 좌표 0-1)
|
||||||
|
* @param holdActive hold 이펙트에서 포인터가 영역 안에 있는지 - 있는 동안만 방출한다
|
||||||
*/
|
*/
|
||||||
this._logCounter = 0;
|
this._logCounter = 0;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
@ -650,9 +651,10 @@ var SpriteEffectInstance = class {
|
|||||||
this.emitOne(center);
|
this.emitOne(center);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
update(deltaTime, emitCenter, resolution) {
|
update(deltaTime, emitCenter, resolution, holdActive = false) {
|
||||||
if (!this.ready) return;
|
if (!this.ready) return;
|
||||||
if (this.config.trigger === "ambient") {
|
const emitting = this.config.trigger === "ambient" || this.config.trigger === "hold" && holdActive;
|
||||||
|
if (emitting) {
|
||||||
this.updateAmbientEmit(deltaTime, emitCenter);
|
this.updateAmbientEmit(deltaTime, emitCenter);
|
||||||
}
|
}
|
||||||
const overLifetime = this.config.overLifetime;
|
const overLifetime = this.config.overLifetime;
|
||||||
@ -825,12 +827,13 @@ var SpriteEffectManager = class {
|
|||||||
*/
|
*/
|
||||||
update(effectAreas, deltaTime, touchState, resolution) {
|
update(effectAreas, deltaTime, touchState, resolution) {
|
||||||
const currentTouchingAreas = /* @__PURE__ */ new Set();
|
const currentTouchingAreas = /* @__PURE__ */ new Set();
|
||||||
if (touchState.isDragging && touchState.position) {
|
const currentHoveringAreas = /* @__PURE__ */ new Set();
|
||||||
|
if (touchState.position) {
|
||||||
for (const area of effectAreas) {
|
for (const area of effectAreas) {
|
||||||
const radius = area.radius ?? 0.1;
|
const radius = area.radius ?? 0.1;
|
||||||
if (isPointInCircle(touchState.position, area.position, radius, resolution)) {
|
if (!isPointInCircle(touchState.position, area.position, radius, resolution)) continue;
|
||||||
currentTouchingAreas.add(area.id);
|
currentHoveringAreas.add(area.id);
|
||||||
}
|
if (touchState.isDragging) currentTouchingAreas.add(area.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const area of effectAreas) {
|
for (const area of effectAreas) {
|
||||||
@ -844,7 +847,9 @@ var SpriteEffectManager = class {
|
|||||||
instance.triggerBurst(touchState.position ?? area.position);
|
instance.triggerBurst(touchState.position ?? area.position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
instance.update(deltaTime, area.position, resolution);
|
const isHolding = effectConfig.trigger === "hold" && currentHoveringAreas.has(area.id);
|
||||||
|
const emitCenter = isHolding && touchState.position ? touchState.position : area.position;
|
||||||
|
instance.update(deltaTime, emitCenter, resolution, isHolding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.previousTouchingAreas = currentTouchingAreas;
|
this.previousTouchingAreas = currentTouchingAreas;
|
||||||
|
|||||||
2
dist/index.js.map
vendored
2
dist/index.js.map
vendored
File diff suppressed because one or more lines are too long
19
dist/index.mjs
vendored
19
dist/index.mjs
vendored
@ -442,6 +442,7 @@ var SpriteEffectInstance = class {
|
|||||||
* 매 프레임 업데이트
|
* 매 프레임 업데이트
|
||||||
* @param deltaTime 초 단위 프레임 시간
|
* @param deltaTime 초 단위 프레임 시간
|
||||||
* @param emitCenter 방출 중심 (정규화 좌표 0-1)
|
* @param emitCenter 방출 중심 (정규화 좌표 0-1)
|
||||||
|
* @param holdActive hold 이펙트에서 포인터가 영역 안에 있는지 - 있는 동안만 방출한다
|
||||||
*/
|
*/
|
||||||
this._logCounter = 0;
|
this._logCounter = 0;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
@ -589,9 +590,10 @@ var SpriteEffectInstance = class {
|
|||||||
this.emitOne(center);
|
this.emitOne(center);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
update(deltaTime, emitCenter, resolution) {
|
update(deltaTime, emitCenter, resolution, holdActive = false) {
|
||||||
if (!this.ready) return;
|
if (!this.ready) return;
|
||||||
if (this.config.trigger === "ambient") {
|
const emitting = this.config.trigger === "ambient" || this.config.trigger === "hold" && holdActive;
|
||||||
|
if (emitting) {
|
||||||
this.updateAmbientEmit(deltaTime, emitCenter);
|
this.updateAmbientEmit(deltaTime, emitCenter);
|
||||||
}
|
}
|
||||||
const overLifetime = this.config.overLifetime;
|
const overLifetime = this.config.overLifetime;
|
||||||
@ -764,12 +766,13 @@ var SpriteEffectManager = class {
|
|||||||
*/
|
*/
|
||||||
update(effectAreas, deltaTime, touchState, resolution) {
|
update(effectAreas, deltaTime, touchState, resolution) {
|
||||||
const currentTouchingAreas = /* @__PURE__ */ new Set();
|
const currentTouchingAreas = /* @__PURE__ */ new Set();
|
||||||
if (touchState.isDragging && touchState.position) {
|
const currentHoveringAreas = /* @__PURE__ */ new Set();
|
||||||
|
if (touchState.position) {
|
||||||
for (const area of effectAreas) {
|
for (const area of effectAreas) {
|
||||||
const radius = area.radius ?? 0.1;
|
const radius = area.radius ?? 0.1;
|
||||||
if (isPointInCircle(touchState.position, area.position, radius, resolution)) {
|
if (!isPointInCircle(touchState.position, area.position, radius, resolution)) continue;
|
||||||
currentTouchingAreas.add(area.id);
|
currentHoveringAreas.add(area.id);
|
||||||
}
|
if (touchState.isDragging) currentTouchingAreas.add(area.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const area of effectAreas) {
|
for (const area of effectAreas) {
|
||||||
@ -783,7 +786,9 @@ var SpriteEffectManager = class {
|
|||||||
instance.triggerBurst(touchState.position ?? area.position);
|
instance.triggerBurst(touchState.position ?? area.position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
instance.update(deltaTime, area.position, resolution);
|
const isHolding = effectConfig.trigger === "hold" && currentHoveringAreas.has(area.id);
|
||||||
|
const emitCenter = isHolding && touchState.position ? touchState.position : area.position;
|
||||||
|
instance.update(deltaTime, emitCenter, resolution, isHolding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.previousTouchingAreas = currentTouchingAreas;
|
this.previousTouchingAreas = currentTouchingAreas;
|
||||||
|
|||||||
2
dist/index.mjs.map
vendored
2
dist/index.mjs.map
vendored
File diff suppressed because one or more lines are too long
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@baekryang/responsive-image-canvas",
|
"name": "@baekryang/responsive-image-canvas",
|
||||||
"version": "1.6.0",
|
"version": "1.7.0",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"registry": "https://git.bnovalab.com/api/packages/baekryang/npm/"
|
"registry": "https://git.bnovalab.com/api/packages/baekryang/npm/"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -240,14 +240,17 @@ export class SpriteEffectInstance {
|
|||||||
* 매 프레임 업데이트
|
* 매 프레임 업데이트
|
||||||
* @param deltaTime 초 단위 프레임 시간
|
* @param deltaTime 초 단위 프레임 시간
|
||||||
* @param emitCenter 방출 중심 (정규화 좌표 0-1)
|
* @param emitCenter 방출 중심 (정규화 좌표 0-1)
|
||||||
|
* @param holdActive hold 이펙트에서 포인터가 영역 안에 있는지 - 있는 동안만 방출한다
|
||||||
*/
|
*/
|
||||||
private _logCounter = 0;
|
private _logCounter = 0;
|
||||||
|
|
||||||
update(deltaTime: number, emitCenter: Point, resolution?: { x: number; y: number }): void {
|
update(deltaTime: number, emitCenter: Point, resolution?: { x: number; y: number }, holdActive = false): void {
|
||||||
if (!this.ready) return;
|
if (!this.ready) return;
|
||||||
|
|
||||||
// ambient 방출
|
// 지속 방출 - ambient는 항상, hold는 포인터가 머무는 동안만
|
||||||
if (this.config.trigger === 'ambient') {
|
const emitting = this.config.trigger === 'ambient'
|
||||||
|
|| (this.config.trigger === 'hold' && holdActive);
|
||||||
|
if (emitting) {
|
||||||
this.updateAmbientEmit(deltaTime, emitCenter);
|
this.updateAmbientEmit(deltaTime, emitCenter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -94,13 +94,15 @@ export class SpriteEffectManager {
|
|||||||
update(effectAreas: SpriteEffectArea[], deltaTime: number, touchState: SpriteEffectTouchState, resolution?: { x: number; y: number }): void {
|
update(effectAreas: SpriteEffectArea[], deltaTime: number, touchState: SpriteEffectTouchState, resolution?: { x: number; y: number }): void {
|
||||||
// 현재 터치 중인 영역 감지
|
// 현재 터치 중인 영역 감지
|
||||||
const currentTouchingAreas = new Set<string>();
|
const currentTouchingAreas = new Set<string>();
|
||||||
|
// 포인터가 머물고 있는 영역 - 마우스는 올려두기만 해도, 터치는 누르고 있는 동안 들어온다
|
||||||
|
const currentHoveringAreas = new Set<string>();
|
||||||
|
|
||||||
if (touchState.isDragging && touchState.position) {
|
if (touchState.position) {
|
||||||
for (const area of effectAreas) {
|
for (const area of effectAreas) {
|
||||||
const radius = area.radius ?? 0.1;
|
const radius = area.radius ?? 0.1;
|
||||||
if (isPointInCircle(touchState.position, area.position, radius, resolution)) {
|
if (!isPointInCircle(touchState.position, area.position, radius, resolution)) continue;
|
||||||
currentTouchingAreas.add(area.id);
|
currentHoveringAreas.add(area.id);
|
||||||
}
|
if (touchState.isDragging) currentTouchingAreas.add(area.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,8 +122,15 @@ export class SpriteEffectManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 매 프레임 업데이트 (ambient 방출 + 파티클 물리)
|
// hold 이펙트: 포인터가 머무는 동안 그 자리에서 계속 방출 - 트레일처럼 따라온다
|
||||||
instance.update(deltaTime, area.position, resolution);
|
const isHolding = effectConfig.trigger === 'hold'
|
||||||
|
&& currentHoveringAreas.has(area.id);
|
||||||
|
const emitCenter = isHolding && touchState.position
|
||||||
|
? touchState.position
|
||||||
|
: area.position;
|
||||||
|
|
||||||
|
// 매 프레임 업데이트 (지속 방출 + 파티클 물리)
|
||||||
|
instance.update(deltaTime, emitCenter, resolution, isHolding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,12 @@
|
|||||||
import type { Point } from './area';
|
import type { Point } from './area';
|
||||||
|
|
||||||
/** 이펙트 트리거 타입 */
|
/**
|
||||||
export type SpriteEffectTrigger = 'ambient' | 'touch';
|
* 이펙트 트리거 타입
|
||||||
|
* - ambient: 영역 중심에서 계속 방출
|
||||||
|
* - touch: 영역에 새로 닿는 순간 한 번 터짐
|
||||||
|
* - hold: 포인터가 영역 안에 머무는 동안 포인터 자리에서 계속 방출 (트레일)
|
||||||
|
*/
|
||||||
|
export type SpriteEffectTrigger = 'ambient' | 'touch' | 'hold';
|
||||||
|
|
||||||
/** 블렌드 모드 */
|
/** 블렌드 모드 */
|
||||||
export type SpriteBlendMode = 'normal' | 'additive';
|
export type SpriteBlendMode = 'normal' | 'additive';
|
||||||
@ -99,7 +104,7 @@ export interface SpriteEffectConfig {
|
|||||||
blendMode?: SpriteBlendMode;
|
blendMode?: SpriteBlendMode;
|
||||||
/** 최대 파티클 수 */
|
/** 최대 파티클 수 */
|
||||||
maxParticles: number;
|
maxParticles: number;
|
||||||
/** ambient: 초당 방출 수 */
|
/** ambient·hold: 초당 방출 수 */
|
||||||
emitRate?: number;
|
emitRate?: number;
|
||||||
/** touch: 터치 시 방출 수 */
|
/** touch: 터치 시 방출 수 */
|
||||||
burstCount?: number;
|
burstCount?: number;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user