-
Notifications
You must be signed in to change notification settings - Fork 24
/
DjvuReader.vue
122 lines (117 loc) · 3.56 KB
/
DjvuReader.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
<template lang="pug">
.container.col-md-8.offset-md-2(v-if="is_rendering")
loading-spinner(style="margin-top: 140px" :label="'rendering...'")
div(ref="wrapper")
canvas(v-show="!is_rendering" id="djvu-reader" ref="reader")
</template>
<script lang="ts">
import {defineComponent, type PropType, toRaw} from 'vue'
import router from "@/router";
import ConnectivityIssuesView from "@/components/ConnectivityIssues.vue";
import LoadingSpinner from "@/components/LoadingSpinner.vue";
import DjVu from "@/components/djvu";
import Hammer from 'hammerjs'
export default defineComponent({
name: 'DjvuReader',
emits: ["update-anchor"],
components: {ConnectivityIssuesView, LoadingSpinner},
props: {
anchor: undefined as PropType<string>,
data: {
type: undefined as PropType<ArrayBuffer>
},
},
data() {
let d = {
is_rendering: false,
hammer: undefined,
current_page: 1,
mounted: false,
scale: 0.8,
worker: undefined,
}
if (this.anchor !== undefined) {
d.current_page = Number.parseInt(this.anchor);
}
return d;
},
async created() {
this.worker = new DjVu.Worker();
await toRaw(this.worker).createDocument(this.data, undefined);
await this.render(undefined);
},
mounted() {
this.hammer = Hammer(this.$refs.reader, { touchAction : 'pan-y' });
document.addEventListener("keyup", this.key_listener);
this.hammer.get('swipe').set({ direction: Hammer.DIRECTION_HORIZONTAL })
this.hammer.get('pan').set({ direction: Hammer.DIRECTION_ALL });
this.hammer.get('pinch').set({ enable: true });
this.hammer.on('panstart panmove', (ev) => ev.preventDefault());
this.hammer.on('swipeleft', () => this.next_page());
this.hammer.on('swiperight', () => this.previous_page());
this.mounted = true
},
beforeUnmount() {
if (this.mounted) {
document.removeEventListener("keyup", this.key_listener, {capture: true});
this.hammer.off("swipeleft");
this.hammer.off("swiperight");
this.hammer.off("panstart");
this.hammer.off("panmove");
}
this.mounted = false;
},
methods: {
async render(old_page) {
this.is_rendering = true;
try {
const resultImageData = await toRaw(this.worker).doc.getPage(this.current_page).getImageData().run();
this.$refs.reader.width = resultImageData.width;
this.$refs.reader.height = resultImageData.height;
this.$refs.reader.style.width = `${100 * this.scale}%`
this.$refs.reader.style['min-width'] = `${100 * this.scale}%`
const context = this.$refs.reader.getContext('2d');
context.putImageData(resultImageData, 0, 0);
this.$emit("update-anchor", this.current_page.toString())
} catch {
if (old_page !== undefined) {
this.current_page = old_page;
}
}
finally {
this.is_rendering = false;
}
},
previous_page() {
const old_page = this.current_page;
this.current_page -= 1;
this.render(old_page);
},
next_page() {
const old_page = this.current_page;
this.current_page += 1;
this.render(old_page);
},
key_listener(event) {
event.preventDefault();
if (event.key == "ArrowLeft") {
this.previous_page()
} else if (event.key == "ArrowRight") {
this.next_page()
} else if (event.key === "Escape") {
router.back();
return;
}
},
}
})
</script>
<style lang="scss" scoped>
#djvu-reader {
display: block;
margin-left: auto;
margin-right: auto;
min-width: 100%;
width: 100%;
}
</style>