feat: allow to add and remove effects
This commit is contained in:
parent
0285ab366a
commit
6b56e11119
4 changed files with 74 additions and 20 deletions
|
|
@ -2,4 +2,4 @@
|
|||
|
||||
Application for manipulating images (crop, resize, adujst brightness, ...).
|
||||
|
||||

|
||||

|
||||
|
|
|
|||
BIN
docs/app.png
Normal file
BIN
docs/app.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.6 MiB |
|
|
@ -10,6 +10,8 @@ const type = ref(null)
|
|||
const result = ref(null)
|
||||
const effects = ref([])
|
||||
const resultLoading = ref(false)
|
||||
const availableEffects = ref([])
|
||||
const effectToAdd = ref(null)
|
||||
|
||||
const makeSetting = (label, value, min, max, step) => {
|
||||
return {label, value, min, max, step}
|
||||
|
|
@ -25,7 +27,7 @@ const openImageFile = () => {
|
|||
|
||||
source.value = info
|
||||
|
||||
effects.value = [
|
||||
availableEffects.value = [
|
||||
{
|
||||
label: "Crop",
|
||||
name: "crop",
|
||||
|
|
@ -154,6 +156,29 @@ const applyEffects = () => {
|
|||
})
|
||||
}
|
||||
|
||||
function makeId() {
|
||||
let result = '';
|
||||
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
const charactersLength = characters.length;
|
||||
|
||||
for ( var i = 0; i < 20; i++ ) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
const addEffect = () => {
|
||||
if (!effectToAdd.value) {
|
||||
return
|
||||
}
|
||||
|
||||
let effect = JSON.parse(JSON.stringify(availableEffects.value.filter((e) => e.name === effectToAdd.value)[0]))
|
||||
effect.id = makeId()
|
||||
effects.value.push(effect)
|
||||
}
|
||||
|
||||
const makeRenderStyle = () => {
|
||||
return {
|
||||
'align-items': source.value !== null ? 'top' : 'center'
|
||||
|
|
@ -164,6 +189,10 @@ const makeImageSrc = (data) => {
|
|||
return `data:image/${data.type};base64, ${data.base64}`
|
||||
}
|
||||
|
||||
const deleteEffect = (index) => {
|
||||
effects.value.splice(index, 1)
|
||||
}
|
||||
|
||||
onMounted(openImageFile)
|
||||
</script>
|
||||
|
||||
|
|
@ -176,20 +205,25 @@ onMounted(openImageFile)
|
|||
:options="{handle: '.effect-move', animation: 400}"
|
||||
v-model="effects"
|
||||
@end="sortEnd"
|
||||
item-key="name"
|
||||
item-key="id"
|
||||
tag="div"
|
||||
>
|
||||
<template #item="{element, index}">
|
||||
<div class="effect" :key="index">
|
||||
<div class="effect-move">
|
||||
↕
|
||||
<div class="effect">
|
||||
<div class="effect-actions">
|
||||
<div class="effect-move">
|
||||
↕
|
||||
</div>
|
||||
<div class="effect-delete" @click="deleteEffect(index)">
|
||||
🗑️
|
||||
</div>
|
||||
</div>
|
||||
<div class="effect-name" @click="element.enabled = !element.enabled">
|
||||
<VueToggles :value="element.enabled" :width="40" />
|
||||
{{ element.label }}
|
||||
</div>
|
||||
<div class="effect-settings" v-if="element.enabled">
|
||||
<div v-for="setting in element.settings" :key="setting.name" class="effect-setting">
|
||||
<div v-for="setting, key in element.settings" :key="element.id + key" class="effect-setting">
|
||||
<input
|
||||
type="range"
|
||||
:min="setting.min"
|
||||
|
|
@ -210,7 +244,20 @@ onMounted(openImageFile)
|
|||
</template>
|
||||
</Sortable>
|
||||
<div class="text-center">
|
||||
<button @click="applyEffects" :disabled="resultLoading">
|
||||
<div>
|
||||
<select v-model="effectToAdd">
|
||||
<option
|
||||
v-for="effect in availableEffects"
|
||||
:key="effect.name"
|
||||
:value="effect.name">
|
||||
{{ effect.label }}
|
||||
</option>
|
||||
</select>
|
||||
<button @click="addEffect">
|
||||
Add
|
||||
</button>
|
||||
</div>
|
||||
<button @click="applyEffects" :disabled="resultLoading" v-if="effects.length > 0">
|
||||
<template v-if="resultLoading">
|
||||
Loading...
|
||||
</template>
|
||||
|
|
@ -315,23 +362,30 @@ onMounted(openImageFile)
|
|||
text-align: left;
|
||||
border-bottom: 1px solid #999;
|
||||
|
||||
&-move {
|
||||
cursor: pointer;
|
||||
&-actions {
|
||||
float: right;
|
||||
display: inline-block;
|
||||
background: #ffffff33;
|
||||
padding: 3px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
line-height: 20px;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: #ffffff99;
|
||||
> div {
|
||||
display: inline-block;
|
||||
padding: 3px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
line-height: 20px;
|
||||
border-radius: 2px;
|
||||
margin-left: 8px;
|
||||
|
||||
&:hover {
|
||||
background: #ffffff99;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-move {
|
||||
background: #ffffff33;
|
||||
}
|
||||
|
||||
&-name {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue