summaryrefslogtreecommitdiff
path: root/packages/frontend/src/components/MkImageEffectorDialog.vue
diff options
context:
space:
mode:
Diffstat (limited to 'packages/frontend/src/components/MkImageEffectorDialog.vue')
-rw-r--r--packages/frontend/src/components/MkImageEffectorDialog.vue112
1 files changed, 30 insertions, 82 deletions
diff --git a/packages/frontend/src/components/MkImageEffectorDialog.vue b/packages/frontend/src/components/MkImageEffectorDialog.vue
index 3d7801f925..85e86e3a77 100644
--- a/packages/frontend/src/components/MkImageEffectorDialog.vue
+++ b/packages/frontend/src/components/MkImageEffectorDialog.vue
@@ -16,37 +16,36 @@ SPDX-License-Identifier: AGPL-3.0-only
>
<template #header><i class="ti ti-sparkles"></i> {{ i18n.ts._imageEffector.title }}</template>
- <div :class="$style.root">
- <div :class="$style.container">
- <div :class="[$style.preview, prefer.s.animation ? $style.animatedBg : null]">
- <canvas ref="canvasEl" :class="$style.previewCanvas" @pointerdown.prevent.stop="onImagePointerdown"></canvas>
- <div :class="$style.previewContainer">
- <div class="_acrylic" :class="$style.previewTitle">{{ i18n.ts.preview }}</div>
- <div class="_acrylic" :class="$style.editControls">
- <button class="_button" :class="[$style.previewControlsButton, penMode != null ? $style.active : null]" @click="showPenMenu"><i class="ti ti-pencil"></i></button>
- </div>
- <div class="_acrylic" :class="$style.previewControls">
- <button class="_button" :class="[$style.previewControlsButton, !enabled ? $style.active : null]" @click="enabled = false">Before</button>
- <button class="_button" :class="[$style.previewControlsButton, enabled ? $style.active : null]" @click="enabled = true">After</button>
- </div>
+ <MkPreviewWithControls>
+ <template #preview>
+ <canvas ref="canvasEl" :class="$style.previewCanvas" @pointerdown.prevent.stop="onImagePointerdown"></canvas>
+ <div :class="$style.previewContainer">
+ <div class="_acrylic" :class="$style.previewTitle">{{ i18n.ts.preview }}</div>
+ <div class="_acrylic" :class="$style.editControls">
+ <button class="_button" :class="[$style.previewControlsButton, penMode != null ? $style.active : null]" @click="showPenMenu"><i class="ti ti-pencil"></i></button>
+ </div>
+ <div class="_acrylic" :class="$style.previewControls">
+ <button class="_button" :class="[$style.previewControlsButton, !enabled ? $style.active : null]" @click="enabled = false">Before</button>
+ <button class="_button" :class="[$style.previewControlsButton, enabled ? $style.active : null]" @click="enabled = true">After</button>
</div>
</div>
- <div :class="$style.controls">
- <div class="_spacer _gaps">
- <XLayer
- v-for="(layer, i) in layers"
- :key="layer.id"
- v-model:layer="layers[i]"
- @del="onLayerDelete(layer)"
- @swapUp="onLayerSwapUp(layer)"
- @swapDown="onLayerSwapDown(layer)"
- ></XLayer>
+ </template>
- <MkButton rounded primary style="margin: 0 auto;" @click="addEffect"><i class="ti ti-plus"></i> {{ i18n.ts._imageEffector.addEffect }}</MkButton>
- </div>
+ <template #controls>
+ <div class="_spacer _gaps">
+ <XLayer
+ v-for="(layer, i) in layers"
+ :key="layer.id"
+ v-model:layer="layers[i]"
+ @del="onLayerDelete(layer)"
+ @swapUp="onLayerSwapUp(layer)"
+ @swapDown="onLayerSwapDown(layer)"
+ ></XLayer>
+
+ <MkButton rounded primary style="margin: 0 auto;" @click="addEffect"><i class="ti ti-plus"></i> {{ i18n.ts._imageEffector.addEffect }}</MkButton>
</div>
- </div>
- </div>
+ </template>
+ </MkPreviewWithControls>
</MkModalWindow>
</template>
@@ -56,15 +55,12 @@ import type { ImageEffectorLayer } from '@/utility/image-effector/ImageEffector.
import { i18n } from '@/i18n.js';
import { ImageEffector } from '@/utility/image-effector/ImageEffector.js';
import MkModalWindow from '@/components/MkModalWindow.vue';
-import MkSelect from '@/components/MkSelect.vue';
+import MkPreviewWithControls from '@/components/MkPreviewWithControls.vue';
import MkButton from '@/components/MkButton.vue';
-import MkInput from '@/components/MkInput.vue';
import XLayer from '@/components/MkImageEffectorDialog.Layer.vue';
import * as os from '@/os.js';
-import { deepClone } from '@/utility/clone.js';
import { FXS } from '@/utility/image-effector/fxs.js';
import { genId } from '@/utility/id.js';
-import { prefer } from '@/preferences.js';
const props = defineProps<{
image: File;
@@ -99,7 +95,7 @@ watch(layers, async () => {
}
}, { deep: true });
-function addEffect(ev: MouseEvent) {
+function addEffect(ev: PointerEvent) {
os.popupMenu(Object.entries(FXS).map(([id, fx]) => ({
text: fx.uiDefinition.name,
action: () => {
@@ -223,7 +219,7 @@ watch(enabled, () => {
const penMode = ref<'fill' | 'blur' | 'pixelate' | null>(null);
-function showPenMenu(ev: MouseEvent) {
+function showPenMenu(ev: PointerEvent) {
os.popupMenu([{
text: i18n.ts._imageEffector._fxs.fill,
action: () => {
@@ -299,7 +295,7 @@ function onImagePointerdown(ev: PointerEvent) {
scaleX: 0.1,
scaleY: 0.1,
angle: 0,
- radius: 3,
+ radius: 10,
ellipse: false,
},
});
@@ -367,33 +363,6 @@ function onImagePointerdown(ev: PointerEvent) {
</script>
<style module>
-.root {
- container-type: inline-size;
- height: 100%;
-}
-
-.container {
- height: 100%;
- display: grid;
- grid-template-columns: 1fr 400px;
-}
-
-.preview {
- position: relative;
- background-color: var(--MI_THEME-bg);
- background-image: linear-gradient(135deg, transparent 30%, var(--MI_THEME-panel) 30%, var(--MI_THEME-panel) 50%, transparent 50%, transparent 80%, var(--MI_THEME-panel) 80%, var(--MI_THEME-panel) 100%);
- background-size: 20px 20px;
-}
-
-.animatedBg {
- animation: bg 1.2s linear infinite;
-}
-
-@keyframes bg {
- 0% { background-position: 0 0; }
- 100% { background-position: -20px -20px; }
-}
-
.previewContainer {
display: flex;
flex-direction: column;
@@ -442,16 +411,6 @@ function onImagePointerdown(ev: PointerEvent) {
}
}
-.previewSpinner {
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- pointer-events: none;
- user-select: none;
- -webkit-user-drag: none;
-}
-
.previewCanvas {
position: absolute;
top: 0;
@@ -467,15 +426,4 @@ function onImagePointerdown(ev: PointerEvent) {
object-fit: contain;
touch-action: none;
}
-
-.controls {
- overflow-y: scroll;
-}
-
-@container (max-width: 800px) {
- .container {
- grid-template-columns: 1fr;
- grid-template-rows: 1fr 1fr;
- }
-}
</style>