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

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

Improve editing action buttons

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 Jimp from "jimp/es";
167import EditAction from "./EditAction.vue"
168
169export default {
170 name: "EditPage",
171 components: {
172 EditAction
173 },
174 props: {
175 imageBuffer: ArrayBuffer,
176 src: String
177 },
178 emits: [ "closeAndDiscard", "closeAndSave" ],
179 data() {
180 return {
181 invert: false,
182 rotation: 0,
183 rotateMode: false,
184 allowRotation: false
185 }
186 },
187 computed: {
188 ...mapState({
189 translations: state => state.translations,
190 filterString() {
191 let filters = "";
192
193 if (this.invert) {
194 filters += "invert(1) ";
195 }
196
197 return filters;
198 },
199 transformString() {
200 return `rotate(${this.rotation}deg)`;
201 },
202 transformStringInverted() {
203 return `rotate(-${this.rotation}deg)`;
204 }
205 })
206 },
207 methods: {
208 async closeAndSave() {
209 const buffer = Buffer.from(this.imageBuffer);
210 const that = this;
211
212 const modifiedBuffer = await Jimp.read(buffer)
213 .then(async image => {
214 if (that.invert) {
215 image.invert();
216 }
217
218 if (that.rotation !== 0) {
219 image.rotate(-that.rotation);
220 }
221
222 return await image.getBufferAsync(Jimp.MIME_PNG);
223 });
224
225 this.$emit("closeAndSave", modifiedBuffer, Jimp.MIME_PNG);
226 },
227
228 onRotateHandleMouseDown(point) {
229 console.log(point);
230 this.rotatePoint = point;
231 },
232 /**
233 * @param {MouseEvent} e The mouse movement event.
234 */
235 onDocumentMouseMove(e) {
236 if (!this.allowRotation) {
237 return;
238 }
239
240 const imageRectangle = this.$refs.image.getBoundingClientRect();
241 const imageCenterX = (imageRectangle.width / 2) + imageRectangle.left;
242 const imageCenterY = (imageRectangle.height / 2) + imageRectangle.top;
243
244 if (e.clientX > imageCenterX) {
245 this.rotation += e.movementY / 8;
246 }
247 else {
248 this.rotation -= e.movementY / 8;
249 }
250
251 if (e.clientY > imageCenterY) {
252 this.rotation -= e.movementX / 8;
253 }
254 else {
255 this.rotation += e.movementX / 8;
256 }
257
258 if (this.rotation < 0) {
259 this.rotation = 360 + this.rotation;
260 }
261 else if (this.rotation > 360) {
262 this.rotation -= 360;
263 }
264 },
265 onDocumentMouseUp() {
266 this.allowRotation = false;
267 }
268 },
269 beforeMount() {
270 document.addEventListener("mousemove", this.onDocumentMouseMove);
271 document.addEventListener("mouseup", this.onDocumentMouseUp);
272 },
273 beforeUnmount() {
274 document.removeEventListener("mousemove", this.onDocumentMouseMove);
275 document.removeEventListener("mouseup", this.onDocumentMouseUp);
276 }
277}
278</script>
Note: See TracBrowser for help on using the repository browser.