|
@@ -1,35 +1,50 @@
|
|
|
<template>
|
|
|
<div class="bezier-editor">
|
|
|
- <svg
|
|
|
- ref="svg"
|
|
|
- class="editor"
|
|
|
- viewBox="0 0 1 1"
|
|
|
- preserveAspectRatio="none"
|
|
|
- @mousedown="onSvgMouseDown"
|
|
|
- >
|
|
|
-
|
|
|
- <line x1="0" y1="1" x2="1" y2="0" stroke="#88888893" stroke-width="0.01" />
|
|
|
-
|
|
|
- <line :x1="0" :y1="1" :x2="p1.x" :y2="p1.y" stroke="#4583FF" stroke-dasharray="2,2" stroke-width="0.015" />
|
|
|
- <line :x1="p2.x" :y1="p2.y" :x2="1" :y2="0" stroke="#4583FF" stroke-dasharray="2,2" stroke-width="0.015" />
|
|
|
-
|
|
|
- <path :d="curvePath" fill="none" stroke="#E3E8F4" stroke-width="0.02" />
|
|
|
-
|
|
|
- <circle
|
|
|
- class="point"
|
|
|
- r="0.03"
|
|
|
- :cx="p1.x"
|
|
|
- :cy="p1.y"
|
|
|
- @mousedown.prevent="startDrag('p1')"
|
|
|
- />
|
|
|
- <circle
|
|
|
- class="point"
|
|
|
- r="0.03"
|
|
|
- :cx="p2.x"
|
|
|
- :cy="p2.y"
|
|
|
- @mousedown.prevent="startDrag('p2')"
|
|
|
- />
|
|
|
- </svg>
|
|
|
+
|
|
|
+ <div class="main">
|
|
|
+ <svg
|
|
|
+ ref="svg"
|
|
|
+ class="editor"
|
|
|
+ viewBox="0 0 1 1"
|
|
|
+ preserveAspectRatio="none"
|
|
|
+ @mousedown="onSvgMouseDown"
|
|
|
+ >
|
|
|
+
|
|
|
+ <line x1="0" y1="1" x2="1" y2="0" stroke="#88888893" stroke-width="0.01" />
|
|
|
+
|
|
|
+ <line :x1="0" :y1="1" :x2="p1.x" :y2="p1.y" stroke="#4583FF" stroke-dasharray="2,2" stroke-width="0.015" />
|
|
|
+ <line :x1="p2.x" :y1="p2.y" :x2="1" :y2="0" stroke="#4583FF" stroke-dasharray="2,2" stroke-width="0.015" />
|
|
|
+
|
|
|
+ <path :d="curvePath" fill="none" stroke="#E3E8F4" stroke-width="0.02" />
|
|
|
+
|
|
|
+ <circle
|
|
|
+ class="point"
|
|
|
+ r="0.03"
|
|
|
+ :cx="p1.x"
|
|
|
+ :cy="p1.y"
|
|
|
+ @mousedown.prevent="startDrag('p1')"
|
|
|
+ />
|
|
|
+ <circle
|
|
|
+ class="point"
|
|
|
+ r="0.03"
|
|
|
+ :cx="p2.x"
|
|
|
+ :cy="p2.y"
|
|
|
+ @mousedown.prevent="startDrag('p2')"
|
|
|
+ />
|
|
|
+ </svg>
|
|
|
+
|
|
|
+ <div class="preset">
|
|
|
+ <div v-for="(item, index) in preset" :key="index" class="presetItem" @click="onPresetClick(item)">
|
|
|
+ <svg
|
|
|
+ :class="{presetItemSvg:true,active:modelValue===item}"
|
|
|
+ viewBox="0 0 1 1"
|
|
|
+ preserveAspectRatio="none"
|
|
|
+ >
|
|
|
+ <path :d="'M 0 1 C ' + parsePresetStr(item)+ ',1 0'" fill="none" stroke="#E3E8F4" stroke-width="0.04" />
|
|
|
+ </svg>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
|
|
|
<div class="controls">
|
|
|
<div class="label">{{ modelValue }}</div>
|
|
@@ -67,6 +82,12 @@ function formatVal() {
|
|
|
return `${x1},${y1},${x2},${y2}`
|
|
|
}
|
|
|
|
|
|
+function onPresetClick(item) {
|
|
|
+ parseRaw(item)
|
|
|
+ emit('update:modelValue', formatVal())
|
|
|
+ emit('change', formatVal())
|
|
|
+}
|
|
|
+
|
|
|
const parseRaw = (str) => {
|
|
|
if(!str) return
|
|
|
const nums = str.split(',').map(Number)
|
|
@@ -84,6 +105,13 @@ const curvePath = computed(() => {
|
|
|
return `M 0 1 C ${p1.value.x} ${p1.value.y}, ${p2.value.x} ${p2.value.y}, 1 0`
|
|
|
})
|
|
|
|
|
|
+function parsePresetStr(str) {
|
|
|
+ if(!str) return
|
|
|
+ const nums = str.split(',').map(Number)
|
|
|
+ if (nums.length === 4 && nums.every(n => !isNaN(n))) {
|
|
|
+ return `${nums[0]} ${1 - nums[1]}, ${nums[2]} ${1 - nums[3]}`
|
|
|
+ }
|
|
|
+}
|
|
|
function startDrag(name) {
|
|
|
dragging.value = name
|
|
|
}
|
|
@@ -161,11 +189,15 @@ onBeforeUnmount(() => {
|
|
|
align-items: center;
|
|
|
user-select: none;
|
|
|
}
|
|
|
-.editor {
|
|
|
+.main {
|
|
|
width: 100%;
|
|
|
aspect-ratio:1;
|
|
|
border: 1px solid #303746;
|
|
|
background: #303746;
|
|
|
+ border-radius: 4px;
|
|
|
+}
|
|
|
+.editor {
|
|
|
+ padding: 20px;
|
|
|
}
|
|
|
.point {
|
|
|
fill: #4583FF;
|
|
@@ -181,4 +213,28 @@ onBeforeUnmount(() => {
|
|
|
justify-content: space-between;
|
|
|
align-items: center;
|
|
|
}
|
|
|
+.preset{
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-around;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 5px;
|
|
|
+}
|
|
|
+
|
|
|
+.presetItem{
|
|
|
+ width: 34px;
|
|
|
+ height: 34px;
|
|
|
+ background-color: #1e2430;
|
|
|
+ border-radius: 4px;
|
|
|
+}
|
|
|
+.presetItem:hover{
|
|
|
+ cursor: pointer;
|
|
|
+}
|
|
|
+
|
|
|
+.presetItemSvg{
|
|
|
+ padding: 4px;
|
|
|
+}
|
|
|
+.active{
|
|
|
+ background-color: #262D3A;
|
|
|
+}
|
|
|
</style>
|