wip
This commit is contained in:
parent
d1b4456845
commit
ddc8072103
|
@ -12083,6 +12083,10 @@ export interface Locale extends ILocale {
|
||||||
* エフェクトを追加
|
* エフェクトを追加
|
||||||
*/
|
*/
|
||||||
"addEffect": string;
|
"addEffect": string;
|
||||||
|
/**
|
||||||
|
* 変更を破棄して終了しますか?
|
||||||
|
*/
|
||||||
|
"discardChangesConfirm": string;
|
||||||
"_fxs": {
|
"_fxs": {
|
||||||
/**
|
/**
|
||||||
* 色収差
|
* 色収差
|
||||||
|
|
|
@ -3237,6 +3237,7 @@ _watermarkEditor:
|
||||||
_imageEffector:
|
_imageEffector:
|
||||||
title: "エフェクト"
|
title: "エフェクト"
|
||||||
addEffect: "エフェクトを追加"
|
addEffect: "エフェクトを追加"
|
||||||
|
discardChangesConfirm: "変更を破棄して終了しますか?"
|
||||||
|
|
||||||
_fxs:
|
_fxs:
|
||||||
chromaticAberration: "色収差"
|
chromaticAberration: "色収差"
|
||||||
|
|
|
@ -61,7 +61,7 @@ import { deepClone } from '@/utility/clone.js';
|
||||||
import { FXS } from '@/utility/image-effector/fxs.js';
|
import { FXS } from '@/utility/image-effector/fxs.js';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
image: ImageBitmap;
|
image: File;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
@ -72,7 +72,14 @@ const emit = defineEmits<{
|
||||||
|
|
||||||
const dialog = useTemplateRef('dialog');
|
const dialog = useTemplateRef('dialog');
|
||||||
|
|
||||||
function cancel() {
|
async function cancel() {
|
||||||
|
if (layers.length > 0) {
|
||||||
|
const { canceled } = await os.confirm({
|
||||||
|
text: i18n.ts._imageEffector.discardChangesConfirm,
|
||||||
|
});
|
||||||
|
if (canceled) return;
|
||||||
|
}
|
||||||
|
|
||||||
emit('cancel');
|
emit('cancel');
|
||||||
dialog.value?.close();
|
dialog.value?.close();
|
||||||
}
|
}
|
||||||
|
@ -108,14 +115,19 @@ function onLayerDelete(layer: ImageEffectorLayer) {
|
||||||
const canvasEl = useTemplateRef('canvasEl');
|
const canvasEl = useTemplateRef('canvasEl');
|
||||||
|
|
||||||
let renderer: ImageEffector | null = null;
|
let renderer: ImageEffector | null = null;
|
||||||
|
let imageBitmap: ImageBitmap | null = null;
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
if (canvasEl.value == null) return;
|
if (canvasEl.value == null) return;
|
||||||
|
|
||||||
|
const closeWaiting = os.waiting();
|
||||||
|
|
||||||
|
imageBitmap = await window.createImageBitmap(props.image);
|
||||||
|
|
||||||
const MAX_W = 500;
|
const MAX_W = 500;
|
||||||
const MAX_H = 500;
|
const MAX_H = 500;
|
||||||
let w = props.image.width;
|
let w = imageBitmap.width;
|
||||||
let h = props.image.height;
|
let h = imageBitmap.height;
|
||||||
|
|
||||||
if (w > MAX_W || h > MAX_H) {
|
if (w > MAX_W || h > MAX_H) {
|
||||||
const scale = Math.min(MAX_W / w, MAX_H / h);
|
const scale = Math.min(MAX_W / w, MAX_H / h);
|
||||||
|
@ -127,13 +139,15 @@ onMounted(async () => {
|
||||||
canvas: canvasEl.value,
|
canvas: canvasEl.value,
|
||||||
renderWidth: w,
|
renderWidth: w,
|
||||||
renderHeight: h,
|
renderHeight: h,
|
||||||
image: props.image,
|
image: imageBitmap,
|
||||||
fxs: FXS,
|
fxs: FXS,
|
||||||
});
|
});
|
||||||
|
|
||||||
await renderer.setLayers(layers);
|
await renderer.setLayers(layers);
|
||||||
|
|
||||||
renderer.render();
|
renderer.render();
|
||||||
|
|
||||||
|
closeWaiting();
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
|
@ -141,19 +155,26 @@ onUnmounted(() => {
|
||||||
renderer.destroy();
|
renderer.destroy();
|
||||||
renderer = null;
|
renderer = null;
|
||||||
}
|
}
|
||||||
|
if (imageBitmap != null) {
|
||||||
|
imageBitmap.close();
|
||||||
|
imageBitmap = null;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
if (layers.length === 0) {
|
if (layers.length === 0 || renderer == null || imageBitmap == null || canvasEl.value == null) {
|
||||||
cancel();
|
cancel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer!.changeResolution(props.image.width, props.image.height); // 本番レンダリングのためオリジナル画質に戻す
|
const closeWaiting = os.waiting();
|
||||||
renderer!.render(); // toBlobの直前にレンダリングしないと何故か壊れる
|
|
||||||
canvasEl.value!.toBlob((blob) => {
|
renderer.changeResolution(imageBitmap.width, imageBitmap.height); // 本番レンダリングのためオリジナル画質に戻す
|
||||||
|
renderer.render(); // toBlobの直前にレンダリングしないと何故か壊れる
|
||||||
|
canvasEl.value.toBlob((blob) => {
|
||||||
emit('ok', new File([blob!], `image-${Date.now()}.png`, { type: 'image/png' }));
|
emit('ok', new File([blob!], `image-${Date.now()}.png`, { type: 'image/png' }));
|
||||||
dialog.value?.close();
|
dialog.value?.close();
|
||||||
|
closeWaiting();
|
||||||
}, 'image/png');
|
}, 'image/png');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -297,9 +297,8 @@ function showMenu(ev: MouseEvent, item: typeof items.value[0]) {
|
||||||
icon: 'ti ti-sparkles',
|
icon: 'ti ti-sparkles',
|
||||||
text: i18n.ts._imageEffector.title,
|
text: i18n.ts._imageEffector.title,
|
||||||
action: async () => {
|
action: async () => {
|
||||||
const imageBitmap = await window.createImageBitmap(item.file);
|
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkImageEffectorDialog.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkImageEffectorDialog.vue')), {
|
||||||
image: imageBitmap,
|
image: item.file,
|
||||||
}, {
|
}, {
|
||||||
ok: (file) => {
|
ok: (file) => {
|
||||||
URL.revokeObjectURL(item.thumbnail);
|
URL.revokeObjectURL(item.thumbnail);
|
||||||
|
@ -313,10 +312,7 @@ function showMenu(ev: MouseEvent, item: typeof items.value[0]) {
|
||||||
triggerRef(items);
|
triggerRef(items);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
closed: () => {
|
closed: () => dispose(),
|
||||||
imageBitmap.close();
|
|
||||||
dispose();
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -353,18 +349,14 @@ function showMenu(ev: MouseEvent, item: typeof items.value[0]) {
|
||||||
icon: 'ti ti-plus',
|
icon: 'ti ti-plus',
|
||||||
text: i18n.ts.add,
|
text: i18n.ts.add,
|
||||||
action: async () => {
|
action: async () => {
|
||||||
const imageBitmap = await window.createImageBitmap(item.file);
|
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkWatermarkEditorDialog.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkWatermarkEditorDialog.vue')), {
|
||||||
image: imageBitmap,
|
image: item.file,
|
||||||
}, {
|
}, {
|
||||||
ok: (preset) => {
|
ok: (preset) => {
|
||||||
prefer.commit('watermarkPresets', [...prefer.s.watermarkPresets, preset]);
|
prefer.commit('watermarkPresets', [...prefer.s.watermarkPresets, preset]);
|
||||||
changeWatermarkPreset(preset.id);
|
changeWatermarkPreset(preset.id);
|
||||||
},
|
},
|
||||||
closed: () => {
|
closed: () => dispose(),
|
||||||
imageBitmap.close();
|
|
||||||
dispose();
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}],
|
}],
|
||||||
|
|
|
@ -63,7 +63,7 @@ const $i = ensureSignin();
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
preset?: WatermarkPreset | null;
|
preset?: WatermarkPreset | null;
|
||||||
image?: ImageBitmap | null;
|
image?: File | null;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const preset = reactive(deepClone(props.preset) ?? {
|
const preset = reactive(deepClone(props.preset) ?? {
|
||||||
|
@ -149,6 +149,7 @@ watch(sampleImageType, async () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
let renderer: WatermarkRenderer | null = null;
|
let renderer: WatermarkRenderer | null = null;
|
||||||
|
let imageBitmap: ImageBitmap | null = null;
|
||||||
|
|
||||||
async function initRenderer() {
|
async function initRenderer() {
|
||||||
if (canvasEl.value == null) return;
|
if (canvasEl.value == null) return;
|
||||||
|
@ -168,10 +169,12 @@ async function initRenderer() {
|
||||||
image: sampleImage_2_3,
|
image: sampleImage_2_3,
|
||||||
});
|
});
|
||||||
} else if (props.image != null) {
|
} else if (props.image != null) {
|
||||||
|
imageBitmap = await window.createImageBitmap(props.image);
|
||||||
|
|
||||||
const MAX_W = 1000;
|
const MAX_W = 1000;
|
||||||
const MAX_H = 1000;
|
const MAX_H = 1000;
|
||||||
let w = props.image.width;
|
let w = imageBitmap.width;
|
||||||
let h = props.image.height;
|
let h = imageBitmap.height;
|
||||||
|
|
||||||
if (w > MAX_W || h > MAX_H) {
|
if (w > MAX_W || h > MAX_H) {
|
||||||
const scale = Math.min(MAX_W / w, MAX_H / h);
|
const scale = Math.min(MAX_W / w, MAX_H / h);
|
||||||
|
@ -183,7 +186,7 @@ async function initRenderer() {
|
||||||
canvas: canvasEl.value,
|
canvas: canvasEl.value,
|
||||||
renderWidth: w,
|
renderWidth: w,
|
||||||
renderHeight: h,
|
renderHeight: h,
|
||||||
image: props.image,
|
image: imageBitmap,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,10 +196,14 @@ async function initRenderer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
const closeWaiting = os.waiting();
|
||||||
|
|
||||||
await sampleImage_3_2_loading;
|
await sampleImage_3_2_loading;
|
||||||
await sampleImage_2_3_loading;
|
await sampleImage_2_3_loading;
|
||||||
|
|
||||||
initRenderer();
|
await initRenderer();
|
||||||
|
|
||||||
|
closeWaiting();
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
|
@ -204,6 +211,10 @@ onUnmounted(() => {
|
||||||
renderer.destroy();
|
renderer.destroy();
|
||||||
renderer = null;
|
renderer = null;
|
||||||
}
|
}
|
||||||
|
if (imageBitmap != null) {
|
||||||
|
imageBitmap.close();
|
||||||
|
imageBitmap = null;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
async function save() {
|
async function save() {
|
||||||
|
|
Loading…
Reference in New Issue