とりあえず出るようにした

This commit is contained in:
kakkokari-gtyih 2024-12-16 11:19:20 +09:00
parent 47ef78afe4
commit 8f3241a6ae
2 changed files with 48 additions and 20 deletions

View file

@ -20,7 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div :class="$style.watermarkEditorInputRoot"> <div :class="$style.watermarkEditorInputRoot">
<div :class="$style.watermarkEditorPreviewRoot"> <div :class="$style.watermarkEditorPreviewRoot">
<MkLoading v-if="canvasLoading" :class="$style.watermarkEditorPreviewSpinner"/> <MkLoading v-if="canvasLoading" :class="$style.watermarkEditorPreviewSpinner"/>
<canvas ref="canvas" :class="$style.watermarkEditorPreviewCanvas"></canvas> <canvas ref="canvasEl" :class="$style.watermarkEditorPreviewCanvas"></canvas>
<div :class="$style.watermarkEditorPreviewWrapper"> <div :class="$style.watermarkEditorPreviewWrapper">
<div class="_acrylic" :class="$style.watermarkEditorPreviewTitle">{{ i18n.ts.preview }}</div> <div class="_acrylic" :class="$style.watermarkEditorPreviewTitle">{{ i18n.ts.preview }}</div>
</div> </div>
@ -37,12 +37,13 @@ SPDX-License-Identifier: AGPL-3.0-only
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { shallowRef, ref, computed } from 'vue'; import { shallowRef, ref, useTemplateRef, computed, onMounted } from 'vue';
import MkModalWindow from '@/components/MkModalWindow.vue'; import MkModalWindow from '@/components/MkModalWindow.vue';
import MkSwitch from '@/components/MkSwitch.vue'; import MkSwitch from '@/components/MkSwitch.vue';
import { defaultStore } from '@/store.js'; import { defaultStore } from '@/store.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { applyWatermark, WatermarkConfig } from '@/scripts/watermark.js';
const emit = defineEmits<{ const emit = defineEmits<{
(ev: 'ok'): void; (ev: 'ok'): void;
@ -66,11 +67,25 @@ function save() {
//#region //#region
const useWatermark = computed(defaultStore.makeGetterSetter('useWatermark')); const useWatermark = computed(defaultStore.makeGetterSetter('useWatermark'));
const watermarkConfig = ref(defaultStore.state.watermarkConfig); const watermarkConfig = ref<WatermarkConfig>(defaultStore.state.watermarkConfig ?? {
fileUrl: '/client-assets/default-watermark.png',
enlargement: 'contain',
opacity: 0.5,
anchor: 'bottom-right',
gravity: 'auto',
repeat: false,
__bypassMediaProxy: true,
});
//#endregion //#endregion
//#region Canvas //#region Canvas
const canvasLoading = ref(true); const canvasLoading = ref(true);
const canvasEl = useTemplateRef('canvasEl');
onMounted(() => {
if (canvasEl.value) {
applyWatermark('/client-assets/hill.webp', canvasEl.value, watermarkConfig.value);
}
});
//#endregion //#endregion
</script> </script>

View file

@ -3,37 +3,41 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { getProxiedImageUrl } from "@/scripts/media-proxy.js"; import { getProxiedImageUrl } from "@/scripts/media-proxy.js";
import { misskeyApi } from "@/scripts/misskey-api.js";
export type WatermarkConfig = { export type WatermarkConfig = {
fileId: string | null; fileId?: string;
fileUrl: string | null; fileUrl?: string;
width: number | null; width?: number;
height: number | null; height?: number;
enlargement: 'scale-down' | 'contain' | 'cover' | 'crop' | 'pad'; enlargement: 'scale-down' | 'contain' | 'cover' | 'crop' | 'pad';
gravity: 'auto' | 'left' | 'right' | 'top' | 'bottom'; gravity: 'auto' | 'left' | 'right' | 'top' | 'bottom';
opacity: number; opacity?: number;
repeat: true | false | 'x' | 'y'; repeat: true | false | 'x' | 'y';
anchor: 'center' | 'top' | 'left' | 'bottom' | 'right' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'; anchor: 'center' | 'top' | 'left' | 'bottom' | 'right' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
offsetTop: number | null; offsetTop?: number;
offsetLeft: number | null; offsetLeft?: number;
offsetBottom: number | null; offsetBottom?: number;
offsetRight: number | null; offsetRight?: number;
backgroundColor: string | null; backgroundColor?: string;
rotate: number | null; rotate?: number;
/** @internal */
__bypassMediaProxy?: boolean;
}; };
/** /**
* *
* *
* @param img stringは画像URL**** * @param img stringは画像URL
* @param el * @param el
* @param config * @param config
*/ */
export function applyWatermark(img: string | Blob, el: HTMLCanvasElement, config: WatermarkConfig) { export async function applyWatermark(img: string | Blob, el: HTMLCanvasElement, config: WatermarkConfig) {
const canvas = el; const canvas = el;
const ctx = canvas.getContext('2d')!; const ctx = canvas.getContext('2d')!;
const imgEl = new Image(); const imgEl = new Image();
imgEl.onload = () => { imgEl.onload = async () => {
canvas.width = imgEl.width; canvas.width = imgEl.width;
canvas.height = imgEl.height; canvas.height = imgEl.height;
ctx.drawImage(imgEl, 0, 0); ctx.drawImage(imgEl, 0, 0);
@ -42,7 +46,7 @@ export function applyWatermark(img: string | Blob, el: HTMLCanvasElement, config
watermark.onload = () => { watermark.onload = () => {
const width = config.width || watermark.width; const width = config.width || watermark.width;
const height = config.height || watermark.height; const height = config.height || watermark.height;
ctx.globalAlpha = config.opacity; ctx.globalAlpha = config.opacity ?? 1;
if (config.repeat !== false) { if (config.repeat !== false) {
const resizedWatermark = document.createElement('canvas'); const resizedWatermark = document.createElement('canvas');
resizedWatermark.width = width; resizedWatermark.width = width;
@ -90,11 +94,20 @@ export function applyWatermark(img: string | Blob, el: HTMLCanvasElement, config
ctx.drawImage(watermark, x, y, width, height); ctx.drawImage(watermark, x, y, width, height);
} }
}; };
watermark.src = config.fileUrl;
let watermarkUrl: string;
if (config.fileUrl == null && config.fileId != null) {
const res = await misskeyApi('drive/files/show', { fileId: config.fileId });
watermarkUrl = res.url;
} else {
watermarkUrl = config.fileUrl!;
}
watermark.src = config.__bypassMediaProxy ? config.fileUrl : getProxiedImageUrl(watermarkUrl, undefined, true);
} }
}; };
if (typeof img === 'string') { if (typeof img === 'string') {
imgEl.src = getProxiedImageUrl(img, undefined, true); imgEl.src = img;
} else { } else {
const reader = new FileReader(); const reader = new FileReader();
reader.onload = () => { reader.onload = () => {