116 lines
3.3 KiB
Vue
116 lines
3.3 KiB
Vue
<template>
|
|
<div @click="handleClick" style="position: relative; width: 100%; height: 100vh">
|
|
<!-- 画线 -->
|
|
<div v-if="state.measureDistancesPoints.length === 2" :style="rangingLineStyle"></div>
|
|
|
|
<!-- 显示距离信息 -->
|
|
<div v-if="state.measureDistancesNum !== null" :style="rangingTextStyle">
|
|
距离: {{ state.measureDistancesNum.toFixed(2) }} 像素
|
|
</div>
|
|
|
|
<!-- 显示点 -->
|
|
<div
|
|
v-for="(point, index) in state.measureDistancesPoints"
|
|
:key="index"
|
|
:style="getRangingPointStyle(point)"
|
|
></div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, computed } from 'vue'
|
|
|
|
const state = reactive({
|
|
measureDistancesPoints: [],
|
|
measureDistancesNum: null
|
|
})
|
|
|
|
// 处理点击事件
|
|
const handleClick = (event) => {
|
|
if (state.measureDistancesPoints.length === 2) {
|
|
// 如果已经有两个点,清空信息
|
|
state.measureDistancesPoints = []
|
|
state.measureDistancesNum = null
|
|
} else {
|
|
// 添加当前点击的点
|
|
state.measureDistancesPoints.push({ x: event.clientX, y: event.clientY })
|
|
|
|
// 当有两个点时,计算距离
|
|
if (state.measureDistancesPoints.length === 2) {
|
|
const [point1, point2] = state.measureDistancesPoints
|
|
state.measureDistancesNum = Math.sqrt(
|
|
Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2)
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 计算连线的样式
|
|
const rangingLineStyle = computed(() => {
|
|
if (state.measureDistancesPoints.length === 2) {
|
|
const [point1, point2] = state.measureDistancesPoints
|
|
const length = Math.sqrt(Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2))
|
|
const angle = (Math.atan2(point2.y - point1.y, point2.x - point1.x) * 180) / Math.PI
|
|
return {
|
|
position: 'absolute',
|
|
left: `${point1.x}px`,
|
|
top: `${point1.y}px`,
|
|
width: `${length}px`,
|
|
height: '2px',
|
|
backgroundColor: 'red',
|
|
transform: `rotate(${angle}deg)`,
|
|
transformOrigin: '0 0'
|
|
}
|
|
}
|
|
return {}
|
|
})
|
|
|
|
// 计算距离信息的样式(显示在连线中间,并根据角度调整文字方向)
|
|
const rangingTextStyle = computed(() => {
|
|
if (state.measureDistancesPoints.length === 2) {
|
|
const [point1, point2] = state.measureDistancesPoints
|
|
const midX = (point1.x + point2.x) / 2
|
|
const midY = (point1.y + point2.y) / 2
|
|
const angle = (Math.atan2(point2.y - point1.y, point2.x - point1.x) * 180) / Math.PI
|
|
|
|
// 调整文字方向,使其始终易于阅读
|
|
let textRotation = 0
|
|
if (angle > 90 || angle < -90) {
|
|
textRotation = angle + 180 // 翻转文字方向
|
|
} else {
|
|
textRotation = angle
|
|
}
|
|
|
|
return {
|
|
position: 'absolute',
|
|
left: `${midX}px`,
|
|
top: `${midY}px`,
|
|
transform: `translate(-50%, -50%) rotate(${textRotation}deg)`,
|
|
backgroundColor: 'rgba(255, 255, 255, 0.8)',
|
|
padding: '4px 8px',
|
|
borderRadius: '4px',
|
|
fontSize: '14px',
|
|
color: 'black',
|
|
whiteSpace: 'nowrap', // 防止文字换行
|
|
pointerEvents: 'none' // 防止文字遮挡点击事件
|
|
}
|
|
}
|
|
return {}
|
|
})
|
|
|
|
// 计算点的样式
|
|
const getRangingPointStyle = (point) => ({
|
|
position: 'absolute',
|
|
left: `${point.x - 5}px`,
|
|
top: `${point.y - 5}px`,
|
|
width: '10px',
|
|
height: '10px',
|
|
backgroundColor: 'blue',
|
|
borderRadius: '50%'
|
|
})
|
|
</script>
|
|
|
|
<style>
|
|
/* 你可以在这里添加一些样式 */
|
|
</style>
|