source: main/trunk/model-interfaces-dev/atea/ocr/src/components/EditPage.vue@ 35752

Last change on this file since 35752 was 35751, checked in by cstephen, 2 years ago

Lazy-load jimp to improve startup time.
Add modal dialog.
Confirm with user before resetting.
npm: Add pdf.js

File size: 7.4 KB
Line 
1<template>
2<div class="edit-page-root">
3 <div class="control-panel">
4 <edit-action :description="translations.get('EditPage_Discard')" @action="$emit('closeAndDiscard')" icon="cancel" />
5 <edit-action :description="translations.get('EditPage_InvertColour')" @action="invert = !invert" icon="invert_colors" />
6 <edit-action :description="translations.get('EditPage_Rotate')" v-model="rotateMode" icon="crop_rotate" toggleMode />
7 <edit-action :description="translations.get('EditPage_Save')" @action="closeAndSave" icon="save" />
8 </div>
9
10 <div class="image-panel">
11 <div class="image-container" :style="{ transform: transformString }">
12 <img v-if="rotateMode" src="images/rotate-arrow.svg" class="rotate-handle rotate-tl" @mousedown="allowRotation = true" draggable="false" />
13 <img v-if="rotateMode" src="images/rotate-arrow.svg" class="rotate-handle rotate-tr" @mousedown="allowRotation = true" draggable="false" />
14 <img v-if="rotateMode" src="images/rotate-arrow.svg" class="rotate-handle rotate-bl" @mousedown="allowRotation = true" draggable="false" />
15 <img v-if="rotateMode" src="images/rotate-arrow.svg" class="rotate-handle rotate-br" @mousedown="allowRotation = true" draggable="false" />
16
17 <table v-if="rotateMode" class="rotate-guide" :style="{ transform: transformStringInverted }">
18 <tr><td><hr /></td></tr>
19 <tr><td><hr /></td></tr>
20 <tr><td><hr /></td></tr>
21 <tr><td><hr /></td></tr>
22 <tr><td><hr /></td></tr>
23 <tr><td><hr /></td></tr>
24 <tr><td><hr /></td></tr>
25 <tr><td><hr /></td></tr>
26 <tr><td><hr /></td></tr>
27 <tr><td><hr /></td></tr>
28 <tr><td><hr /></td></tr>
29 <tr><td><hr /></td></tr>
30 </table>
31
32 <img ref="image" :src="src" class="image" :style="{ filter: filterString }" />
33 </div>
34 </div>
35</div>
36</template>
37
38<style lang="scss" scoped>
39.edit-page-root {
40 display: grid;
41 grid-template-columns: auto 1fr;
42 align-items: center;
43 justify-items: center;
44 background: rgba(0, 0, 0, 0.8);
45}
46
47.image-panel {
48 position: relative;
49 height: 100%;
50 width: 100%;
51
52 display: grid;
53 align-items: center;
54 justify-items: center;
55}
56
57.image {
58 max-width: 70vw;
59 max-height: 70vh;
60}
61
62.image-container {
63 position: relative;
64 margin: auto;
65 padding: 1.5em;
66 user-select: none;
67
68 .rotate-handle {
69 height: 2em;
70 position: absolute;
71 z-index: 5;
72
73 // Generated with https://codepen.io/sosuke/pen/Pjoqqp using var(--primary-bg-color)
74 // filter: invert(16%) sepia(100%) saturate(3091%) hue-rotate(347deg) brightness(75%) contrast(90%);
75 }
76
77 .rotate-tl {
78 top: 0;
79 left: 0;
80 }
81
82 .rotate-tr {
83 top: 0;
84 right: 0;
85 transform: rotate(90deg);
86 }
87
88 .rotate-bl {
89 bottom: 0;
90 left: 0;
91 transform: rotate(270deg);
92 }
93
94 .rotate-br {
95 bottom: 0;
96 right: 0;
97 transform: rotate(180deg);
98 }
99}
100
101.rotate-guide {
102 position: absolute;
103 top: 0;
104 left: 0;
105 height: 100%;
106 width: 100%;
107 z-index: 3;
108
109 tr {
110 td {
111 vertical-align: center;
112 }
113
114 hr {
115 background-color: rgba(var(--bg-color-raw), 0.5);
116 height: 2px;
117 }
118 }
119}
120
121.control-panel {
122 display: flex;
123 flex-direction: column;
124 justify-content: center;
125 align-items: flex-start;
126
127 padding: 0.5em;
128 gap: 1em;
129 height: 100%;
130
131 // background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.2) 10%);
132}
133
134.edit-action {
135 display: flex;
136 position: relative;
137
138 .infotab {
139 position: absolute;
140 height: 70%;
141 top: 15%;
142 left: 120%;
143
144 display: flex;
145 align-items: center;
146 justify-content: center;
147 visibility: hidden;
148
149 width: 0;
150 min-width: 0;
151 padding: 0 0.2em;
152
153 white-space: nowrap;
154 transition-duration: var(--transition-duration);
155 }
156
157 .btn-fab:hover + .infotab {
158 visibility: visible;
159 min-width: 10em;
160 }
161}
162</style>
163
164<script>
165import { mapState } from "vuex";
166import EditAction from "./EditAction.vue"
167
168export default {
169 name: "EditPage",
170 components: {
171 EditAction
172 },
173 props: {
174 imageBuffer: ArrayBuffer,
175 src: String
176 },
177 emits: [ "closeAndDiscard", "closeAndSave" ],
178 data() {
179 return {
180 invert: false,
181 rotation: 0,
182 rotateMode: false,
183 allowRotation: false
184 }
185 },
186 computed: {
187 ...mapState({
188 translations: state => state.translations,
189 filterString() {
190 let filters = "";
191
192 if (this.invert) {
193 filters += "invert(1) ";
194 }
195
196 return filters;
197 },
198 transformString() {
199 return `rotate(${this.rotation}deg)`;
200 },
201 transformStringInverted() {
202 return `rotate(-${this.rotation}deg)`;
203 }
204 })
205 },
206 methods: {
207 async closeAndSave() {
208 const Jimp = await import("jimp/es");
209
210 const buffer = Buffer.from(this.imageBuffer);
211 const that = this;
212
213 const modifiedBuffer = await Jimp.read(buffer)
214 .then(async image => {
215 if (that.invert) {
216 image.invert();
217 }
218
219 if (that.rotation !== 0) {
220 image.rotate(-that.rotation);
221 }
222
223 return await image.getBufferAsync(Jimp.MIME_PNG);
224 });
225
226 this.$emit("closeAndSave", modifiedBuffer, Jimp.MIME_PNG);
227 },
228
229 onRotateHandleMouseDown(point) {
230 console.log(point);
231 this.rotatePoint = point;
232 },
233 /**
234 * @param {MouseEvent} e The mouse movement event.
235 */
236 onDocumentMouseMove(e) {
237 if (!this.allowRotation) {
238 return;
239 }
240
241 const imageRectangle = this.$refs.image.getBoundingClientRect();
242 const imageCenterX = (imageRectangle.width / 2) + imageRectangle.left;
243 const imageCenterY = (imageRectangle.height / 2) + imageRectangle.top;
244
245 if (e.clientX > imageCenterX) {
246 this.rotation += e.movementY / 8;
247 }
248 else {
249 this.rotation -= e.movementY / 8;
250 }
251
252 if (e.clientY > imageCenterY) {
253 this.rotation -= e.movementX / 8;
254 }
255 else {
256 this.rotation += e.movementX / 8;
257 }
258
259 if (this.rotation < 0) {
260 this.rotation = 360 + this.rotation;
261 }
262 else if (this.rotation > 360) {
263 this.rotation -= 360;
264 }
265 },
266 onDocumentMouseUp() {
267 this.allowRotation = false;
268 }
269 },
270 beforeMount() {
271 document.addEventListener("mousemove", this.onDocumentMouseMove);
272 document.addEventListener("mouseup", this.onDocumentMouseUp);
273 },
274 beforeUnmount() {
275 document.removeEventListener("mousemove", this.onDocumentMouseMove);
276 document.removeEventListener("mouseup", this.onDocumentMouseUp);
277 }
278}
279</script>
Note: See TracBrowser for help on using the repository browser.