<template>
    <div>
        <div class="out_circle" ref="outCircleRef" :style="{ width: r * 2 + 'px', height: r * 2 + 'px' }">
            <div class="inner_circle" ref="innerCircleRef" :style="{ width: inR * 2 + 'px', height: inR * 2 + 'px' }">
                Press
            </div>
        </div>
    </div>
</template>
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'

const { r } = withDefaults(defineProps<{
    r: number,
    inR: number
}>(), {
    r: 100,
    inR: 30
})

let outCircleRef = ref<HTMLElement>()
let innerCircleRef = ref<HTMLElement>()
let mouseAngle = ref<number>(0)
let mouseAngleComp = computed(() => {
    return mouseAngle.value.toFixed(2) + '°'
})

defineExpose({ mouseAngleComp })

function mouseDown(e: MouseEvent) {
    document.body.addEventListener('mousemove', mouseMove)
}

function mouseMove(e: MouseEvent) {
    if (outCircleRef.value && innerCircleRef.value) {
        let centerX = outCircleRef.value.offsetLeft + r
        let centerY = outCircleRef.value.offsetTop + r
        let disToCenter = distance(centerX, centerY, e.clientX, e.clientY)
        let ratioX = 0
        let ratioY = 0
        if (disToCenter <= r) {
            ratioX = (e.clientX - outCircleRef.value.offsetLeft) / (r * 2) * 100
            ratioY = (e.clientY - outCircleRef.value.offsetTop) / (r * 2) * 100
        } else {
            let copyX = e.clientX
            let copyY = e.clientY
            while (disToCenter > r) {
                copyX += copyX > centerX ? -2 : 2
                copyY += copyY > centerY ? -2 : 2
                disToCenter = distance(centerX, centerY, copyX, copyY)
            }
            ratioX = (copyX - outCircleRef.value.offsetLeft) / (r * 2) * 100
            ratioY = (copyY - outCircleRef.value.offsetTop) / (r * 2) * 100
        }
        innerCircleRef.value.style.left = ratioX + '%'
        innerCircleRef.value.style.top = ratioY + '%'
        mouseAngle.value = (Math.atan2(ratioX, ratioY) * 180) % 360
    }
}

function mouseUp(e: MouseEvent) {
    document.body.removeEventListener('mousemove', mouseMove)
    innerCircleRef.value!.style.left = '50%'
    innerCircleRef.value!.style.top = '50%'
    mouseAngle.value = 0
}

function distance(x0: number, y0: number, x1: number, y1: number) {
    return Math.sqrt((x1 - x0) ** 2 + (y1 - y0) ** 2)
}

onMounted(() => {
    innerCircleRef.value?.addEventListener('mousedown', mouseDown)
    document.body.addEventListener('mouseup', mouseUp)
})

</script>
<style scoped>
.out_circle {
    border-radius: 50%;
    background-color: #ddd;
    position: relative;
    margin-top: 8px;

    .inner_circle {
        border-radius: 50%;
        background-color: #999;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        cursor: pointer;
        display: flex;
        justify-content: center;
        align-items: center;
        font-weight: bold;
        user-select: none;

        &:active {
            background: #666;
        }
    }
}
</style>