feat: new ghost accent state, new click and hold behaviour for track units
This commit is contained in:
@@ -2,9 +2,10 @@ import {IPublisher, Publisher} from "./Publisher";
|
|||||||
import ISubscriber from "./Subscriber";
|
import ISubscriber from "./Subscriber";
|
||||||
|
|
||||||
export const enum TrackUnitType {
|
export const enum TrackUnitType {
|
||||||
Normal="but-0",
|
Normal="tut-0",
|
||||||
GhostNote="but-1",
|
GhostNote="tut-1",
|
||||||
Accent="but-2",
|
Accent="tut-2",
|
||||||
|
GhostNoteAccent="tut-3",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const enum TrackUnitEvent {
|
export const enum TrackUnitEvent {
|
||||||
@@ -20,6 +21,7 @@ export default class TrackUnit implements IPublisher<TrackUnitEvent> {
|
|||||||
TrackUnitType.Normal,
|
TrackUnitType.Normal,
|
||||||
TrackUnitType.GhostNote,
|
TrackUnitType.GhostNote,
|
||||||
TrackUnitType.Accent,
|
TrackUnitType.Accent,
|
||||||
|
TrackUnitType.GhostNoteAccent,
|
||||||
] as const;
|
] as const;
|
||||||
private publisher: Publisher<TrackUnitEvent, TrackUnit> = new Publisher<TrackUnitEvent, TrackUnit>(this);
|
private publisher: Publisher<TrackUnitEvent, TrackUnit> = new Publisher<TrackUnitEvent, TrackUnit>(this);
|
||||||
private on = false;
|
private on = false;
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export default class TrackView extends UINode implements ISubscriber<EventTypeSu
|
|||||||
view = new TrackUnitView({trackUnit});
|
view = new TrackUnitView({trackUnit});
|
||||||
this.trackUnitViews.push(view);
|
this.trackUnitViews.push(view);
|
||||||
view.onHover(() => this.onBeatViewHover(view));
|
view.onHover(() => this.onBeatViewHover(view));
|
||||||
view.onMouseDown((event: MouseEvent) => this.onTrackUnitClick(event.button, i));
|
view.onMouseUp((event: MouseEvent) => this.onTrackUnitClick(event.button, i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,21 +35,8 @@
|
|||||||
|
|
||||||
.track-unit.track-unit-on.track-unit-accent {
|
.track-unit.track-unit-on.track-unit-accent {
|
||||||
border-color: var(--color-ui-neutral-light);
|
border-color: var(--color-ui-neutral-light);
|
||||||
background-color: var(--color-ui-accent);
|
|
||||||
}
|
|
||||||
|
|
||||||
.track-unit.track-unit-on.track-unit-accent:hover {
|
|
||||||
border-color: var(--color-ui-neutral-light);
|
|
||||||
background-color: var(--color-ui-accent-hover);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.track-unit.track-unit-on.track-unit-ghost {
|
.track-unit.track-unit-on.track-unit-ghost {
|
||||||
border-color: var(--color-ui-accent);
|
|
||||||
background-color: var(--color-ui-accent);
|
|
||||||
opacity: 60%;
|
opacity: 60%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.track-unit.track-unit-on.track-unit-ghost:hover {
|
|
||||||
border-color: var(--color-ui-accent-hover);
|
|
||||||
background-color: var(--color-ui-accent-hover);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -19,9 +19,10 @@ export default class TrackUnitView extends UINode implements ISubscriber<EventTy
|
|||||||
private trackUnit: TrackUnit;
|
private trackUnit: TrackUnit;
|
||||||
private subscription: ISubscription | null = null;
|
private subscription: ISubscription | null = null;
|
||||||
private publisher: IPublisher<TrackUnitEvent> = new Publisher<TrackUnitEvent, TrackUnitView>(this);
|
private publisher: IPublisher<TrackUnitEvent> = new Publisher<TrackUnitEvent, TrackUnitView>(this);
|
||||||
private touchTimeout: ReturnType<typeof setTimeout> | null = null;
|
private rotationTimeout: ReturnType<typeof setTimeout> | null = null;
|
||||||
private mouseDownListeners: ((ev: MouseEvent) => void)[] = [];
|
private mouseUpListeners: ((ev: MouseEvent) => void)[] = [];
|
||||||
private hoverListeners: ((ev: MouseEvent) => void)[] = [];
|
private hoverListeners: ((ev: MouseEvent) => void)[] = [];
|
||||||
|
private blockNextMouseUp = false;
|
||||||
|
|
||||||
constructor(options: TrackUnitUINodeOptions) {
|
constructor(options: TrackUnitUINodeOptions) {
|
||||||
super(options);
|
super(options);
|
||||||
@@ -43,12 +44,10 @@ export default class TrackUnitView extends UINode implements ISubscriber<EventTy
|
|||||||
private setupBindings() {
|
private setupBindings() {
|
||||||
this.subscription?.unbind();
|
this.subscription?.unbind();
|
||||||
this.subscription = this.trackUnit.addSubscriber(this, EventTypeSubscriptions);
|
this.subscription = this.trackUnit.addSubscriber(this, EventTypeSubscriptions);
|
||||||
this.mouseDownListeners.forEach(listener => this.getNode().removeEventListener("mousedown", listener));
|
|
||||||
this.hoverListeners.forEach(listener => this.getNode().removeEventListener("mouseover", listener));
|
this.hoverListeners.forEach(listener => this.getNode().removeEventListener("mouseover", listener));
|
||||||
this.redraw();
|
this.redraw();
|
||||||
this.mouseDownListeners.forEach(listener => this.getNode().addEventListener("mousedown", listener));
|
|
||||||
this.hoverListeners.forEach(listener => this.getNode().addEventListener("mouseover", listener));
|
|
||||||
this.getNode().addEventListener("mousedown", (ev) => this.handleMouseDown(ev));
|
this.getNode().addEventListener("mousedown", (ev) => this.handleMouseDown(ev));
|
||||||
|
this.getNode().addEventListener("mouseup", (ev) => this.handleMouseUp(ev));
|
||||||
this.getNode().addEventListener("touchstart", (ev) => this.handleTouchStart(ev));
|
this.getNode().addEventListener("touchstart", (ev) => this.handleTouchStart(ev));
|
||||||
this.getNode().addEventListener("touchend", (ev) => this.handleTouchEnd(ev));
|
this.getNode().addEventListener("touchend", (ev) => this.handleTouchEnd(ev));
|
||||||
}
|
}
|
||||||
@@ -56,20 +55,37 @@ export default class TrackUnitView extends UINode implements ISubscriber<EventTy
|
|||||||
private handleMouseDown(ev: MouseEvent): void {
|
private handleMouseDown(ev: MouseEvent): void {
|
||||||
if (ev.button === 1) {
|
if (ev.button === 1) {
|
||||||
this.trackUnit.rotateType();
|
this.trackUnit.rotateType();
|
||||||
|
} else if (ev.button === 0) {
|
||||||
|
this.rotationTimeout = this.rotationTimeout || setTimeout(() => {
|
||||||
|
this.trackUnit.rotateType();
|
||||||
|
this.blockNextMouseUp = true;
|
||||||
|
this.rotationTimeout = null;
|
||||||
|
}, 400);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private handleMouseUp(ev: MouseEvent): void {
|
||||||
|
if (this.rotationTimeout) {
|
||||||
|
clearTimeout(this.rotationTimeout);
|
||||||
|
this.rotationTimeout = null;
|
||||||
|
}
|
||||||
|
if (!this.blockNextMouseUp) {
|
||||||
|
this.mouseUpListeners.forEach(listener => listener(ev));
|
||||||
|
}
|
||||||
|
this.blockNextMouseUp = false;
|
||||||
|
}
|
||||||
|
|
||||||
private handleTouchStart(ev: TouchEvent): void {
|
private handleTouchStart(ev: TouchEvent): void {
|
||||||
this.touchTimeout = this.touchTimeout || setTimeout(() => {
|
this.rotationTimeout = this.rotationTimeout || setTimeout(() => {
|
||||||
this.trackUnit.rotateType();
|
this.trackUnit.rotateType();
|
||||||
this.touchTimeout = null;
|
this.rotationTimeout = null;
|
||||||
}, 400);
|
}, 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleTouchEnd(ev: TouchEvent): void {
|
private handleTouchEnd(ev: TouchEvent): void {
|
||||||
if (this.touchTimeout) {
|
if (this.rotationTimeout) {
|
||||||
clearTimeout(this.touchTimeout);
|
clearTimeout(this.rotationTimeout);
|
||||||
this.touchTimeout = null;
|
this.rotationTimeout = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,13 +116,17 @@ export default class TrackUnitView extends UINode implements ISubscriber<EventTy
|
|||||||
this.getNode().classList.remove("track-unit-accent");
|
this.getNode().classList.remove("track-unit-accent");
|
||||||
break;
|
break;
|
||||||
case TrackUnitType.GhostNote:
|
case TrackUnitType.GhostNote:
|
||||||
this.getNode().classList.remove("track-unit-accent");
|
|
||||||
this.getNode().classList.add("track-unit-ghost");
|
this.getNode().classList.add("track-unit-ghost");
|
||||||
|
this.getNode().classList.remove("track-unit-accent");
|
||||||
break;
|
break;
|
||||||
case TrackUnitType.Accent:
|
case TrackUnitType.Accent:
|
||||||
this.getNode().classList.remove("track-unit-ghost");
|
this.getNode().classList.remove("track-unit-ghost");
|
||||||
this.getNode().classList.add("track-unit-accent");
|
this.getNode().classList.add("track-unit-accent");
|
||||||
break;
|
break;
|
||||||
|
case TrackUnitType.GhostNoteAccent:
|
||||||
|
this.getNode().classList.add("track-unit-ghost");
|
||||||
|
this.getNode().classList.add("track-unit-accent");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -125,11 +145,10 @@ export default class TrackUnitView extends UINode implements ISubscriber<EventTy
|
|||||||
|
|
||||||
onHover(cb: () => void): void {
|
onHover(cb: () => void): void {
|
||||||
this.hoverListeners.push(cb);
|
this.hoverListeners.push(cb);
|
||||||
this.setupBindings();
|
this.getNode().addEventListener("mouseover", cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
onMouseDown(cb: (ev: MouseEvent) => void): void {
|
onMouseUp(cb: (ev: MouseEvent) => void): void {
|
||||||
this.mouseDownListeners.push(cb);
|
this.mouseUpListeners.push(cb);
|
||||||
this.setupBindings();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user