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

Last change on this file since 35743 was 35743, checked in by cstephen, 13 months ago

Rework for single image content.
Implement rotation and inversion editing.

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