图片更换为本地引用
This commit is contained in:
parent
f660711212
commit
306450e179
@ -46,7 +46,7 @@
|
||||
>
|
||||
<template #reference>
|
||||
<img
|
||||
src="https://api.znkjfw.com/admin-api/infra/file/4/get/库位库存_png_179_1739326653035.png"
|
||||
src="@/assets/imgs/indexPage/bin-location.png"
|
||||
alt=""
|
||||
:style="{
|
||||
position: 'absolute',
|
||||
@ -92,7 +92,7 @@
|
||||
<template #reference>
|
||||
<img
|
||||
@click="choosePoint(item)"
|
||||
src="https://api.znkjfw.com/admin-api/infra/file/4/get/库位库存_png_179_1739326653035.png"
|
||||
src="@/assets/imgs/indexPage/bin-location.png"
|
||||
alt=""
|
||||
:style="{
|
||||
position: 'absolute',
|
||||
|
@ -1,94 +0,0 @@
|
||||
<template>
|
||||
<div style="width: 600px; height: 300px; background: #dbeede; position: relative">
|
||||
<div v-for="(item, index) in points" :key="index">
|
||||
<div
|
||||
:style="{
|
||||
position: 'absolute',
|
||||
width: '10px',
|
||||
height: '10px',
|
||||
backgroundColor: '#000',
|
||||
borderRadius: '50%',
|
||||
zIndex: 999,
|
||||
left: item.x + 'px',
|
||||
top: item.y + 'px'
|
||||
}"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="width: 600px; height: 300px; background: #b3dcff; position: relative">
|
||||
<div v-for="(item, index) in mappedPoints" :key="index">
|
||||
<div
|
||||
:style="{
|
||||
position: 'absolute',
|
||||
width: '10px',
|
||||
height: '10px',
|
||||
backgroundColor: '#000',
|
||||
borderRadius: '50%',
|
||||
zIndex: 999,
|
||||
left: item.x + 'px',
|
||||
top: item.y + 'px'
|
||||
}"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
const points = ref([
|
||||
{
|
||||
x: 123.567,
|
||||
y: 178.123
|
||||
},
|
||||
{
|
||||
x: 255.567,
|
||||
y: 79.123
|
||||
},
|
||||
{
|
||||
x: 382.567,
|
||||
y: 178.123
|
||||
},
|
||||
{
|
||||
x: 481.567,
|
||||
y: 238.123
|
||||
}
|
||||
])
|
||||
|
||||
const mapPointsToLine = (points) => {
|
||||
if (points.length < 2) {
|
||||
return points
|
||||
}
|
||||
// 取数组的第一项和最后一项
|
||||
const firstPoint = points[0]
|
||||
const lastPoint = points[points.length - 1]
|
||||
|
||||
// 计算直线的斜率
|
||||
const dx = lastPoint.x - firstPoint.x
|
||||
const dy = lastPoint.y - firstPoint.y
|
||||
if (dx === 0) {
|
||||
// 垂直直线的情况
|
||||
return points.map((point, index) => {
|
||||
if (index === 0 || index === points.length - 1) {
|
||||
return point
|
||||
}
|
||||
return { x: firstPoint.x, y: point.y }
|
||||
})
|
||||
}
|
||||
const slope = dy / dx
|
||||
// 计算直线的截距
|
||||
const intercept = firstPoint.y - slope * firstPoint.x
|
||||
|
||||
// 映射其他点到直线上
|
||||
return points.map((point, index) => {
|
||||
if (index === 0 || index === points.length - 1) {
|
||||
return point
|
||||
}
|
||||
const newY = slope * point.x + intercept
|
||||
return { x: point.x, y: newY }
|
||||
})
|
||||
}
|
||||
|
||||
const mappedPoints = mapPointsToLine(points.value)
|
||||
console.log(mappedPoints)
|
||||
</script>
|
@ -1,125 +0,0 @@
|
||||
<template>
|
||||
<div
|
||||
@mousedown="startSelection"
|
||||
@mousemove="updateSelection"
|
||||
@mouseup="endSelection"
|
||||
style="position: relative; height: 100vh; border: 1px solid #ccc"
|
||||
>
|
||||
<!-- 框选区域 -->
|
||||
<div
|
||||
v-if="isSelecting || selectionBox.width > 0"
|
||||
:style="{
|
||||
position: 'absolute',
|
||||
left: `${selectionBox.x}px`,
|
||||
top: `${selectionBox.y}px`,
|
||||
width: `${selectionBox.width}px`,
|
||||
height: `${selectionBox.height}px`,
|
||||
border: '2px dashed #007bff',
|
||||
backgroundColor: 'rgba(0, 123, 255, 0.1)'
|
||||
}"
|
||||
></div>
|
||||
|
||||
<!-- 图片 -->
|
||||
<img
|
||||
v-for="(img, index) in images"
|
||||
:key="index"
|
||||
:src="img.src"
|
||||
:style="{
|
||||
position: 'absolute',
|
||||
left: `${img.x}px`,
|
||||
top: `${img.y}px`,
|
||||
width: '100px',
|
||||
height: '100px',
|
||||
userSelect: isSelecting ? 'none' : 'auto', // 动态禁用选择
|
||||
pointerEvents: isSelecting ? 'none' : 'auto' // 动态禁用鼠标事件
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from 'vue'
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
// 图片数据
|
||||
const images = ref([
|
||||
{ src: 'https://via.placeholder.com/100', x: 100, y: 100 },
|
||||
{ src: 'https://via.placeholder.com/100', x: 300, y: 200 },
|
||||
{ src: 'https://via.placeholder.com/100', x: 500, y: 300 }
|
||||
])
|
||||
|
||||
// 框选区域
|
||||
const selectionBox = ref({
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 0,
|
||||
height: 0
|
||||
})
|
||||
|
||||
// 是否正在框选
|
||||
const isSelecting = ref(false)
|
||||
|
||||
// 框选起始位置
|
||||
const startPos = ref({ x: 0, y: 0 })
|
||||
|
||||
// 开始框选
|
||||
const startSelection = (event) => {
|
||||
isSelecting.value = true
|
||||
startPos.value = { x: event.clientX, y: event.clientY }
|
||||
selectionBox.value = {
|
||||
x: event.clientX,
|
||||
y: event.clientY,
|
||||
width: 0,
|
||||
height: 0
|
||||
}
|
||||
|
||||
// 阻止默认行为(避免选中图片或文本)
|
||||
event.preventDefault()
|
||||
}
|
||||
|
||||
// 更新框选区域
|
||||
const updateSelection = (event) => {
|
||||
if (!isSelecting.value) return
|
||||
|
||||
const currentX = event.clientX
|
||||
const currentY = event.clientY
|
||||
|
||||
selectionBox.value = {
|
||||
x: Math.min(startPos.value.x, currentX),
|
||||
y: Math.min(startPos.value.y, currentY),
|
||||
width: Math.abs(currentX - startPos.value.x),
|
||||
height: Math.abs(currentY - startPos.value.y)
|
||||
}
|
||||
|
||||
// 阻止默认行为(避免选中图片或文本)
|
||||
event.preventDefault()
|
||||
}
|
||||
|
||||
// 结束框选
|
||||
const endSelection = () => {
|
||||
isSelecting.value = false
|
||||
console.log('框选区域:', selectionBox.value)
|
||||
}
|
||||
|
||||
return {
|
||||
images,
|
||||
selectionBox,
|
||||
isSelecting,
|
||||
startSelection,
|
||||
updateSelection,
|
||||
endSelection
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 禁用用户选择 */
|
||||
img {
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
@ -1,155 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 左侧菜单 -->
|
||||
<div
|
||||
style="
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 200px;
|
||||
height: 100vh;
|
||||
background-color: #f0f0f0;
|
||||
"
|
||||
>
|
||||
左侧菜单
|
||||
</div>
|
||||
|
||||
<!-- 背景区域 -->
|
||||
<div
|
||||
ref="background"
|
||||
style="margin-left: 200px; height: 100vh; position: relative; background-color: #fff"
|
||||
>
|
||||
<!-- 其他定位元素(如图片) -->
|
||||
<img
|
||||
src="https://sys.znkjfw.com/imgs/process/%E8%AF%B7%E5%81%87.png"
|
||||
style="position: absolute; top: 100px; left: 300px; width: 150px; height: 150px"
|
||||
alt="示例图片"
|
||||
/>
|
||||
|
||||
<!-- 显示测量结果 -->
|
||||
<div v-if="distance !== null" style="position: absolute; top: 20px; left: 220px">
|
||||
距离:{{ distance.toFixed(2) }} 像素
|
||||
</div>
|
||||
|
||||
<!-- 绘制点和连线 -->
|
||||
<template v-if="points.length > 0">
|
||||
<div
|
||||
v-for="(point, index) in points"
|
||||
:key="index"
|
||||
:style="{
|
||||
position: 'absolute',
|
||||
left: `${point.x}px`,
|
||||
top: `${point.y}px`,
|
||||
width: '10px',
|
||||
height: '10px',
|
||||
backgroundColor: 'red',
|
||||
borderRadius: '50%'
|
||||
}"
|
||||
></div>
|
||||
<div
|
||||
v-if="points.length === 2"
|
||||
:style="{
|
||||
position: 'absolute',
|
||||
left: `${points[0].x}px`,
|
||||
top: `${points[0].y}px`,
|
||||
width: `${lineWidth}px`,
|
||||
height: '2px',
|
||||
backgroundColor: 'blue',
|
||||
transform: `rotate(${lineAngle}deg)`,
|
||||
transformOrigin: '0 0'
|
||||
}"
|
||||
></div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const background = ref(null) // 背景区域的 DOM 元素
|
||||
const points = ref([]) // 存储点击的点位
|
||||
const distance = ref(null) // 存储两点之间的距离
|
||||
|
||||
// 计算两点之间的距离
|
||||
const calculateDistance = (point1, point2) => {
|
||||
const dx = point2.x - point1.x
|
||||
const dy = point2.y - point1.y
|
||||
return Math.sqrt(dx * dx + dy * dy)
|
||||
}
|
||||
|
||||
// 计算连线的角度
|
||||
const lineAngle = computed(() => {
|
||||
if (points.value.length === 2) {
|
||||
const dx = points.value[1].x - points.value[0].x
|
||||
const dy = points.value[1].y - points.value[0].y
|
||||
return Math.atan2(dy, dx) * (180 / Math.PI)
|
||||
}
|
||||
return 0
|
||||
})
|
||||
|
||||
// 计算连线的长度
|
||||
const lineWidth = computed(() => {
|
||||
if (points.value.length === 2) {
|
||||
return calculateDistance(points.value[0], points.value[1])
|
||||
}
|
||||
return 0
|
||||
})
|
||||
|
||||
// 处理点击事件
|
||||
const handleClick = (event) => {
|
||||
// 获取点击点相对于整个页面的坐标
|
||||
const x = event.clientX
|
||||
const y = event.clientY
|
||||
|
||||
// 检查点击是否发生在背景区域内
|
||||
const backgroundRect = background.value.getBoundingClientRect()
|
||||
if (
|
||||
x >= backgroundRect.left &&
|
||||
x <= backgroundRect.right &&
|
||||
y >= backgroundRect.top &&
|
||||
y <= backgroundRect.bottom
|
||||
) {
|
||||
if (points.value.length === 2) {
|
||||
// 如果已经有两个点,清空信息
|
||||
points.value = []
|
||||
distance.value = null
|
||||
} else {
|
||||
// 记录点击的点位(相对于背景区域的坐标)
|
||||
const offsetX = x - backgroundRect.left
|
||||
const offsetY = y - backgroundRect.top
|
||||
points.value.push({ x: offsetX, y: offsetY })
|
||||
if (points.value.length === 2) {
|
||||
// 计算两点之间的距离
|
||||
distance.value = calculateDistance(points.value[0], points.value[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 监听全局点击事件
|
||||
onMounted(() => {
|
||||
window.addEventListener('click', handleClick)
|
||||
})
|
||||
|
||||
// 移除全局点击事件监听
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('click', handleClick)
|
||||
})
|
||||
|
||||
return {
|
||||
background,
|
||||
points,
|
||||
distance,
|
||||
lineAngle,
|
||||
lineWidth
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 样式可以根据需要调整 */
|
||||
</style>
|
@ -1,180 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- SVG 画布 -->
|
||||
<svg
|
||||
ref="svg"
|
||||
width="500"
|
||||
height="300"
|
||||
@mousedown="handleMouseDown"
|
||||
@mousemove="handleMouseMove"
|
||||
@mouseup="handleMouseUp"
|
||||
>
|
||||
<!-- 绘制所有曲线 -->
|
||||
<path
|
||||
v-for="(curve, index) in curves"
|
||||
:key="index"
|
||||
:d="getCurvePath(curve)"
|
||||
stroke="#000"
|
||||
fill="none"
|
||||
stroke-width="2"
|
||||
:class="{ selected: selectedCurve === curve }"
|
||||
@click="svgClick(curve)"
|
||||
/>
|
||||
<!-- 绘制控制点和连线 -->
|
||||
<line
|
||||
v-if="selectedCurve"
|
||||
:x1="selectedCurve.start.x"
|
||||
:y1="selectedCurve.start.y"
|
||||
:x2="selectedCurve.control1.x"
|
||||
:y2="selectedCurve.control1.y"
|
||||
stroke="gray"
|
||||
stroke-dasharray="2"
|
||||
/>
|
||||
<line
|
||||
v-if="selectedCurve"
|
||||
:x1="selectedCurve.end.x"
|
||||
:y1="selectedCurve.end.y"
|
||||
:x2="selectedCurve.control2.x"
|
||||
:y2="selectedCurve.control2.y"
|
||||
stroke="gray"
|
||||
stroke-dasharray="2"
|
||||
/>
|
||||
<!-- 绘制起点、终点和控制点 -->
|
||||
<circle
|
||||
v-for="(curve, index) in curves"
|
||||
:key="'start' + index"
|
||||
:cx="curve.start.x"
|
||||
:cy="curve.start.y"
|
||||
r="5"
|
||||
fill="red"
|
||||
@mousedown="startDrag($event, curve, 'start')"
|
||||
/>
|
||||
<circle
|
||||
v-for="(curve, index) in curves"
|
||||
:key="'end' + index"
|
||||
:cx="curve.end.x"
|
||||
:cy="curve.end.y"
|
||||
r="5"
|
||||
fill="red"
|
||||
@mousedown="startDrag($event, curve, 'end')"
|
||||
/>
|
||||
<circle
|
||||
v-if="selectedCurve"
|
||||
:cx="selectedCurve.control1.x"
|
||||
:cy="selectedCurve.control1.y"
|
||||
r="5"
|
||||
fill="green"
|
||||
@mousedown="startDrag($event, selectedCurve, 'control1')"
|
||||
/>
|
||||
<circle
|
||||
v-if="selectedCurve"
|
||||
:cx="selectedCurve.control2.x"
|
||||
:cy="selectedCurve.control2.y"
|
||||
r="5"
|
||||
fill="green"
|
||||
@mousedown="startDrag($event, selectedCurve, 'control2')"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
<!-- 显示控制点坐标 -->
|
||||
<div class="points" v-if="selectedCurve">
|
||||
<p>起点: ({{ selectedCurve.start.x }}, {{ selectedCurve.start.y }})</p>
|
||||
<p>控制点 1: ({{ selectedCurve.control1.x }}, {{ selectedCurve.control1.y }})</p>
|
||||
<p>控制点 2: ({{ selectedCurve.control2.x }}, {{ selectedCurve.control2.y }})</p>
|
||||
<p>终点: ({{ selectedCurve.end.x }}, {{ selectedCurve.end.y }})</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
const svg = ref(null) // SVG 元素的引用
|
||||
const curves = ref([]) // 存储所有曲线
|
||||
const selectedCurve = ref(null) // 当前选中的曲线
|
||||
const isDragging = ref(false) // 是否正在拖拽
|
||||
const dragTarget = ref(null) // 当前拖拽的目标(起点、终点、控制点)
|
||||
|
||||
// 获取鼠标位置
|
||||
const getMousePos = (event) => {
|
||||
const rect = svg.value.getBoundingClientRect()
|
||||
return {
|
||||
x: event.clientX - rect.left,
|
||||
y: event.clientY - rect.top
|
||||
}
|
||||
}
|
||||
|
||||
// 开始拖拽
|
||||
const startDrag = (event, curve, target) => {
|
||||
event.preventDefault()
|
||||
isDragging.value = true
|
||||
selectedCurve.value = curve
|
||||
dragTarget.value = target
|
||||
}
|
||||
|
||||
// 鼠标按下事件
|
||||
const handleMouseDown = (event) => {
|
||||
const mousePos = getMousePos(event)
|
||||
|
||||
// 如果没有选中任何点,则创建一条新的直线
|
||||
if (!isDragging.value && curves.value.length === 0) {
|
||||
const newCurve = {
|
||||
start: mousePos,
|
||||
end: mousePos,
|
||||
control1: { x: mousePos.x + 50, y: mousePos.y - 50 },
|
||||
control2: { x: mousePos.x + 100, y: mousePos.y - 50 }
|
||||
}
|
||||
curves.value.push(newCurve)
|
||||
selectedCurve.value = newCurve
|
||||
dragTarget.value = 'end'
|
||||
isDragging.value = true
|
||||
}
|
||||
}
|
||||
|
||||
// 鼠标移动事件
|
||||
const handleMouseMove = (event) => {
|
||||
if (!isDragging.value || !selectedCurve.value) return
|
||||
|
||||
const mousePos = getMousePos(event)
|
||||
|
||||
// 更新拖拽的目标点
|
||||
if (dragTarget.value === 'start') {
|
||||
selectedCurve.value.start = mousePos
|
||||
} else if (dragTarget.value === 'end') {
|
||||
selectedCurve.value.end = mousePos
|
||||
} else if (dragTarget.value === 'control1') {
|
||||
selectedCurve.value.control1 = mousePos
|
||||
} else if (dragTarget.value === 'control2') {
|
||||
selectedCurve.value.control2 = mousePos
|
||||
}
|
||||
}
|
||||
|
||||
// 鼠标松开事件
|
||||
const handleMouseUp = () => {
|
||||
isDragging.value = false
|
||||
dragTarget.value = null
|
||||
}
|
||||
|
||||
// 获取曲线的路径
|
||||
const getCurvePath = (curve) => {
|
||||
return `M ${curve.start.x} ${curve.start.y} C ${curve.control1.x} ${curve.control1.y}, ${curve.control2.x} ${curve.control2.y}, ${curve.end.x} ${curve.end.y}`
|
||||
}
|
||||
const svgClick = (item) => {
|
||||
console.log(item)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
svg {
|
||||
border: 1px solid #000;
|
||||
cursor: crosshair;
|
||||
}
|
||||
|
||||
path.selected {
|
||||
stroke: blue;
|
||||
}
|
||||
|
||||
.points {
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue
Block a user