add small dev panel
This commit is contained in:
parent
28b44e262e
commit
70a09e9eec
1 changed files with 61 additions and 17 deletions
|
@ -1,15 +1,29 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="content" ref="root">
|
<div class="svg-content">
|
||||||
<div class="video-scrolls">
|
<div class="content" ref="root">
|
||||||
<VideoScroll v-for="scroll in scrolls" :definition="scroll"/>
|
<div class="video-scrolls">
|
||||||
|
<VideoScroll v-for="scroll in scrolls" :definition="scroll"/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<AudioArea v-for="audio in audioAreas" :definition="audio" :bbox="bbox"/>
|
<AudioArea v-for="audio in audioAreas" :definition="audio" :bbox="bbox"/>
|
||||||
|
<div class="devpanel">
|
||||||
|
<div>
|
||||||
|
Current position: {{ Math.round(bbox.x) }}x{{ Math.round(bbox.y) }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Zoom level: {{ currentTransform ? (Math.round(currentTransform.scale * 1000) / 1000) : '???' }}
|
||||||
|
</div>
|
||||||
|
<label>
|
||||||
|
<input v-model="showInternal" type="checkbox">
|
||||||
|
<label>Show internal elements</label>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {defineComponent, onMounted, reactive, ref} from "vue";
|
import {defineComponent, onMounted, reactive, ref} from "vue";
|
||||||
import createPanZoom, {PanZoom} from "panzoom";
|
import createPanZoom, {PanZoom, Transform} from "panzoom";
|
||||||
import VideoScroll, {VideoScrollDef, VideoScrollDirection} from "@/components/VideoScroll.vue";
|
import VideoScroll, {VideoScrollDef, VideoScrollDirection} from "@/components/VideoScroll.vue";
|
||||||
import AudioArea, {AudioAreaDef} from "@/components/AudioArea.vue";
|
import AudioArea, {AudioAreaDef} from "@/components/AudioArea.vue";
|
||||||
import Stats from "stats.js";
|
import Stats from "stats.js";
|
||||||
|
@ -23,13 +37,26 @@ export default defineComponent({
|
||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showInternal: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
showInternal(value) {
|
||||||
|
Array.from(this.root!.getElementsByClassName("internal")).forEach((el) => {
|
||||||
|
(el as SVGElement).style.visibility = value ? "visible" : "hidden";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
setup(props, {emit}) {
|
setup(props, {emit}) {
|
||||||
const root = ref(null);
|
const root = ref<HTMLDivElement | null>(null);
|
||||||
const panzoom = ref<null | PanZoom>(null);
|
const panzoom = ref<null | PanZoom>(null);
|
||||||
const anchors = ref<SVGRectElement[]>([]);
|
const anchors = ref<SVGRectElement[]>([]);
|
||||||
const scrolls = ref<VideoScrollDef[]>([]);
|
const scrolls = ref<VideoScrollDef[]>([]);
|
||||||
const panToAnchor = ref();
|
const panToAnchor = ref();
|
||||||
const audioAreas = ref<AudioAreaDef[]>([]);
|
const audioAreas = ref<AudioAreaDef[]>([]);
|
||||||
|
const currentTransform = ref<Transform | null>(null);
|
||||||
const bbox = reactive({
|
const bbox = reactive({
|
||||||
x: ref(0),
|
x: ref(0),
|
||||||
y: ref(0),
|
y: ref(0),
|
||||||
|
@ -69,6 +96,20 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
panzoom.value = pz;
|
panzoom.value = pz;
|
||||||
|
currentTransform.value = pz.getTransform();
|
||||||
|
|
||||||
|
// Calculate SVG-unit bounding box, update transform
|
||||||
|
pz.on("transform", function (_) {
|
||||||
|
const transform = pz.getTransform();
|
||||||
|
const currentRatio = svg.clientWidth * transform.scale / svg.viewBox.baseVal.width;
|
||||||
|
|
||||||
|
bbox.x = transform.x / currentRatio * -1;
|
||||||
|
bbox.y = transform.y / currentRatio * -1;
|
||||||
|
bbox.w = window.innerWidth / currentRatio;
|
||||||
|
bbox.h = window.innerHeight / currentRatio;
|
||||||
|
|
||||||
|
currentTransform.value = transform;
|
||||||
|
});
|
||||||
|
|
||||||
function panToElement(element: SVGRectElement, smooth: boolean) {
|
function panToElement(element: SVGRectElement, smooth: boolean) {
|
||||||
const transform = pz.getTransform();
|
const transform = pz.getTransform();
|
||||||
|
@ -103,17 +144,6 @@ export default defineComponent({
|
||||||
panToElement(start, false);
|
panToElement(start, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate SVG-unit bounding box
|
|
||||||
pz.on("transform", function (_) {
|
|
||||||
const transform = pz.getTransform();
|
|
||||||
const currentRatio = svg.clientWidth * transform.scale / svg.viewBox.baseVal.width;
|
|
||||||
|
|
||||||
bbox.x = transform.x / currentRatio * -1;
|
|
||||||
bbox.y = transform.y / currentRatio * -1;
|
|
||||||
bbox.w = window.innerWidth / currentRatio;
|
|
||||||
bbox.h = window.innerHeight / currentRatio;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Edge scrolling
|
// Edge scrolling
|
||||||
const MOVE_EDGE = 75;
|
const MOVE_EDGE = 75;
|
||||||
const MAX_SPEED = 20;
|
const MAX_SPEED = 20;
|
||||||
|
@ -194,7 +224,8 @@ export default defineComponent({
|
||||||
panToAnchor,
|
panToAnchor,
|
||||||
scrolls,
|
scrolls,
|
||||||
audioAreas,
|
audioAreas,
|
||||||
bbox
|
bbox,
|
||||||
|
currentTransform
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -279,4 +310,17 @@ function processStart(svg: XMLDocument): SVGRectElement | null {
|
||||||
svg .internal {
|
svg .internal {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.devpanel {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 999;
|
||||||
|
|
||||||
|
color: white;
|
||||||
|
background: #000000aa;
|
||||||
|
border: 2px solid white;
|
||||||
|
font-family: monospace;
|
||||||
|
padding: 1em 2em;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in a new issue