autoformat

master
Tomáš Mládek 2021-04-22 11:33:33 +02:00
parent bfa569853b
commit 7bff008853
4 changed files with 131 additions and 83 deletions

View File

@ -1,32 +1,40 @@
<template>
<SVGContent id="root" url="content/intro.svg" @set-background="setBackground"/>
<SVGContent
id="root"
url="content/intro.svg"
@set-background="setBackground"
/>
</template>
<script lang="ts">
import {defineComponent} from "vue";
import { defineComponent } from "vue";
import SVGContent from "@/components/SVGContent.vue";
import "normalize.css";
export default defineComponent({
name: "App",
components: {
SVGContent
SVGContent,
},
methods: {
setBackground(background: string) {
document.body.style.background = background;
}
}
},
},
});
</script>
<style>
html, body {
html,
body {
overflow: hidden;
background: black;
}
html, body, #app, #root {
html,
body,
#app,
#root {
width: 100%;
height: 100%;
cursor: default;

View File

@ -1,23 +1,21 @@
<template>
<audio ref="audio"
:src="definition.src"
loop preload="auto"/>
<audio ref="audio" :src="definition.src" loop preload="auto" />
</template>
<script lang="ts">
import {defineComponent, PropType, ref, watch} from "vue";
import {BoundingBox} from "@/components/SVGContent.vue";
import { defineComponent, PropType, ref, watch } from "vue";
import { BoundingBox } from "@/components/SVGContent.vue";
export default defineComponent({
name: "AudioArea",
props: {
definition: {
type: Object as PropType<AudioAreaDef>,
required: true
required: true,
},
bbox: {
type: Object as PropType<BoundingBox>,
required: true
required: true,
},
},
setup(props) {
@ -34,38 +32,46 @@ export default defineComponent({
const onBBoxChange = () => {
const x = props.bbox.x + props.bbox.w / 2;
const y = props.bbox.y + props.bbox.h / 2;
const distance = Math.sqrt(Math.pow(x - props.definition.cx, 2) + Math.pow(y - props.definition.cy, 2));
const distance = Math.sqrt(
Math.pow(x - props.definition.cx, 2) +
Math.pow(y - props.definition.cy, 2)
);
if (distance < props.definition.radius) {
if (audio.value!.paused) {
console.debug(`[AUDIOAREA] Entered audio area "${props.definition.src}", starting playback...`);
console.debug(
`[AUDIOAREA] Entered audio area "${props.definition.src}", starting playback...`
);
audio.value!.play();
}
const volume = (props.definition.radius - distance) / props.definition.radius;
audio.value!.volume = volume * (props.bbox.z < 1 ? (props.bbox.z * vol_x + vol_b) : 1);
const volume =
(props.definition.radius - distance) / props.definition.radius;
audio.value!.volume =
volume * (props.bbox.z < 1 ? props.bbox.z * vol_x + vol_b : 1);
} else {
if (!audio.value!.paused) {
console.debug(`[AUDIOAREA] Left audio area "${props.definition.src}", pausing playback...`);
console.debug(
`[AUDIOAREA] Left audio area "${props.definition.src}", pausing playback...`
);
audio.value!.pause();
}
}
};
watch(props.bbox, onBBoxChange, {deep: true});
watch(props.bbox, onBBoxChange, { deep: true });
return {
audio
audio,
};
}
},
});
export interface AudioAreaDef {
id: string,
cx: number,
cy: number,
radius: number,
src: string
id: string;
cx: number;
cy: number;
radius: number;
src: string;
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->

View File

@ -5,10 +5,19 @@
</div>
<div class="content" ref="root">
<div class="video-scrolls">
<VideoScroll v-for="scroll in scrolls" :definition="scroll" :key="scroll.id"/>
<VideoScroll
v-for="scroll in scrolls"
:definition="scroll"
:key="scroll.id"
/>
</div>
</div>
<AudioArea v-for="audio in audioAreas" :definition="audio" :bbox="bbox" :key="audio.id"/>
<AudioArea
v-for="audio in audioAreas"
:definition="audio"
:bbox="bbox"
:key="audio.id"
/>
<div class="dev devpanel">
<div>
<span>Current viewport position:</span>
@ -382,10 +391,10 @@ export default defineComponent({
if (gp) {
if (gp.buttons[7].pressed) {
gamePadZoomSpeed += .1;
gamePadZoomSpeed += 0.1;
}
if (gp.buttons[5].pressed) {
gamePadZoomSpeed -= .1;
gamePadZoomSpeed -= 0.1;
}
if (gamePadZoomSpeed < 1) {
gamePadZoomSpeed = 1;
@ -469,11 +478,14 @@ async function processScrolls(svg: XMLDocument): Promise<VideoScrollDef[]> {
direction as VideoScrollDirection
)
) {
console.error(`Unknown direction definition: "${direction}" (in #${el.id})`);
console.error(
`Unknown direction definition: "${direction}" (in #${el.id})`
);
return false;
}
return direction as VideoScrollDirection;
}).filter((d) => Boolean(d)) as VideoScrollDirection[];
})
.filter((d) => Boolean(d)) as VideoScrollDirection[];
console.debug(`[SVG/VIDEOSCROLLS] Fetching ${filesURL}...`);
const fileFetch = await fetch(`content/${filesURL}`);

View File

@ -1,70 +1,91 @@
<template>
<div class="video-scroll" ref="root" v-if="definition.directions.length > 0">
<img class="visible displayed loaded"
:src="definition.files[0]"
:style="{
top: `${Math.round(definition.top)}px`,
left: `${Math.round(definition.left)}px`,
width: isHorizontal ? `${Math.round(definition.width)}px` : 'auto',
height: isVertical ? `${Math.round(definition.height)}px` : 'auto',
transform: `rotate(${definition.angle}deg)`
}"
<img
class="visible displayed loaded"
:src="definition.files[0]"
:style="{
top: `${Math.round(definition.top)}px`,
left: `${Math.round(definition.left)}px`,
width: isHorizontal ? `${Math.round(definition.width)}px` : 'auto',
height: isVertical ? `${Math.round(definition.height)}px` : 'auto',
transform: `rotate(${definition.angle}deg)`,
}"
/>
<!--suppress RequiredAttributes -->
<img v-for="(file, idx) in dynamicFiles"
:key="`${idx}_${file.src}`"
:data-src="file.src"
:style="{
top: `${Math.round(file.top)}px`,
left: `${Math.round(file.left)}px`,
width: `${Math.round(definition.width)}px`,
height: `${Math.round(definition.height)}px`,
transform: `rotate(${definition.angle}deg)`
}"
<img
v-for="(file, idx) in dynamicFiles"
:key="`${idx}_${file.src}`"
:data-src="file.src"
:style="{
top: `${Math.round(file.top)}px`,
left: `${Math.round(file.left)}px`,
width: `${Math.round(definition.width)}px`,
height: `${Math.round(definition.height)}px`,
transform: `rotate(${definition.angle}deg)`,
}"
/>
</div>
</template>
<script lang="ts">
import {defineComponent, PropType} from "vue";
import {rotate} from "@/utils";
import { defineComponent, PropType } from "vue";
import { rotate } from "@/utils";
export default defineComponent({
name: "VideoScroll",
props: {
definition: {
type: Object as PropType<VideoScrollDef>,
required: true
}
required: true,
},
},
computed: {
dynamicFiles(): { top: number, left: number, src: string }[] {
dynamicFiles(): { top: number; left: number; src: string }[] {
return this.definition.files.slice(1).map((src: string, idx: number) => {
const cy = this.definition.top +
(this.isVertical ? (this.definition.height * (idx + 1) * this.verticalDirection) : 0);
const cx = this.definition.left +
(this.isHorizontal ? (this.definition.width * (idx + 1) * this.horizontalDirection) : 0);
const [left, top] = rotate(cx, cy, this.definition.left, this.definition.top, this.definition.angle);
return {top, left, src};
const cy =
this.definition.top +
(this.isVertical
? this.definition.height * (idx + 1) * this.verticalDirection
: 0);
const cx =
this.definition.left +
(this.isHorizontal
? this.definition.width * (idx + 1) * this.horizontalDirection
: 0);
const [left, top] = rotate(
cx,
cy,
this.definition.left,
this.definition.top,
this.definition.angle
);
return { top, left, src };
});
},
isHorizontal(): boolean {
return this.definition.directions.some(
(dir: VideoScrollDirection) => dir === VideoScrollDirection.LEFT || dir === VideoScrollDirection.RIGHT
(dir: VideoScrollDirection) =>
dir === VideoScrollDirection.LEFT ||
dir === VideoScrollDirection.RIGHT
);
},
isVertical(): boolean {
return this.definition.directions.some(
(dir: VideoScrollDirection) => dir === VideoScrollDirection.UP || dir === VideoScrollDirection.DOWN
(dir: VideoScrollDirection) =>
dir === VideoScrollDirection.UP || dir === VideoScrollDirection.DOWN
);
},
horizontalDirection(): number {
return this.definition.directions.includes(VideoScrollDirection.RIGHT) ? 1 : -1;
return this.definition.directions.includes(VideoScrollDirection.RIGHT)
? 1
: -1;
},
verticalDirection(): number {
return this.definition.directions.includes(VideoScrollDirection.DOWN) ? 1 : -1;
}
return this.definition.directions.includes(VideoScrollDirection.DOWN)
? 1
: -1;
},
},
mounted() {
const observer = new IntersectionObserver((entries, _) => {
@ -73,7 +94,9 @@ export default defineComponent({
if (entry.isIntersecting) {
element.classList.add("visible");
if (!element.src) {
console.debug(`[VIDEOSCROLL] Intersected, loading ${element.dataset.src}`);
console.debug(
`[VIDEOSCROLL] Intersected, loading ${element.dataset.src}`
);
element.src = element.dataset.src!;
setTimeout(() => {
element.classList.add("displayed");
@ -93,32 +116,31 @@ export default defineComponent({
}
});
});
if (this.$refs.root){
if (this.$refs.root) {
Array.from((this.$refs.root as Element).children).forEach((el) => {
observer.observe(el);
});
}
}
},
});
export enum VideoScrollDirection {
RIGHT = "right",
LEFT = "left",
UP = "up",
DOWN = "down"
DOWN = "down",
}
export interface VideoScrollDef {
id: string,
top: number,
left: number,
angle: number,
width: number,
height: number,
directions: VideoScrollDirection[],
files: string[]
id: string;
top: number;
left: number;
angle: number;
width: number;
height: number;
directions: VideoScrollDirection[];
files: string[];
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
@ -129,7 +151,7 @@ export interface VideoScrollDef {
background: grey;
visibility: hidden;
opacity: 0;
transition: opacity .5s;
transition: opacity 0.5s;
}
.video-scroll img.visible {