mirror of
https://github.com/motion-canvas/motion-canvas.git
synced 2026-01-11 14:57:56 -05:00
feat(player): add auto mode
This commit is contained in:
@@ -15,7 +15,6 @@
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
<motion-canvas-player
|
||||
src="/@id/__x00__virtual:template"
|
||||
height="320"
|
||||
style="aspect-ratio: 16 / 9"
|
||||
></motion-canvas-player>
|
||||
</body>
|
||||
|
||||
@@ -15,7 +15,12 @@ enum State {
|
||||
|
||||
class MotionCanvasPlayer extends HTMLElement {
|
||||
public static get observedAttributes() {
|
||||
return ['src', 'quality', 'width', 'height'];
|
||||
return ['src', 'quality', 'width', 'height', 'auto'];
|
||||
}
|
||||
|
||||
private get auto() {
|
||||
const attr = this.getAttribute('auto');
|
||||
return !!attr;
|
||||
}
|
||||
|
||||
private get quality() {
|
||||
@@ -43,7 +48,8 @@ class MotionCanvasPlayer extends HTMLElement {
|
||||
private defaultHeight = 1080;
|
||||
private project: Project | null = null;
|
||||
private abortController: AbortController | null = null;
|
||||
private requestId: number | null = null;
|
||||
private runId: number | null = null;
|
||||
private mouseMoveId: number | null = null;
|
||||
private renderTime = 0;
|
||||
private finished = false;
|
||||
private playing = false;
|
||||
@@ -57,10 +63,32 @@ class MotionCanvasPlayer extends HTMLElement {
|
||||
this.button = this.root.querySelector('.button');
|
||||
|
||||
this.overlay.addEventListener('click', this.handleClick);
|
||||
this.overlay.addEventListener('mousemove', this.handleMouseMove);
|
||||
this.overlay.addEventListener('mouseleave', this.handleMouseLeave);
|
||||
this.setState(State.Initial);
|
||||
}
|
||||
|
||||
private handleMouseMove = () => {
|
||||
if (this.mouseMoveId) {
|
||||
clearTimeout(this.mouseMoveId);
|
||||
}
|
||||
this.mouseMoveId = window.setTimeout(() => {
|
||||
this.mouseMoveId = null;
|
||||
this.updateClass();
|
||||
}, 2000);
|
||||
this.updateClass();
|
||||
};
|
||||
|
||||
private handleMouseLeave = () => {
|
||||
if (this.mouseMoveId) {
|
||||
clearTimeout(this.mouseMoveId);
|
||||
this.mouseMoveId = null;
|
||||
this.updateClass();
|
||||
}
|
||||
};
|
||||
|
||||
private handleClick = () => {
|
||||
this.handleMouseMove();
|
||||
this.setPlaying(!this.playing);
|
||||
this.button.animate(
|
||||
[
|
||||
@@ -80,15 +108,23 @@ class MotionCanvasPlayer extends HTMLElement {
|
||||
}
|
||||
|
||||
private setPlaying(value: boolean) {
|
||||
if (this.state === State.Ready && value) {
|
||||
if (this.state === State.Ready && (value || this.auto)) {
|
||||
this.playing = true;
|
||||
this.request();
|
||||
} else {
|
||||
this.playing = false;
|
||||
}
|
||||
this.updateClass();
|
||||
}
|
||||
|
||||
private updateClass() {
|
||||
this.overlay.className = `overlay state-${this.state}`;
|
||||
this.overlay.classList.toggle('playing', this.playing);
|
||||
this.overlay.classList.toggle('auto', this.auto);
|
||||
this.overlay.classList.toggle(
|
||||
'hover',
|
||||
this.mouseMoveId !== null && !this.auto,
|
||||
);
|
||||
}
|
||||
|
||||
private shouldPlay() {
|
||||
@@ -145,8 +181,8 @@ class MotionCanvasPlayer extends HTMLElement {
|
||||
}
|
||||
|
||||
private request() {
|
||||
this.requestId ??= requestAnimationFrame(async time => {
|
||||
this.requestId = null;
|
||||
this.runId ??= requestAnimationFrame(async time => {
|
||||
this.runId = null;
|
||||
if (time - this.renderTime >= 990 / this.project.framerate) {
|
||||
this.renderTime = time;
|
||||
if (!this.shouldPlay()) return;
|
||||
@@ -165,6 +201,9 @@ class MotionCanvasPlayer extends HTMLElement {
|
||||
|
||||
private attributeChangedCallback(name: string, oldValue: any, newValue: any) {
|
||||
switch (name) {
|
||||
case 'auto':
|
||||
this.setPlaying(true);
|
||||
break;
|
||||
case 'src':
|
||||
this.updateSource(newValue);
|
||||
break;
|
||||
|
||||
@@ -28,11 +28,15 @@ $states: ('initial' 'loading' 'ready' 'error');
|
||||
background-color: rgba(0, 0, 0, 0.54);
|
||||
transition: opacity 0.1s;
|
||||
|
||||
&.state-ready {
|
||||
&.state-ready:not(.auto) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:not(.hover):not(.auto):hover {
|
||||
cursor: none;
|
||||
}
|
||||
|
||||
&.hover,
|
||||
&:not(.playing) {
|
||||
opacity: 1;
|
||||
|
||||
@@ -41,6 +45,10 @@ $states: ('initial' 'loading' 'ready' 'error');
|
||||
transition: scale 0.1s ease-out;
|
||||
}
|
||||
}
|
||||
|
||||
&.auto .button {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
|
||||
@@ -3,7 +3,6 @@ import * as fs from 'fs';
|
||||
|
||||
export default defineConfig({
|
||||
build: {
|
||||
minify: 'esbuild',
|
||||
lib: {
|
||||
entry: 'src/main.ts',
|
||||
formats: ['es'],
|
||||
|
||||
Reference in New Issue
Block a user