wip
This commit is contained in:
parent
368b98bbfd
commit
7bff6cccb7
|
@ -12105,6 +12105,10 @@ export interface Locale extends ILocale {
|
|||
* 点グリッド
|
||||
*/
|
||||
"dottedGrid": string;
|
||||
/**
|
||||
* チェッカー
|
||||
*/
|
||||
"checker": string;
|
||||
};
|
||||
"_imageEffector": {
|
||||
/**
|
||||
|
|
|
@ -3241,6 +3241,7 @@ _watermarkEditor:
|
|||
stripeFrequency: "ラインの数"
|
||||
angle: "角度"
|
||||
dottedGrid: "点グリッド"
|
||||
checker: "チェッカー"
|
||||
|
||||
_imageEffector:
|
||||
title: "エフェクト"
|
||||
|
|
|
@ -54,6 +54,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template #label>{{ i18n.ts._watermarkEditor.repeat }}</template>
|
||||
</MkSwitch>
|
||||
</template>
|
||||
|
||||
<template v-else-if="layer.type === 'image'">
|
||||
<MkButton inline rounded primary @click="chooseFile">{{ i18n.ts.selectFile }}</MkButton>
|
||||
|
||||
|
@ -105,6 +106,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template #label>{{ i18n.ts._watermarkEditor.cover }}</template>
|
||||
</MkSwitch>
|
||||
</template>
|
||||
|
||||
<template v-else-if="layer.type === 'stripe'">
|
||||
<MkRange
|
||||
v-model="layer.frequency"
|
||||
|
@ -147,12 +149,109 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template #label>{{ i18n.ts._watermarkEditor.opacity }}</template>
|
||||
</MkRange>
|
||||
</template>
|
||||
|
||||
<template v-else-if="layer.type === 'dottedGrid'">
|
||||
<MkRange
|
||||
v-model="layer.angle"
|
||||
:min="-1"
|
||||
:max="1"
|
||||
:step="0.01"
|
||||
continuousUpdate
|
||||
>
|
||||
<template #label>{{ i18n.ts._watermarkEditor.angle }}</template>
|
||||
</MkRange>
|
||||
|
||||
<MkRange
|
||||
v-model="layer.scale"
|
||||
:min="0"
|
||||
:max="10"
|
||||
:step="0.01"
|
||||
continuousUpdate
|
||||
>
|
||||
<template #label>{{ i18n.ts._watermarkEditor.scale }}</template>
|
||||
</MkRange>
|
||||
|
||||
<MkRange
|
||||
v-model="layer.minorRadius"
|
||||
:min="0"
|
||||
:max="1"
|
||||
:step="0.01"
|
||||
:textConverter="(v) => (v * 100).toFixed(1) + '%'"
|
||||
continuousUpdate
|
||||
>
|
||||
<template #label>{{ i18n.ts._watermarkEditor.gridMinorRadius }}</template>
|
||||
</MkRange>
|
||||
|
||||
<MkRange
|
||||
v-model="layer.minorDivisions"
|
||||
:min="0"
|
||||
:max="16"
|
||||
:step="1"
|
||||
continuousUpdate
|
||||
>
|
||||
<template #label>{{ i18n.ts._watermarkEditor.gridMinorDivisions }}</template>
|
||||
</MkRange>
|
||||
|
||||
<MkRange
|
||||
v-model="layer.majorOpacity"
|
||||
:min="0"
|
||||
:max="1"
|
||||
:step="0.01"
|
||||
:textConverter="(v) => (v * 100).toFixed(1) + '%'"
|
||||
continuousUpdate
|
||||
>
|
||||
<template #label>{{ i18n.ts._watermarkEditor.gridMajorOpacity }}</template>
|
||||
</MkRange>
|
||||
|
||||
<MkRange
|
||||
v-model="layer.minorOpacity"
|
||||
:min="0"
|
||||
:max="1"
|
||||
:step="0.01"
|
||||
:textConverter="(v) => (v * 100).toFixed(1) + '%'"
|
||||
continuousUpdate
|
||||
>
|
||||
<template #label>{{ i18n.ts._watermarkEditor.gridMinorOpacity }}</template>
|
||||
</MkRange>
|
||||
</template>
|
||||
|
||||
<template v-else-if="layer.type === 'checker'">
|
||||
<MkRange
|
||||
v-model="layer.angle"
|
||||
:min="-1"
|
||||
:max="1"
|
||||
:step="0.01"
|
||||
continuousUpdate
|
||||
>
|
||||
<template #label>{{ i18n.ts._watermarkEditor.angle }}</template>
|
||||
</MkRange>
|
||||
|
||||
<MkRange
|
||||
v-model="layer.scale"
|
||||
:min="0"
|
||||
:max="10"
|
||||
:step="0.01"
|
||||
continuousUpdate
|
||||
>
|
||||
<template #label>{{ i18n.ts._watermarkEditor.scale }}</template>
|
||||
</MkRange>
|
||||
|
||||
<MkRange
|
||||
v-model="layer.opacity"
|
||||
:min="0"
|
||||
:max="1"
|
||||
:step="0.01"
|
||||
:textConverter="(v) => (v * 100).toFixed(1) + '%'"
|
||||
continuousUpdate
|
||||
>
|
||||
<template #label>{{ i18n.ts._watermarkEditor.opacity }}</template>
|
||||
</MkRange>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, useTemplateRef, watch, onMounted, onUnmounted } from 'vue';
|
||||
import type { ImageEffectorLayer } from '@/utility/image-effector/ImageEffector.js';
|
||||
import type { WatermarkPreset } from '@/utility/watermark.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import MkSelect from '@/components/MkSelect.vue';
|
||||
|
|
|
@ -47,6 +47,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<div v-if="layer.type === 'text'">{{ i18n.ts._watermarkEditor.text }}</div>
|
||||
<div v-if="layer.type === 'image'">{{ i18n.ts._watermarkEditor.image }}</div>
|
||||
<div v-if="layer.type === 'stripe'">{{ i18n.ts._watermarkEditor.stripe }}</div>
|
||||
<div v-if="layer.type === 'dottedGrid'">{{ i18n.ts._watermarkEditor.dottedGrid }}</div>
|
||||
<div v-if="layer.type === 'checker'">{{ i18n.ts._watermarkEditor.checker }}</div>
|
||||
</template>
|
||||
<template #footer>
|
||||
<div class="_buttons">
|
||||
|
@ -127,6 +129,33 @@ function createStripeLayer(): WatermarkPreset['layers'][number] {
|
|||
};
|
||||
}
|
||||
|
||||
function createDottedGridLayer(): WatermarkPreset['layers'][number] {
|
||||
return {
|
||||
id: genId(),
|
||||
type: 'dottedGrid',
|
||||
angle: 0.5,
|
||||
scale: 3,
|
||||
majorRadius: 0.1,
|
||||
minorRadius: 0.25,
|
||||
majorOpacity: 0.75,
|
||||
minorOpacity: 0.5,
|
||||
minorDivisions: 4,
|
||||
black: false,
|
||||
opacity: 0.75,
|
||||
};
|
||||
}
|
||||
|
||||
function createCheckerLayer(): WatermarkPreset['layers'][number] {
|
||||
return {
|
||||
id: genId(),
|
||||
type: 'checker',
|
||||
angle: 0.5,
|
||||
scale: 3,
|
||||
black: false,
|
||||
opacity: 0.75,
|
||||
};
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
preset?: WatermarkPreset | null;
|
||||
image?: File | null;
|
||||
|
@ -301,6 +330,16 @@ function addLayer(ev: MouseEvent) {
|
|||
action: () => {
|
||||
preset.layers.push(createStripeLayer());
|
||||
},
|
||||
}, {
|
||||
text: i18n.ts._watermarkEditor.dottedGrid,
|
||||
action: () => {
|
||||
preset.layers.push(createDottedGridLayer());
|
||||
},
|
||||
}, {
|
||||
text: i18n.ts._watermarkEditor.checker,
|
||||
action: () => {
|
||||
preset.layers.push(createCheckerLayer());
|
||||
},
|
||||
}], ev.currentTarget ?? ev.target);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
import { FX_watermarkPlacement } from './image-effector/fxs/watermarkPlacement.js';
|
||||
import { FX_stripe } from './image-effector/fxs/stripe.js';
|
||||
import { FX_dottedGrid } from './image-effector/fxs/dottedGrid.js';
|
||||
import { FX_checker } from './image-effector/fxs/checker.js';
|
||||
import type { ImageEffectorLayer } from '@/utility/image-effector/ImageEffector.js';
|
||||
import { ImageEffector } from '@/utility/image-effector/ImageEffector.js';
|
||||
|
||||
|
@ -39,6 +41,25 @@ export type WatermarkPreset = {
|
|||
threshold: number;
|
||||
black: boolean;
|
||||
opacity: number;
|
||||
} | {
|
||||
id: string;
|
||||
type: 'dottedGrid';
|
||||
angle: number;
|
||||
scale: number;
|
||||
majorRadius: number;
|
||||
majorOpacity: number;
|
||||
minorDivisions: number;
|
||||
minorRadius: number;
|
||||
minorOpacity: number;
|
||||
black: boolean;
|
||||
opacity: number;
|
||||
} | {
|
||||
id: string;
|
||||
type: 'checker';
|
||||
angle: number;
|
||||
scale: number;
|
||||
black: boolean;
|
||||
opacity: number;
|
||||
})[];
|
||||
};
|
||||
|
||||
|
@ -57,7 +78,7 @@ export class WatermarkRenderer {
|
|||
renderWidth: options.renderWidth,
|
||||
renderHeight: options.renderHeight,
|
||||
image: options.image,
|
||||
fxs: [FX_watermarkPlacement, FX_stripe],
|
||||
fxs: [FX_watermarkPlacement, FX_stripe, FX_dottedGrid, FX_checker],
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -109,6 +130,33 @@ export class WatermarkRenderer {
|
|||
opacity: layer.opacity,
|
||||
},
|
||||
};
|
||||
} else if (layer.type === 'dottedGrid') {
|
||||
return {
|
||||
fxId: 'dottedGrid',
|
||||
id: layer.id,
|
||||
params: {
|
||||
angle: layer.angle,
|
||||
scale: layer.scale,
|
||||
majorRadius: layer.majorRadius,
|
||||
majorOpacity: layer.majorOpacity,
|
||||
minorDivisions: layer.minorDivisions,
|
||||
minorRadius: layer.minorRadius,
|
||||
minorOpacity: layer.minorOpacity,
|
||||
black: layer.black,
|
||||
opacity: layer.opacity,
|
||||
},
|
||||
};
|
||||
} else if (layer.type === 'checker') {
|
||||
return {
|
||||
fxId: 'checker',
|
||||
id: layer.id,
|
||||
params: {
|
||||
angle: layer.angle,
|
||||
scale: layer.scale,
|
||||
black: layer.black,
|
||||
opacity: layer.opacity,
|
||||
},
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue