168 lines
3.6 KiB
Vue
168 lines
3.6 KiB
Vue
<template>
|
|
<div class="angle-tool" :disabled="disabled">
|
|
<template v-if="styleType === '1'">
|
|
<div
|
|
ref="dishRef"
|
|
class="dish"
|
|
@mousedown.stop="mousedown"
|
|
@touchmove.stop="mousedown"
|
|
>
|
|
<div
|
|
class="pointer"
|
|
:style="{ transform: `rotate(${angle}deg)` }"
|
|
>
|
|
<span></span>
|
|
</div>
|
|
</div>
|
|
<div class="input">
|
|
<input
|
|
type="number"
|
|
v-model="angle"
|
|
@input="onInput"
|
|
@change="onChange"
|
|
:disabled="disabled"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<my-input
|
|
v-if="styleType === '2'"
|
|
v-model="angle"
|
|
@input="onInput"
|
|
@change="onChange"
|
|
:disabled="disabled"
|
|
type="number"
|
|
after="°"
|
|
icon="icon-angle"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, defineProps, defineEmits, watch } from "vue";
|
|
import { calculateAngle } from "@/component/Canvas/CanvasEditor/utils/helper";
|
|
import MyInput from "./MyInput.vue";
|
|
// Props
|
|
const props = defineProps({
|
|
styleType: {
|
|
type: String,
|
|
default: "1",
|
|
},
|
|
angle: {
|
|
type: Number,
|
|
default: 0,
|
|
},
|
|
disabled: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
});
|
|
const emit = defineEmits(["change", "input"]);
|
|
const angle = ref(props.angle);
|
|
watch(
|
|
() => props.angle,
|
|
(value) => {
|
|
angle.value = value;
|
|
}
|
|
);
|
|
const dishRef = ref<HTMLDivElement>();
|
|
const mousedown = (e: MouseEvent | TouchEvent) => {
|
|
if (props.disabled) return;
|
|
const mousemove = (e: MouseEvent | TouchEvent) => {
|
|
if (!dishRef.value) return;
|
|
const { left, top, width, height } =
|
|
dishRef.value.getBoundingClientRect();
|
|
const centerX = left + width / 2;
|
|
const centerY = top + height / 2;
|
|
const { clientX, clientY } = e?.touches?.[0] || e;
|
|
angle.value = calculateAngle(centerX, centerY, clientX, clientY, true);
|
|
onInput();
|
|
};
|
|
mousemove(e);
|
|
const mouseup = () => {
|
|
onChange();
|
|
document.removeEventListener("mousemove", mousemove);
|
|
document.removeEventListener("touchmove", mousemove);
|
|
document.removeEventListener("mouseup", mouseup);
|
|
document.removeEventListener("touchend", mouseup);
|
|
};
|
|
document.addEventListener("mousemove", mousemove);
|
|
document.addEventListener("touchmove", mousemove);
|
|
document.addEventListener("mouseup", mouseup);
|
|
document.addEventListener("touchend", mouseup);
|
|
};
|
|
const onInput = () => !props.disabled && emit("input", angle.value);
|
|
var changeTime: any = null;
|
|
const onChange = () => {
|
|
if (props.disabled) return;
|
|
clearTimeout(changeTime);
|
|
changeTime = setTimeout(() => emit("change", angle.value), 500);
|
|
};
|
|
// var angleTime = null;
|
|
// watch(angle, (value) => {
|
|
// emit("input", value);
|
|
// clearTimeout(angleTime);
|
|
// angleTime = setTimeout(() => emit("change", value), 50);
|
|
// });
|
|
// defineExpose({
|
|
// open,
|
|
// close,
|
|
// });
|
|
</script>
|
|
|
|
<style scoped lang="less">
|
|
.angle-tool {
|
|
display: flex;
|
|
align-items: center;
|
|
width: 100%;
|
|
--color: #000;
|
|
&[disabled="true"] {
|
|
--color: #b2b2b2;
|
|
> .dish {
|
|
cursor: not-allowed;
|
|
}
|
|
}
|
|
> .dish {
|
|
width: 24px;
|
|
height: 24px;
|
|
border: 1px solid var(--color);
|
|
border-radius: 50%;
|
|
cursor: pointer;
|
|
> .pointer {
|
|
pointer-events: none;
|
|
user-select: none;
|
|
position: relative;
|
|
width: 100%;
|
|
height: 100%;
|
|
> span {
|
|
position: absolute;
|
|
top: 10%;
|
|
left: 50%;
|
|
transform: translate(-50%, 0);
|
|
width: 35%;
|
|
height: 35%;
|
|
background-color: var(--color);
|
|
border-radius: 50%;
|
|
}
|
|
}
|
|
}
|
|
> .input {
|
|
margin-left: 5px;
|
|
font-size: 14px;
|
|
color: var(--color);
|
|
flex: 1;
|
|
// min-width: 45px;
|
|
// max-width: 80px;
|
|
// width: 50px;
|
|
> input {
|
|
width: 100%;
|
|
border-radius: 3px;
|
|
outline: none;
|
|
}
|
|
}
|
|
> .my-input {
|
|
flex: 1;
|
|
}
|
|
}
|
|
</style>
|