OpenSeadragon viewer implemented
This commit is contained in:
parent
cc3620d2ed
commit
a9b94bc0d8
3 changed files with 166 additions and 8 deletions
|
|
@ -17,6 +17,7 @@
|
||||||
"material-design-icons": "^3.0",
|
"material-design-icons": "^3.0",
|
||||||
"material-symbols": "^0.14.3",
|
"material-symbols": "^0.14.3",
|
||||||
"mousetrap": "^1.6.5",
|
"mousetrap": "^1.6.5",
|
||||||
|
"openseadragon": "^5.0.0",
|
||||||
"vue-observe-visibility": "^0.4"
|
"vue-observe-visibility": "^0.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,96 @@
|
||||||
|
<template>
|
||||||
|
<div v-observe-visibility="visibilityChanged">
|
||||||
|
<div id="openseadragon"></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import OpenSeaDragon from "openseadragon";
|
||||||
|
|
||||||
|
// Export main app
|
||||||
|
export default {
|
||||||
|
name: "OpenSeadragonViewer",
|
||||||
|
components: { },
|
||||||
|
|
||||||
|
props: {
|
||||||
|
src: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data: function() {
|
||||||
|
return {
|
||||||
|
osdViewer: null
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
src: {
|
||||||
|
immediate: true,
|
||||||
|
handler(newVal) {
|
||||||
|
this.loadOpenSeaDragon(newVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async mounted() {
|
||||||
|
if (this.src) {
|
||||||
|
this.loadOpenSeaDragon(this.src);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeDestroy() {
|
||||||
|
// Remove global signal listener to perform a gallery refresh
|
||||||
|
this.osdViewer.destroy();
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
visibilityChanged(isVisible) {
|
||||||
|
if (isVisible) {
|
||||||
|
this.loadOpenSeaDragon();
|
||||||
|
}else{
|
||||||
|
this.osdViewer.destroy();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async loadOpenSeaDragon() {
|
||||||
|
if (this.osdViewer) {
|
||||||
|
this.osdViewer.destroy();
|
||||||
|
}
|
||||||
|
this.osdViewer = OpenSeaDragon({
|
||||||
|
id: "openseadragon",
|
||||||
|
crossOriginPolicy: 'Anonymous',
|
||||||
|
tileSources: this.src,
|
||||||
|
showNavigationControl: false,
|
||||||
|
maxZoomPixelRatio: 2,
|
||||||
|
gestureSettingsMouse: {
|
||||||
|
clickToZoom: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
openFullscreen() {
|
||||||
|
if (this.osdViewer) {
|
||||||
|
this.osdViewer.setFullScreen(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
#openseadragon {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: black;
|
||||||
|
z-index:1;
|
||||||
|
}
|
||||||
|
#info-panel {
|
||||||
|
position: relative;
|
||||||
|
top: 10px;
|
||||||
|
left: 10px;
|
||||||
|
background-color: rgba(255, 255, 255, 0.7);
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 1px;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
v-observe-visibility="visibilityChanged"
|
v-observe-visibility="visibilityChanged"
|
||||||
class="galleryDisplay uk-padding uk-padding-remove-top"
|
class="galleryDisplay uk-padding uk-padding-remove-top">
|
||||||
>
|
|
||||||
<!-- Gallery nav bar -->
|
<!-- Gallery nav bar -->
|
||||||
<nav
|
<nav
|
||||||
class="gallery-navbar uk-navbar-container uk-navbar-transparent"
|
class="gallery-navbar uk-navbar-container uk-navbar-transparent"
|
||||||
|
|
@ -35,6 +34,26 @@
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
<!-- Modal for scan display -->
|
||||||
|
<div id="scan-modal" ref="scanModal" uk-modal>
|
||||||
|
<div class="uk-modal-dialog uk-modal-body" v-if="selectedScan" style="width: 95%; height: 95%;">
|
||||||
|
<h2 class="uk-modal-title">
|
||||||
|
{{ selectedScan.name }}
|
||||||
|
<button class="uk-modal-close uk-float-right" type="button"><span class="material-symbols-outlined">close</span></button>
|
||||||
|
<button class="uk-float-right" type="button" @click="goFullscreen">
|
||||||
|
<span class="material-symbols-outlined">fullscreen</span>
|
||||||
|
</button>
|
||||||
|
</h2>
|
||||||
|
<div v-if="selectedScanDZIAvailable" id="viewer_container" style="height: 80%;">
|
||||||
|
<OpenSeadragonViewer
|
||||||
|
id="openseadragon"
|
||||||
|
ref="openseadragon"
|
||||||
|
:src="selectedScanDZI"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Gallery -->
|
<!-- Gallery -->
|
||||||
<div
|
<div
|
||||||
v-if="$store.getters.ready"
|
v-if="$store.getters.ready"
|
||||||
|
|
@ -50,7 +69,7 @@
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div v-for="item in scans" :key="item.id">
|
<div v-for="item in scans" :key="item.id">
|
||||||
<div class="uk-card">
|
<div class="uk-card" @click="showScan(item)">
|
||||||
<div class="uk-card-body">
|
<div class="uk-card-body">
|
||||||
<div class="uk-card-media-top">
|
<div class="uk-card-media-top">
|
||||||
<div
|
<div
|
||||||
|
|
@ -65,7 +84,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="uk-card-title" style="text-align: center;">{{ item.name }}</h3>
|
<h3 class="uk-card-title" style="text-align: center;">{{ item.name }}</h3>
|
||||||
<action-button
|
<div class="button-container">
|
||||||
|
<action-button
|
||||||
thing="smart_scan"
|
thing="smart_scan"
|
||||||
action="download_zip"
|
action="download_zip"
|
||||||
submit-label="Download ZIP"
|
submit-label="Download ZIP"
|
||||||
|
|
@ -105,20 +125,25 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import UIkit from "uikit";
|
||||||
import actionButton from "../labThingsComponents/actionButton.vue";
|
import actionButton from "../labThingsComponents/actionButton.vue";
|
||||||
|
import OpenSeadragonViewer from "./scanListComponents/openSeadragonViewer.vue";
|
||||||
|
|
||||||
// Export main app
|
// Export main app
|
||||||
export default {
|
export default {
|
||||||
name: "ScanListContent",
|
name: "ScanListContent",
|
||||||
components: { actionButton },
|
components: { actionButton, OpenSeadragonViewer },
|
||||||
|
|
||||||
data: function() {
|
data: function() {
|
||||||
return {
|
return {
|
||||||
scans: []
|
scans: [],
|
||||||
|
selectedScan: null,
|
||||||
|
osdViewer: null
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -133,6 +158,16 @@ export default {
|
||||||
},
|
},
|
||||||
scansEmpty() {
|
scansEmpty() {
|
||||||
return this.scans.length == 0;
|
return this.scans.length == 0;
|
||||||
|
},
|
||||||
|
selectedScanDZI() {
|
||||||
|
if (this.selectedScan && this.dzi!="") {
|
||||||
|
return `${this.$store.getters.baseUri}/scans/${this.selectedScan.name}/images/${this.selectedScan.dzi}`;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
selectedScanDZIAvailable() {
|
||||||
|
return this.selectedScan && this.selectedScan.dzi;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -185,6 +220,9 @@ export default {
|
||||||
this.updateScans();
|
this.updateScans();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
goFullscreen() {
|
||||||
|
this.$refs.openseadragon.openFullscreen();
|
||||||
|
},
|
||||||
async updateScans() {
|
async updateScans() {
|
||||||
try {
|
try {
|
||||||
let scans = await this.readThingProperty("smart_scan", "scans");
|
let scans = await this.readThingProperty("smart_scan", "scans");
|
||||||
|
|
@ -194,7 +232,7 @@ export default {
|
||||||
scans.forEach(scan => {
|
scans.forEach(scan => {
|
||||||
scan.modified = Date.parse(scan.modified);
|
scan.modified = Date.parse(scan.modified);
|
||||||
scan.created = Date.parse(scan.created);
|
scan.created = Date.parse(scan.created);
|
||||||
scan.can_stitch = !scan.stitch_available && scan.number_of_images > 3;
|
scan.can_stitch = !scan.stitch_available && scan.number_of_images > 3 || !scan.dzi && scan.number_of_images > 3;
|
||||||
});
|
});
|
||||||
scans.sort((a, b) => {
|
scans.sort((a, b) => {
|
||||||
return b.modified - a.modified;
|
return b.modified - a.modified;
|
||||||
|
|
@ -256,7 +294,16 @@ export default {
|
||||||
console.log(link);
|
console.log(link);
|
||||||
document.body.appendChild(link);
|
document.body.appendChild(link);
|
||||||
link.click();
|
link.click();
|
||||||
}
|
},
|
||||||
|
showScan(scan) {
|
||||||
|
if (scan.dzi){
|
||||||
|
this.selectedScan = scan;
|
||||||
|
UIkit.modal(this.$refs.scanModal).show();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.modalError(`Scan not stitched for viewing in webapp, please download or stitch`)
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -285,6 +332,20 @@ export default {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#openseadragon {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
#info-panel {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
left: 10px;
|
||||||
|
background-color: rgba(255, 255, 255, 0.7);
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 1px;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
/deep/ .capture-card {
|
/deep/ .capture-card {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
height: 100%; // Used to have all cards in a row match their heights
|
height: 100%; // Used to have all cards in a row match their heights
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue