diff options
author | OzoneGrif | 2020-04-28 03:28:20 +0200 |
---|---|---|
committer | GitHub | 2020-04-28 03:28:20 +0200 |
commit | 20fda5a867d9afb0a90eda78834c487df40abd05 (patch) | |
tree | e9350f02a188fd35bcbe19a835e28a5116344f60 /viewer | |
parent | add23cc6e83a677f8e747348a2429050efe8c515 (diff) | |
parent | b4b698ccbdec98dd902b6290f12207bf5547b140 (diff) | |
download | ldgallery-20fda5a867d9afb0a90eda78834c487df40abd05.tar.gz |
Merge pull request #195 from pacien/scroll-zoom
viewer/LdPicture: implement mousewheel and pinch zoom
Diffstat (limited to 'viewer')
-rw-r--r-- | viewer/package-lock.json | 15 | ||||
-rw-r--r-- | viewer/package.json | 3 | ||||
-rw-r--r-- | viewer/src/@types/gallery.d.ts | 10 | ||||
-rw-r--r-- | viewer/src/components/LdPicture.vue | 56 | ||||
-rw-r--r-- | viewer/src/services/ldzoom.ts | 134 | ||||
-rw-r--r-- | viewer/src/views/MainLayout.vue | 1 |
6 files changed, 186 insertions, 33 deletions
diff --git a/viewer/package-lock.json b/viewer/package-lock.json index 228788d..d4a5fb0 100644 --- a/viewer/package-lock.json +++ b/viewer/package-lock.json | |||
@@ -1232,6 +1232,11 @@ | |||
1232 | "@types/node": "*" | 1232 | "@types/node": "*" |
1233 | } | 1233 | } |
1234 | }, | 1234 | }, |
1235 | "@types/hammerjs": { | ||
1236 | "version": "2.0.36", | ||
1237 | "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.36.tgz", | ||
1238 | "integrity": "sha512-7TUK/k2/QGpEAv/BCwSHlYu3NXZhQ9ZwBYpzr9tjlPIL2C5BeGhH3DmVavRx3ZNyELX5TLC91JTz/cen6AAtIQ==" | ||
1239 | }, | ||
1235 | "@types/json-schema": { | 1240 | "@types/json-schema": { |
1236 | "version": "7.0.4", | 1241 | "version": "7.0.4", |
1237 | "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz", | 1242 | "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz", |
@@ -6487,6 +6492,11 @@ | |||
6487 | "pify": "^4.0.1" | 6492 | "pify": "^4.0.1" |
6488 | } | 6493 | } |
6489 | }, | 6494 | }, |
6495 | "hammerjs": { | ||
6496 | "version": "2.0.8", | ||
6497 | "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz", | ||
6498 | "integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE=" | ||
6499 | }, | ||
6490 | "handle-thing": { | 6500 | "handle-thing": { |
6491 | "version": "2.0.1", | 6501 | "version": "2.0.1", |
6492 | "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", | 6502 | "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", |
@@ -10464,6 +10474,11 @@ | |||
10464 | "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", | 10474 | "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", |
10465 | "dev": true | 10475 | "dev": true |
10466 | }, | 10476 | }, |
10477 | "resize-observer-polyfill": { | ||
10478 | "version": "1.5.1", | ||
10479 | "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", | ||
10480 | "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" | ||
10481 | }, | ||
10467 | "resolve": { | 10482 | "resolve": { |
10468 | "version": "1.14.1", | 10483 | "version": "1.14.1", |
10469 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.14.1.tgz", | 10484 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.14.1.tgz", |
diff --git a/viewer/package.json b/viewer/package.json index 40a91ba..bc63dfd 100644 --- a/viewer/package.json +++ b/viewer/package.json | |||
@@ -13,8 +13,11 @@ | |||
13 | "@fortawesome/fontawesome-svg-core": "^1.2.28", | 13 | "@fortawesome/fontawesome-svg-core": "^1.2.28", |
14 | "@fortawesome/free-solid-svg-icons": "^5.13.0", | 14 | "@fortawesome/free-solid-svg-icons": "^5.13.0", |
15 | "@fortawesome/vue-fontawesome": "^0.1.9", | 15 | "@fortawesome/vue-fontawesome": "^0.1.9", |
16 | "@types/hammerjs": "^2.0.36", | ||
16 | "buefy": "^0.8.15", | 17 | "buefy": "^0.8.15", |
17 | "core-js": "^3.6.4", | 18 | "core-js": "^3.6.4", |
19 | "hammerjs": "^2.0.8", | ||
20 | "resize-observer-polyfill": "^1.5.1", | ||
18 | "v-lazy-image": "^1.4.0", | 21 | "v-lazy-image": "^1.4.0", |
19 | "vue": "^2.6.11", | 22 | "vue": "^2.6.11", |
20 | "vue-class-component": "^7.2.3", | 23 | "vue-class-component": "^7.2.3", |
diff --git a/viewer/src/@types/gallery.d.ts b/viewer/src/@types/gallery.d.ts index de1c0dd..956ab6b 100644 --- a/viewer/src/@types/gallery.d.ts +++ b/viewer/src/@types/gallery.d.ts | |||
@@ -49,12 +49,17 @@ declare namespace Gallery { | |||
49 | thumbnail?: Thumbnail | 49 | thumbnail?: Thumbnail |
50 | properties: OtherProperties | PictureProperties | DirectoryProperties, | 50 | properties: OtherProperties | PictureProperties | DirectoryProperties, |
51 | } | 51 | } |
52 | interface Resolution { | ||
53 | width: number, | ||
54 | height: number, | ||
55 | } | ||
52 | interface OtherProperties { | 56 | interface OtherProperties { |
53 | type: "other", | 57 | type: "other", |
54 | } | 58 | } |
55 | interface PictureProperties { | 59 | interface PictureProperties { |
56 | type: "picture", | 60 | type: "picture", |
57 | resource: string, | 61 | resource: string, |
62 | resolution: Resolution | ||
58 | } | 63 | } |
59 | interface DirectoryProperties { | 64 | interface DirectoryProperties { |
60 | type: "directory", | 65 | type: "directory", |
@@ -62,10 +67,7 @@ declare namespace Gallery { | |||
62 | } | 67 | } |
63 | interface Thumbnail { | 68 | interface Thumbnail { |
64 | resource: string, | 69 | resource: string, |
65 | resolution: { | 70 | resolution: Resolution |
66 | width: number, | ||
67 | height: number, | ||
68 | } | ||
69 | } | 71 | } |
70 | type RawTag = string; | 72 | type RawTag = string; |
71 | type ItemType = "other" | "picture" | "directory"; | 73 | type ItemType = "other" | "picture" | "directory"; |
diff --git a/viewer/src/components/LdPicture.vue b/viewer/src/components/LdPicture.vue index 3170c81..de46bcb 100644 --- a/viewer/src/components/LdPicture.vue +++ b/viewer/src/components/LdPicture.vue | |||
@@ -18,17 +18,21 @@ | |||
18 | --> | 18 | --> |
19 | 19 | ||
20 | <template> | 20 | <template> |
21 | <!-- FIXME: v-dragscroll interferes with pinch-to-zoom --> | ||
21 | <div | 22 | <div |
23 | ref="containerElement" | ||
22 | v-dragscroll | 24 | v-dragscroll |
23 | class="scrollbar" | 25 | class="scrollbar ld-picture-container" |
24 | :class="{'fit-to-screen': !$uiStore.fullscreen, 'original-size': $uiStore.fullscreen}" | ||
25 | @click.capture="e => dragScrollClickFix.onClickCapture(e)" | 26 | @click.capture="e => dragScrollClickFix.onClickCapture(e)" |
26 | @click="$uiStore.toggleFullscreen()" | 27 | @dblclick="$uiStore.toggleFullscreen()" |
28 | @dragstart.prevent | ||
27 | @dragscrollstart="dragScrollClickFix.onDragScrollStart()" | 29 | @dragscrollstart="dragScrollClickFix.onDragScrollStart()" |
28 | @dragscrollend="dragScrollClickFix.onDragScrollEnd()" | 30 | @dragscrollend="dragScrollClickFix.onDragScrollEnd()" |
29 | > | 31 | > |
30 | <v-lazy-image | 32 | <v-lazy-image |
33 | ref="imageElement" | ||
31 | :src="pictureSrc(picture.properties.resource)" | 34 | :src="pictureSrc(picture.properties.resource)" |
35 | class="ld-picture-element" | ||
32 | :class="{'slow-loading': Boolean(slowLoadingStyle)}" | 36 | :class="{'slow-loading': Boolean(slowLoadingStyle)}" |
33 | :style="slowLoadingStyle" | 37 | :style="slowLoadingStyle" |
34 | @load="clearSlowLoading" | 38 | @load="clearSlowLoading" |
@@ -38,12 +42,15 @@ | |||
38 | </template> | 42 | </template> |
39 | 43 | ||
40 | <script lang="ts"> | 44 | <script lang="ts"> |
41 | import { Component, Vue, Prop } from "vue-property-decorator"; | 45 | import { Component, Vue, Prop, Ref } from "vue-property-decorator"; |
46 | import LdZoom from "@/services/ldzoom"; | ||
42 | import DragScrollClickFix from "@/services/dragscrollclickfix"; | 47 | import DragScrollClickFix from "@/services/dragscrollclickfix"; |
43 | 48 | ||
44 | @Component | 49 | @Component |
45 | export default class LdPicture extends Vue { | 50 | export default class LdPicture extends Vue { |
46 | @Prop({ required: true }) readonly picture!: Gallery.Picture; | 51 | @Prop({ required: true }) readonly picture!: Gallery.Picture; |
52 | @Ref() readonly containerElement!: HTMLDivElement; | ||
53 | @Ref() readonly imageElement!: Vue; | ||
47 | 54 | ||
48 | readonly SLOW_LOADING_TIMEOUT_MS: number = 1500; | 55 | readonly SLOW_LOADING_TIMEOUT_MS: number = 1500; |
49 | readonly dragScrollClickFix = new DragScrollClickFix(); | 56 | readonly dragScrollClickFix = new DragScrollClickFix(); |
@@ -54,6 +61,7 @@ export default class LdPicture extends Vue { | |||
54 | 61 | ||
55 | mounted() { | 62 | mounted() { |
56 | this.timer = setTimeout(this.generateSlowLoadingStyle, this.SLOW_LOADING_TIMEOUT_MS); | 63 | this.timer = setTimeout(this.generateSlowLoadingStyle, this.SLOW_LOADING_TIMEOUT_MS); |
64 | new LdZoom(this.containerElement, this.imageElement.$el as HTMLImageElement, this.picture.properties, 10, 1 / 5).install(); | ||
57 | } | 65 | } |
58 | 66 | ||
59 | destroyed() { | 67 | destroyed() { |
@@ -85,13 +93,17 @@ export default class LdPicture extends Vue { | |||
85 | <style lang="scss"> | 93 | <style lang="scss"> |
86 | @import "~@/assets/scss/theme.scss"; | 94 | @import "~@/assets/scss/theme.scss"; |
87 | 95 | ||
88 | .ld-picture-loader { | 96 | .ld-picture-container { |
89 | position: relative; | 97 | height: 100%; |
90 | & .loading-background { | ||
91 | background: none !important; | ||
92 | } | ||
93 | } | 98 | } |
94 | img.slow-loading { | 99 | |
100 | .ld-picture-element { | ||
101 | max-width: unset; | ||
102 | max-height: unset; | ||
103 | cursor: grab; | ||
104 | } | ||
105 | |||
106 | .slow-loading { | ||
95 | background-repeat: no-repeat; | 107 | background-repeat: no-repeat; |
96 | background-position: center; | 108 | background-position: center; |
97 | background-size: contain; | 109 | background-size: contain; |
@@ -99,25 +111,11 @@ img.slow-loading { | |||
99 | background-blend-mode: soft-light; | 111 | background-blend-mode: soft-light; |
100 | opacity: 1 !important; | 112 | opacity: 1 !important; |
101 | } | 113 | } |
102 | .fit-to-screen { | 114 | |
103 | display: flex; | 115 | .ld-picture-loader { |
104 | justify-content: space-around; | 116 | position: relative; |
105 | height: 100%; | 117 | & .loading-background { |
106 | & > img { | 118 | background: none !important; |
107 | object-fit: contain; | ||
108 | cursor: zoom-in; | ||
109 | } | ||
110 | } | ||
111 | .original-size { | ||
112 | display: block; | ||
113 | text-align: center; | ||
114 | cursor: grab; | ||
115 | height: 100%; | ||
116 | & > img { | ||
117 | max-width: unset; | ||
118 | max-height: unset; | ||
119 | object-fit: none; | ||
120 | cursor: zoom-out; | ||
121 | } | 119 | } |
122 | } | 120 | } |
123 | </style> | 121 | </style> |