From e50f10156c21e526bdbd78109bbd4fb99af4a53e Mon Sep 17 00:00:00 2001 From: Miha Lunar Date: Tue, 30 Aug 2022 21:53:00 +0200 Subject: [PATCH 1/2] Replace OpenSeadragon with OpenLayers Bonus: Refactor scroll updates --- README.md | 6 +- ui/package-lock.json | 422 +++++++++++++++++++++++++-- ui/package.json | 2 +- ui/src/components/NaturalViewer.vue | 54 ++-- ui/src/components/Overlays.vue | 107 +++++-- ui/src/components/TileViewer.vue | 437 ++++++++++++++-------------- ui/src/components/VideoPlayer.vue | 2 +- 7 files changed, 727 insertions(+), 303 deletions(-) diff --git a/README.md b/README.md index dfa0751..5173a51 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ gallery software. ### Features * **Seamless zoomable interface**. Thanks to tiled image loading supported by -[OpenSeadragon] and the API implementing tile rendering, you can switch between +[OpenLayers] and the API implementing tile rendering, you can switch between levels of detail seamlessly without loading a special detailed or fullscreen view. @@ -134,7 +134,8 @@ over time as IDs can change. fast single-file database/cache * [Vue 3] - frontend framework * [BalmUI] - Material UI components -* [OpenSeadragon] - in-browser tiled image rendering +* [OpenLayers] - in-browser tiled image rendering +* [OpenSeadragon] (honorary mention) - tiled image rendering library used previously * [+ more Go libraries](go.mod) * [+ more npm libraries](ui/package.json) @@ -370,6 +371,7 @@ Distributed under the MIT License. See `LICENSE` for more information. [godirwalk]: https://github.com/karrick/godirwalk [prominent color]: https://github.com/EdlinOrg/prominentcolor +[OpenLayers]: https://openlayers.org/ [OpenSeadragon]: https://openseadragon.github.io/ [Node.js]: https://nodejs.org/ [Vue 3]: https://v3.vuejs.org/ diff --git a/ui/package-lock.json b/ui/package-lock.json index 7867e45..0b1de49 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -15,7 +15,7 @@ "balm-ui": "^10.9.0", "copy-image-clipboard": "^1.0.1", "date-fns": "^2.28.0", - "openseadragon": "^3.1.0", + "ol": "^6.15.1", "overlayscrollbars": "^1.13.2", "plyr": "^3.7.2", "qs": "^6.11.0", @@ -106,6 +106,45 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "node_modules/@mapbox/jsonlint-lines-primitives": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz", + "integrity": "sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@mapbox/mapbox-gl-style-spec": { + "version": "13.25.0", + "resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-style-spec/-/mapbox-gl-style-spec-13.25.0.tgz", + "integrity": "sha512-ukBk13MyI/X4tjRfPaNCo4rJLrRJ7ZbANxjeQyGeLYJTF1DZxqkX9C8qlxnQlxYllBBDBWiYYX5lU1fIsm2jwg==", + "dependencies": { + "@mapbox/jsonlint-lines-primitives": "~2.0.2", + "@mapbox/point-geometry": "^0.1.0", + "@mapbox/unitbezier": "^0.0.0", + "csscolorparser": "~1.0.2", + "json-stringify-pretty-compact": "^2.0.0", + "minimist": "^1.2.5", + "rw": "^1.3.3", + "sort-object": "^0.3.2" + }, + "bin": { + "gl-style-composite": "bin/gl-style-composite.js", + "gl-style-format": "bin/gl-style-format.js", + "gl-style-migrate": "bin/gl-style-migrate.js", + "gl-style-validate": "bin/gl-style-validate.js" + } + }, + "node_modules/@mapbox/point-geometry": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz", + "integrity": "sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ==" + }, + "node_modules/@mapbox/unitbezier": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-0.0.0.tgz", + "integrity": "sha512-HPnRdYO0WjFjRTSwO3frz1wKaU649OBFPX3Zo/2WZvuRi6zMiRGui8SnPQiQABgqCf8YikDe5t3HViTVw1WUzA==" + }, "node_modules/@material/animation": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/@material/animation/-/animation-14.0.0.tgz", @@ -853,6 +892,11 @@ "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.12.tgz", "integrity": "sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg==" }, + "node_modules/@petamoriken/float16": { + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.6.6.tgz", + "integrity": "sha512-3MUulwMtsdCA9lw8a/Kc0XDBJJVCkYTQ5aGd+///TbfkOMXoOGAzzoiYKwPEsLYZv7He7fKJ/mCacqKOO7REyg==" + }, "node_modules/@vitejs/plugin-vue": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-1.10.2.tgz", @@ -1196,6 +1240,11 @@ "node": ">= 8" } }, + "node_modules/csscolorparser": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/csscolorparser/-/csscolorparser-1.0.3.tgz", + "integrity": "sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w==" + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -2017,6 +2066,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/geotiff": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/geotiff/-/geotiff-2.0.4.tgz", + "integrity": "sha512-aG8h9bJccGusioPsEWsEqx8qdXpZN71A20WCvRKGxcnHSOWLKmC5ZmsAmodfxb9TRQvs+89KikGuPzxchhA+Uw==", + "dependencies": { + "@petamoriken/float16": "^3.4.7", + "lerc": "^3.0.0", + "lru-cache": "^6.0.0", + "pako": "^2.0.4", + "parse-headers": "^2.0.2", + "web-worker": "^1.2.0", + "xml-utils": "^1.0.2" + }, + "engines": { + "browsers": "defaults", + "node": ">=10.19" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -2124,6 +2191,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", @@ -2294,6 +2380,11 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "node_modules/json-stringify-pretty-compact": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-2.0.0.tgz", + "integrity": "sha512-WRitRfs6BGq4q8gTgOy4ek7iPFXjbra0H3PmDLKm2xnZ+Gh1HUhiKGgCZkSPNULlP7mvfu6FV/mOLhCarspADQ==" + }, "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -2306,6 +2397,11 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/lerc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lerc/-/lerc-3.0.0.tgz", + "integrity": "sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww==" + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -2340,7 +2436,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -2356,6 +2451,11 @@ "sourcemap-codec": "^1.4.4" } }, + "node_modules/mapbox-to-css-font": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/mapbox-to-css-font/-/mapbox-to-css-font-2.4.1.tgz", + "integrity": "sha512-QQ/iKiM43DM9+aujTL45Iz5o7gDeSFmy4LPl3HZmNcwCE++NxGazf+yFpY+wCb+YS23sDa1ghpo3zrNFOcHlow==" + }, "node_modules/material-components-web": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/material-components-web/-/material-components-web-14.0.0.tgz", @@ -2424,6 +2524,11 @@ "node": "*" } }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -2475,6 +2580,30 @@ "node": ">= 0.4" } }, + "node_modules/ol": { + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/ol/-/ol-6.15.1.tgz", + "integrity": "sha512-ZG2CKTpJ8Q+tPywYysVwPk+yevwJzlbwjRKhoCvd7kLVWMbfBl1O/+Kg/yrZZrhG9FNXbFH4GeOZ5yVRqo3P4w==", + "dependencies": { + "geotiff": "2.0.4", + "ol-mapbox-style": "^8.0.5", + "pbf": "3.2.1", + "rbush": "^3.0.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/openlayers" + } + }, + "node_modules/ol-mapbox-style": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/ol-mapbox-style/-/ol-mapbox-style-8.2.1.tgz", + "integrity": "sha512-3kBBuZC627vDL8vnUdfVbCbfkhkcZj2kXPHQcuLhC4JJEA+XkEVEtEde8x8+AZctRbHwBkSiubTPaRukgLxIRw==", + "dependencies": { + "@mapbox/mapbox-gl-style-spec": "^13.23.1", + "mapbox-to-css-font": "^2.4.1" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -2501,14 +2630,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/openseadragon": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/openseadragon/-/openseadragon-3.1.0.tgz", - "integrity": "sha512-0zCbRIWUbCto7xm1tv2ZLEiSl84cDU659W/sfs2zqqTqVRa4CRHzhy7i9nsv6dHA1DryFR8IzjStjmWOqRs9Rg==", - "funding": { - "url": "https://opencollective.com/openseadragon" - } - }, "node_modules/optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -2531,6 +2652,11 @@ "resolved": "https://registry.npmjs.org/overlayscrollbars/-/overlayscrollbars-1.13.2.tgz", "integrity": "sha512-xk9eJ8fpuh28WABSDpMpOv90aDQk+x5wLeqU4AGbJg56eGLeKxVPQzMxeX6+BM2dsIIOcBj3Fwvn8A0EzhHN3g==" }, + "node_modules/pako": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.0.4.tgz", + "integrity": "sha512-v8tweI900AUkZN6heMU/4Uy4cXRc2AYNRggVmTR+dEncawDJgCdLMximOVA2p4qO57WMynangsfGRb5WD6L1Bg==" + }, "node_modules/parchment": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/parchment/-/parchment-1.1.4.tgz", @@ -2548,6 +2674,11 @@ "node": ">=6" } }, + "node_modules/parse-headers": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz", + "integrity": "sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==" + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -2571,6 +2702,18 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, + "node_modules/pbf": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.2.1.tgz", + "integrity": "sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==", + "dependencies": { + "ieee754": "^1.1.12", + "resolve-protobuf-schema": "^2.1.0" + }, + "bin": { + "pbf": "bin/pbf" + } + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -2633,6 +2776,11 @@ "node": ">= 0.8.0" } }, + "node_modules/protocol-buffers-schema": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz", + "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==" + }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -2656,6 +2804,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/quickselect": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz", + "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==" + }, "node_modules/quill": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/quill/-/quill-1.3.7.tgz", @@ -2687,6 +2840,14 @@ "resolved": "https://registry.npmjs.org/rangetouch/-/rangetouch-2.0.1.tgz", "integrity": "sha512-sln+pNSc8NGaHoLzwNBssFSf/rSYkqeBXzX1AtJlkJiUaVSJSbRAWJk+4omsXkN+EJalzkZhWQ3th1m0FpR5xA==" }, + "node_modules/rbush": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/rbush/-/rbush-3.0.1.tgz", + "integrity": "sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==", + "dependencies": { + "quickselect": "^2.0.0" + } + }, "node_modules/regexp.prototype.flags": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", @@ -2749,6 +2910,14 @@ "node": ">=4" } }, + "node_modules/resolve-protobuf-schema": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz", + "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==", + "dependencies": { + "protocol-buffers-schema": "^3.3.1" + } + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -2808,6 +2977,11 @@ "node": ">= 8" } }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" + }, "node_modules/semver": { "version": "7.3.7", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", @@ -2857,6 +3031,34 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/sort-asc": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/sort-asc/-/sort-asc-0.1.0.tgz", + "integrity": "sha512-jBgdDd+rQ+HkZF2/OHCmace5dvpos/aWQpcxuyRs9QUbPRnkEJmYVo81PIGpjIdpOcsnJ4rGjStfDHsbn+UVyw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sort-desc": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/sort-desc/-/sort-desc-0.1.1.tgz", + "integrity": "sha512-jfZacW5SKOP97BF5rX5kQfJmRVZP5/adDUTY8fCSPvNcXDVpUEe2pr/iKGlcyZzchRJZrswnp68fgk3qBXgkJw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sort-object": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/sort-object/-/sort-object-0.3.2.tgz", + "integrity": "sha512-aAQiEdqFTTdsvUFxXm3umdo04J7MRljoVGbBlkH7BgNsMvVNAJyGj7C/wV1A8wHWAJj/YikeZbfuCKqhggNWGA==", + "dependencies": { + "sort-asc": "^0.1.0", + "sort-desc": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -3186,6 +3388,11 @@ "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.37.tgz", "integrity": "sha512-4rSJemR2NQIo9Klm1vabqWjD8rs/ZaJSzMxkMNeJS6lHiUjjUeYFbooN19NgFjztubEKh3WlZUeOLVdbbUWHsw==" }, + "node_modules/web-worker": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.2.0.tgz", + "integrity": "sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==" + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -3242,6 +3449,11 @@ "node": ">=12" } }, + "node_modules/xml-utils": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/xml-utils/-/xml-utils-1.2.0.tgz", + "integrity": "sha512-z4unVPZruEDC3tfyd7wvWfjclnMz34iwQpv8H28H+qREpjKkR083MBvcrWXfJrIcrSmHR5ghguOcgQqWdnBpVA==" + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -3254,8 +3466,7 @@ "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yargs": { "version": "17.5.1", @@ -3347,6 +3558,36 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "@mapbox/jsonlint-lines-primitives": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz", + "integrity": "sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==" + }, + "@mapbox/mapbox-gl-style-spec": { + "version": "13.25.0", + "resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-style-spec/-/mapbox-gl-style-spec-13.25.0.tgz", + "integrity": "sha512-ukBk13MyI/X4tjRfPaNCo4rJLrRJ7ZbANxjeQyGeLYJTF1DZxqkX9C8qlxnQlxYllBBDBWiYYX5lU1fIsm2jwg==", + "requires": { + "@mapbox/jsonlint-lines-primitives": "~2.0.2", + "@mapbox/point-geometry": "^0.1.0", + "@mapbox/unitbezier": "^0.0.0", + "csscolorparser": "~1.0.2", + "json-stringify-pretty-compact": "^2.0.0", + "minimist": "^1.2.5", + "rw": "^1.3.3", + "sort-object": "^0.3.2" + } + }, + "@mapbox/point-geometry": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz", + "integrity": "sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ==" + }, + "@mapbox/unitbezier": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-0.0.0.tgz", + "integrity": "sha512-HPnRdYO0WjFjRTSwO3frz1wKaU649OBFPX3Zo/2WZvuRi6zMiRGui8SnPQiQABgqCf8YikDe5t3HViTVw1WUzA==" + }, "@material/animation": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/@material/animation/-/animation-14.0.0.tgz", @@ -4096,6 +4337,11 @@ } } }, + "@petamoriken/float16": { + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.6.6.tgz", + "integrity": "sha512-3MUulwMtsdCA9lw8a/Kc0XDBJJVCkYTQ5aGd+///TbfkOMXoOGAzzoiYKwPEsLYZv7He7fKJ/mCacqKOO7REyg==" + }, "@vitejs/plugin-vue": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-1.10.2.tgz", @@ -4391,6 +4637,11 @@ "which": "^2.0.1" } }, + "csscolorparser": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/csscolorparser/-/csscolorparser-1.0.3.tgz", + "integrity": "sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w==" + }, "cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -4910,6 +5161,20 @@ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" }, + "geotiff": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/geotiff/-/geotiff-2.0.4.tgz", + "integrity": "sha512-aG8h9bJccGusioPsEWsEqx8qdXpZN71A20WCvRKGxcnHSOWLKmC5ZmsAmodfxb9TRQvs+89KikGuPzxchhA+Uw==", + "requires": { + "@petamoriken/float16": "^3.4.7", + "lerc": "^3.0.0", + "lru-cache": "^6.0.0", + "pako": "^2.0.4", + "parse-headers": "^2.0.2", + "web-worker": "^1.2.0", + "xml-utils": "^1.0.2" + } + }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -4984,6 +5249,11 @@ "has-symbols": "^1.0.2" } }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, "ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", @@ -5106,6 +5376,11 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "json-stringify-pretty-compact": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-2.0.0.tgz", + "integrity": "sha512-WRitRfs6BGq4q8gTgOy4ek7iPFXjbra0H3PmDLKm2xnZ+Gh1HUhiKGgCZkSPNULlP7mvfu6FV/mOLhCarspADQ==" + }, "jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -5116,6 +5391,11 @@ "universalify": "^2.0.0" } }, + "lerc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lerc/-/lerc-3.0.0.tgz", + "integrity": "sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww==" + }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -5147,7 +5427,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "requires": { "yallist": "^4.0.0" } @@ -5160,6 +5439,11 @@ "sourcemap-codec": "^1.4.4" } }, + "mapbox-to-css-font": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/mapbox-to-css-font/-/mapbox-to-css-font-2.4.1.tgz", + "integrity": "sha512-QQ/iKiM43DM9+aujTL45Iz5o7gDeSFmy4LPl3HZmNcwCE++NxGazf+yFpY+wCb+YS23sDa1ghpo3zrNFOcHlow==" + }, "material-components-web": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/material-components-web/-/material-components-web-14.0.0.tgz", @@ -5225,6 +5509,11 @@ "brace-expansion": "^1.1.7" } }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -5261,6 +5550,26 @@ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, + "ol": { + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/ol/-/ol-6.15.1.tgz", + "integrity": "sha512-ZG2CKTpJ8Q+tPywYysVwPk+yevwJzlbwjRKhoCvd7kLVWMbfBl1O/+Kg/yrZZrhG9FNXbFH4GeOZ5yVRqo3P4w==", + "requires": { + "geotiff": "2.0.4", + "ol-mapbox-style": "^8.0.5", + "pbf": "3.2.1", + "rbush": "^3.0.1" + } + }, + "ol-mapbox-style": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/ol-mapbox-style/-/ol-mapbox-style-8.2.1.tgz", + "integrity": "sha512-3kBBuZC627vDL8vnUdfVbCbfkhkcZj2kXPHQcuLhC4JJEA+XkEVEtEde8x8+AZctRbHwBkSiubTPaRukgLxIRw==", + "requires": { + "@mapbox/mapbox-gl-style-spec": "^13.23.1", + "mapbox-to-css-font": "^2.4.1" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -5281,11 +5590,6 @@ "is-wsl": "^2.2.0" } }, - "openseadragon": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/openseadragon/-/openseadragon-3.1.0.tgz", - "integrity": "sha512-0zCbRIWUbCto7xm1tv2ZLEiSl84cDU659W/sfs2zqqTqVRa4CRHzhy7i9nsv6dHA1DryFR8IzjStjmWOqRs9Rg==" - }, "optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -5305,6 +5609,11 @@ "resolved": "https://registry.npmjs.org/overlayscrollbars/-/overlayscrollbars-1.13.2.tgz", "integrity": "sha512-xk9eJ8fpuh28WABSDpMpOv90aDQk+x5wLeqU4AGbJg56eGLeKxVPQzMxeX6+BM2dsIIOcBj3Fwvn8A0EzhHN3g==" }, + "pako": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.0.4.tgz", + "integrity": "sha512-v8tweI900AUkZN6heMU/4Uy4cXRc2AYNRggVmTR+dEncawDJgCdLMximOVA2p4qO57WMynangsfGRb5WD6L1Bg==" + }, "parchment": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/parchment/-/parchment-1.1.4.tgz", @@ -5319,6 +5628,11 @@ "callsites": "^3.0.0" } }, + "parse-headers": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz", + "integrity": "sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==" + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -5336,6 +5650,15 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, + "pbf": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.2.1.tgz", + "integrity": "sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==", + "requires": { + "ieee754": "^1.1.12", + "resolve-protobuf-schema": "^2.1.0" + } + }, "picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -5379,6 +5702,11 @@ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, + "protocol-buffers-schema": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz", + "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==" + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -5393,6 +5721,11 @@ "side-channel": "^1.0.4" } }, + "quickselect": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz", + "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==" + }, "quill": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/quill/-/quill-1.3.7.tgz", @@ -5421,6 +5754,14 @@ "resolved": "https://registry.npmjs.org/rangetouch/-/rangetouch-2.0.1.tgz", "integrity": "sha512-sln+pNSc8NGaHoLzwNBssFSf/rSYkqeBXzX1AtJlkJiUaVSJSbRAWJk+4omsXkN+EJalzkZhWQ3th1m0FpR5xA==" }, + "rbush": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/rbush/-/rbush-3.0.1.tgz", + "integrity": "sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==", + "requires": { + "quickselect": "^2.0.0" + } + }, "regexp.prototype.flags": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", @@ -5459,6 +5800,14 @@ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, + "resolve-protobuf-schema": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz", + "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==", + "requires": { + "protocol-buffers-schema": "^3.3.1" + } + }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -5496,6 +5845,11 @@ } } }, + "rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" + }, "semver": { "version": "7.3.7", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", @@ -5530,6 +5884,25 @@ "object-inspect": "^1.9.0" } }, + "sort-asc": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/sort-asc/-/sort-asc-0.1.0.tgz", + "integrity": "sha512-jBgdDd+rQ+HkZF2/OHCmace5dvpos/aWQpcxuyRs9QUbPRnkEJmYVo81PIGpjIdpOcsnJ4rGjStfDHsbn+UVyw==" + }, + "sort-desc": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/sort-desc/-/sort-desc-0.1.1.tgz", + "integrity": "sha512-jfZacW5SKOP97BF5rX5kQfJmRVZP5/adDUTY8fCSPvNcXDVpUEe2pr/iKGlcyZzchRJZrswnp68fgk3qBXgkJw==" + }, + "sort-object": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/sort-object/-/sort-object-0.3.2.tgz", + "integrity": "sha512-aAQiEdqFTTdsvUFxXm3umdo04J7MRljoVGbBlkH7BgNsMvVNAJyGj7C/wV1A8wHWAJj/YikeZbfuCKqhggNWGA==", + "requires": { + "sort-asc": "^0.1.0", + "sort-desc": "^0.1.1" + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -5776,6 +6149,11 @@ "@vue/devtools-api": "^6.1.4" } }, + "web-worker": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.2.0.tgz", + "integrity": "sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==" + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -5814,6 +6192,11 @@ "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", "dev": true }, + "xml-utils": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/xml-utils/-/xml-utils-1.2.0.tgz", + "integrity": "sha512-z4unVPZruEDC3tfyd7wvWfjclnMz34iwQpv8H28H+qREpjKkR083MBvcrWXfJrIcrSmHR5ghguOcgQqWdnBpVA==" + }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -5823,8 +6206,7 @@ "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yargs": { "version": "17.5.1", diff --git a/ui/package.json b/ui/package.json index 56d7d47..f551ac7 100644 --- a/ui/package.json +++ b/ui/package.json @@ -13,7 +13,7 @@ "balm-ui": "^10.9.0", "copy-image-clipboard": "^1.0.1", "date-fns": "^2.28.0", - "openseadragon": "^3.1.0", + "ol": "^6.15.1", "overlayscrollbars": "^1.13.2", "plyr": "^3.7.2", "qs": "^6.11.0", diff --git a/ui/src/components/NaturalViewer.vue b/ui/src/components/NaturalViewer.vue index c6a0c11..2a25681 100644 --- a/ui/src/components/NaturalViewer.vue +++ b/ui/src/components/NaturalViewer.vue @@ -38,7 +38,7 @@ @@ -335,20 +335,26 @@ export default { }).keepLatest(); const scrollTop = ref(0); - let scrollTopLastUpdate = 0; - watch(scrollTop, (newValue, oldValue) => { + const scrollRatio = ref(0); + const scrollLastUpdate = ref(0); + const scrollSpeed = ref(0); + const scrollUpdateTask = useTask(function*(_, ratio, top) { + yield timeout(200); + const prevTop = scrollTop.value; + const prevTime = scrollLastUpdate.value; const now = Date.now(); - const diff = newValue - oldValue; - const elapsed = now - scrollTopLastUpdate; + scrollTop.value = top; + scrollRatio.value = ratio; + scrollLastUpdate.value = now; + const elapsed = now - prevTime; + const diff = top - prevTop; const pxPerSec = Math.abs(diff) * 1000 / elapsed; - scrollSpeedTask.perform(pxPerSec); - scrollTopLastUpdate = now; - }) - - const scrollSpeed = ref(0); - const scrollSpeedTask = useTask(function*(_, y) { - scrollSpeed.value = y; - yield timeout(500); + scrollSpeed.value += (pxPerSec - scrollSpeed.value) * 0.9; + scrollResetTask.perform(); + }).keepLatest(); + + const scrollResetTask = useTask(function*(_) { + yield timeout(1000); scrollSpeed.value = 0; }).restartable(); @@ -376,9 +382,7 @@ export default { const timestamps = computed(() => { return new Uint32Array(datesBuffer.value); - }) - - const scrollRatio = ref(0); + }); const scrollDate = computed(() => { if (!timestamps.value || timestamps.value.length < 1) return; @@ -423,8 +427,7 @@ export default { regionSeekApplyTask, visibleViewTask, visibleRegions, - scrollRatio, - scrollTop, + scrollUpdateTask, scrollDate, scrollSpeed, } @@ -814,7 +817,7 @@ export default { }, async onZoom(zoom) { - if (!this.wasRecentlyFocused() && zoom < 0.99) { + if (!this.wasRecentlyFocused() && zoom <= 1.1) { this.nativeScroll = true; this.pushScrollToView(); } @@ -898,7 +901,6 @@ export default { }, setView(view, transition) { - // console.log(view, transition); this.$refs.viewer.setView( view, transition && { animationTime: transition } @@ -1001,8 +1003,7 @@ export default { }) } - this.scrollRatio = scrollRatio; - this.scrollTop = scrollTop; + this.scrollUpdateTask.perform(scrollRatio, scrollTop); return scrollRatio; }, @@ -1044,7 +1045,11 @@ export default { scrollY = scrollTop; } } - + + if (viewMaxY < scrollY) { + this.scrollbar.scroll([0, viewMaxY + "px"]); + } + // Ratio can be outside of range if the range has changed recently scrollRatio = Math.min(1, Math.max(0, scrollRatio)); @@ -1061,8 +1066,7 @@ export default { this.$refs.viewer.$el.style.transform = `translate(0, ${scrollY}px)`; this.visibleViewTask.perform(view, this.sceneParams); - this.scrollRatio = scrollRatio; - this.scrollTop = scrollY; + this.scrollUpdateTask.perform(scrollRatio, scrollY); }, } diff --git a/ui/src/components/Overlays.vue b/ui/src/components/Overlays.vue index e27d583..07b72e2 100644 --- a/ui/src/components/Overlays.vue +++ b/ui/src/components/Overlays.vue @@ -3,7 +3,7 @@
-import OpenSeadragon from "openseadragon"; import VideoPlayer from './VideoPlayer.vue'; +import Overlay from 'ol/Overlay'; export default { @@ -42,25 +42,24 @@ export default { emits: ["interactive"], - async created() { - this.tempRect = new OpenSeadragon.Rect(); + mounted() { + this.mountViewer(this.viewer); + }, + + unmounted() { + this.unmountViewer(); }, watch: { - viewer: { - immediate: true, - handler(viewer) { - if (!viewer) return; - this.initViewer(viewer); - this.updateOverlay(this.overlay); - }, + viewer(viewer) { + this.mountViewer(viewer); }, overlay: { immediate: true, handler(overlay) { this.updateOverlay(overlay); } - } + }, }, computed: { @@ -69,36 +68,77 @@ export default { poolId: 0, region: this.overlay, }]; - } + }, }, - + methods: { - initViewer(viewer) { - viewer.addOverlay( - "overlay-0", - new OpenSeadragon.Rect( - 0, - 0, - 0, - 0, - ), - ); + mountViewer(viewer) { + if (viewer != this.mountedViewer) { + this.unmountViewer(); + if (viewer) { + viewer.getView().on("change:resolution", this.onResolutionChange); + } + } + this.mountedViewer = viewer; + if (!viewer) return; + + const ref = this.$refs["overlay-0"]; + if (ref && !this.olOverlay) { + const overlays = viewer.getOverlays(); + const length = overlays.push(new Overlay({ + element: ref[0], + stopEvent: false, + })) + const overlay = overlays.item(length - 1); + this.olOverlay = overlay; + this.updateOverlay(overlay); + } + }, + + unmountViewer() { + const viewer = this.mountedViewer; + this.mountedViewer = null; + if (!viewer) return; + if (this.olOverlay) { + viewer.removeOverlay(this.olOverlay); + this.olOverlay = null; + } + viewer.getView().un("change:resolution", this.onResolutionChange); + }, + + onResolutionChange() { + this.updateOverlay(this.overlay); + }, + + extentFromView(view) { + if (!this.scene) throw new Error("Scene not found"); + const fullExtent = this.viewer.getView().getProjection().getExtent(); + const fw = fullExtent[2] - fullExtent[0]; + const fh = fullExtent[3] - fullExtent[1]; + const sx = fw / this.scene.bounds.w; + const sy = fh / this.scene.bounds.h; + const tx = view.x * sx; + const ty = fh - view.y * sy; + const tw = view.w * sx; + const th = view.h * sy; + return [tx, ty-th, tx+tw, ty]; }, updateOverlay(region) { if (!region || !region.bounds) return; if (!this.viewer) return; - const overlay = this.viewer.getOverlayById("overlay-0"); - const scale = 1 / this.scene.bounds.w; - const rect = this.tempRect; - rect.x = region.bounds.x * scale; - rect.y = region.bounds.y * scale; - rect.width = region.bounds.w * scale; - rect.height = region.bounds.h * scale; + const overlay = this.olOverlay; + if (!overlay) return; - overlay.update(rect); + const extent = this.extentFromView(region.bounds); + overlay.setPosition([extent[0], extent[3]]); + + const element = overlay.element; + const resolution = this.viewer.getView().getResolution(); + element.style.width = (extent[2] - extent[0]) / resolution + "px"; + element.style.height = (extent[3] - extent[1]) / resolution + "px"; }, } @@ -106,4 +146,7 @@ export default { diff --git a/ui/src/components/TileViewer.vue b/ui/src/components/TileViewer.vue index 1da9fb4..6b55588 100644 --- a/ui/src/components/TileViewer.vue +++ b/ui/src/components/TileViewer.vue @@ -1,12 +1,18 @@