<!-- Description: 设备管理 - 区域绘制(电子围栏) Author: 李亚光 Date: 2024-11-01 --> <script lang="ts" setup name="DrawArea"> const $props = defineProps({ disabled: { type: Boolean, default: true }, width: { type: Number, default: 426.4 }, height: { type: Number, default: 240 } }) const points = ref([ { x: 30, y: 30 }, { x: 395, y: 30 }, { x: 395, y: 210 }, { x: 30, y: 210 }, ]) const elementId = ref(`${new Date().getTime()}`) const setSize = () => { const container = document.getElementById(`${elementId.value}-container`) as HTMLElement container.style.width = `${$props.width}px` container.style.height = `${$props.height}px` const canvas = document.getElementById(`${elementId.value}-canvas`) as HTMLCanvasElement canvas.width = $props.width canvas.height = $props.height } const initDraw = () => { const canvas = document.getElementById(`${elementId.value}-canvas`) const container = document.getElementById(`${elementId.value}-container`) const ctx = canvas.getContext('2d') // console.log(canvas, points.value, 'canvas') ctx.clearRect(0, 0, container.clientWidth, container.clientHeight) // 初始位置 function draw() { if (points.value.length !== 4) { return } ctx.clearRect(0, 0, canvas.width, canvas.height) ctx.beginPath() ctx.moveTo(points.value[0].x, points.value[0].y) ctx.lineTo(points.value[1].x, points.value[1].y) ctx.lineTo(points.value[2].x, points.value[2].y) ctx.lineTo(points.value[3].x, points.value[3].y) ctx.closePath() ctx.strokeStyle = 'red' ctx.lineWidth = 1 ctx.stroke() } function drag(e, pointIndex) { if ($props.disabled) { return true } e = e || window.event e.preventDefault() var mousePos = { x: e.clientX - canvas.getBoundingClientRect().left, y: e.clientY - canvas.getBoundingClientRect().top } // console.log(mousePos, 'mousePos') // 限制在指定区域内 if (mousePos.x < 0) { mousePos.x = 0 } else if (mousePos.x > 533) { mousePos.x = 533 } if (mousePos.y < 0) { mousePos.y = 0 } else if (mousePos.y > 300) { mousePos.y = 300 } points.value[pointIndex].x = mousePos.x points.value[pointIndex].y = mousePos.y draw() } function addDragEvents() { // if ($props.disabled) { // return true // } var dragEvents = { dragStart(e) { e = e || window.event var target = e.target || e.srcElement var pointIndex = parseInt(target.getAttribute('data-point-index'), 10) if (isNaN(pointIndex)) { return } document.onmouseup = function () { document.onmouseup = null document.onmousemove = null } document.onmousemove = function (e) { drag(e, pointIndex) } }, } var pointsElements = document.getElementsByClassName('point') for (var i = 0; i < pointsElements.length; i++) { pointsElements[i].addEventListener('mousedown', dragEvents.dragStart) pointsElements[i].setAttribute('data-point-index', i) } } function init() { if (points.value.length !== 4) { return } draw() setTimeout(() => { addDragEvents() }) } init() } onMounted(() => { setSize() setTimeout(() => { initDraw() }, 100); }) const style = ref([ { top: `${points.value[0].y - 5}px`, left: `${points.value[0].x - 5}px`, }, { top: `${points.value[1].y - 5}px`, left: `${points.value[1].x - 5}px`, }, { top: `${points.value[2].y - 5}px`, left: `${points.value[2].x - 5}px`, }, { top: `${points.value[3].y - 5}px`, left: `${points.value[3].x - 5}px`, }, ]) watch(() => points.value, () => { if (points.value.length !== 4) { style.value = [] return } style.value = [ { top: `${points.value[0].y - 5}px`, left: `${points.value[0].x - 5}px`, }, { top: `${points.value[1].y - 5}px`, left: `${points.value[1].x - 5}px`, }, { top: `${points.value[2].y - 5}px`, left: `${points.value[2].x - 5}px`, }, { top: `${points.value[3].y - 5}px`, left: `${points.value[3].x - 5}px`, }, ] }, { deep: true, }) const getPoints = () => { return points.value.map((item) => ([item.x / $props.width, item.y / $props.height])) } const setPonits = (data) => { if (!data) { points.value = [ { x: 30, y: 30 }, { x: 395, y: 30 }, { x: 395, y: 210 }, { x: 30, y: 210 }, ] initDraw() return } const pointsArr = JSON.parse(data) points.value = pointsArr.map((item: any) => ({ x: Number(item[0]) * $props.width, y: Number(item[1]) * $props.height, })) initDraw() } defineExpose({ points, getPoints, setPonits }) watch([() => $props.width, $props.height], () => { // // console.log(document.getElementById('myCanvas')) // console.log($props.width, $props.height, '123') }, { deep: true, immediate: true }) </script> <template> <div :style="{ width: `${$props.width}px`, height: `${$props.height}px`, position: 'relative', 'z-index': '9' }" :id="`${elementId}-container`"> <canvas :id="`${elementId}-canvas`" :width="$props.width" :height="$props.height" class="canvans" /> <div v-for="(item, index) in points" :key="index" class="point" :class="$props.disabled ? 'no' : ''" :style="style[index]" /> </div> </template> <style scoped> #draw-area { /* border: 1px solid #000; */ } .canvans { padding: 0; margin: 0; /* position: absolute; */ /* width: 100%; height: 100%; */ /* left: 0; top: 0; */ position: relative; } .point { width: 10px; height: 10px; position: absolute; border-radius: 50%; background-color: red; opacity: 0.5; top: 0; left: 0; z-index: 99; &:hover { cursor: move; } } .no { &:hover { cursor: default !important; } } </style>