封装v-drag
This commit is contained in:
parent
437738b211
commit
557f557857
@ -44,6 +44,7 @@ import VueDOMPurifyHTML from 'vue-dompurify-html' // 解决v-html 的安全隐
|
||||
import VueDragResizeRotate from '@gausszhou/vue3-drag-resize-rotate'
|
||||
import '@gausszhou/vue3-drag-resize-rotate/lib/bundle.esm.css'
|
||||
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
||||
import { vDrag } from './utils/drag';
|
||||
// 创建实例
|
||||
const setupAll = async () => {
|
||||
const app = createApp(App)
|
||||
@ -67,7 +68,8 @@ const setupAll = async () => {
|
||||
setupMountedFocus(app)
|
||||
|
||||
await router.isReady()
|
||||
|
||||
// 注册全局指令
|
||||
app.directive('drag', vDrag);
|
||||
app.use(VueDOMPurifyHTML)
|
||||
app.use(VueDragResizeRotate)
|
||||
app.mount('#app')
|
||||
|
31
src/utils/drag.ts
Normal file
31
src/utils/drag.ts
Normal file
@ -0,0 +1,31 @@
|
||||
// directives.js
|
||||
export const vDrag = {
|
||||
mounted(el) {
|
||||
el.style.position = 'absolute';
|
||||
|
||||
let startX, startY, initialMouseX, initialMouseY;
|
||||
|
||||
const mousemove = (e) => {
|
||||
const dx = e.clientX - initialMouseX;
|
||||
const dy = e.clientY - initialMouseY;
|
||||
el.style.top = `${startY + dy}px`;
|
||||
el.style.left = `${startX + dx}px`;
|
||||
};
|
||||
|
||||
const mouseup = () => {
|
||||
document.removeEventListener('mousemove', mousemove);
|
||||
document.removeEventListener('mouseup', mouseup);
|
||||
};
|
||||
|
||||
el.addEventListener('mousedown', (e) => {
|
||||
startX = el.offsetLeft;
|
||||
startY = el.offsetTop;
|
||||
initialMouseX = e.clientX;
|
||||
initialMouseY = e.clientY;
|
||||
document.addEventListener('mousemove', mousemove);
|
||||
document.addEventListener('mouseup', mouseup);
|
||||
e.preventDefault();
|
||||
});
|
||||
}
|
||||
|
||||
};
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="affix-container">
|
||||
<div class="affix-container" :style="{ height: heightVal + 'px' }">
|
||||
<el-affix target=".affix-container" :offset="80">
|
||||
<div class="affix-container-top">
|
||||
<el-scrollbar>
|
||||
@ -28,14 +28,26 @@
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</el-affix>
|
||||
<div class="indexpage-container" v-if="imgUrl">
|
||||
<div class="indexpage-container" v-if="imgUrl" v-drag>
|
||||
<div class="indexpage-container-box">
|
||||
<img :src="imgUrl" alt="" class="indexpage-container-box-img" />
|
||||
|
||||
<div class="indexpage-container-box-point">
|
||||
<div class="line-box" v-for="(item, index) in lineList" :key="index" :style="{ left: item.left * radio + 'px', top: item.top * radio + 'px', width: item.distance * radio + 'px', height: item.height * radio + 'px', transform: 'rotate(' + item.angle + 'deg)', backgroundColor: item.color ,transformOrigin: 'left top'}">
|
||||
|
||||
</div>
|
||||
<div class="indexpage-container-box-point">
|
||||
<div
|
||||
class="line-box"
|
||||
v-for="(item, index) in lineList"
|
||||
:key="index"
|
||||
:style="{
|
||||
left: item.left * radio + 'px',
|
||||
top: item.top * radio + 'px',
|
||||
width: item.distance * radio + 'px',
|
||||
height: item.height * radio + 'px',
|
||||
transform: 'rotate(' + item.angle + 'deg)',
|
||||
backgroundColor: item.color,
|
||||
transformOrigin: 'left top'
|
||||
}"
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
class="indexpage-container-box-point-item"
|
||||
v-for="(item, index) in pointList"
|
||||
@ -51,38 +63,48 @@
|
||||
}"
|
||||
>
|
||||
<div v-if="item.type == 2" style="width: 100%; height: 100%">
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
trigger="hover"
|
||||
width="auto"
|
||||
>
|
||||
<el-popover placement="top-start" trigger="hover" width="auto">
|
||||
<template #reference>
|
||||
<img :src="item.imgUrl" alt="" style="width: 100%; height: 100%" @dblclick="storeClick(item)"/>
|
||||
<img
|
||||
:src="item.imgUrl"
|
||||
alt=""
|
||||
style="width: 100%; height: 100%"
|
||||
@dblclick="storeClick(item)"
|
||||
/>
|
||||
</template>
|
||||
<div class="indexpage-container-box-point-item-inner-popover">
|
||||
<div class="indexpage-container-box-point-item-inner-popover-item" style="margin-bottom: 8px;">
|
||||
<div
|
||||
class="indexpage-container-box-point-item-inner-popover-item"
|
||||
style="margin-bottom: 8px"
|
||||
>
|
||||
<div class="indexpage-container-box-point-item-inner-popover-name">
|
||||
库位名:
|
||||
库位名:
|
||||
</div>
|
||||
<div class="indexpage-container-box-point-item-inner-popover-value">
|
||||
{{ item.showData.locationNo || '' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="indexpage-container-box-point-item-inner-popover-value">
|
||||
{{ item.showData.locationNo || '' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="indexpage-container-box-point-item-inner-popover-item" style="margin-bottom: 8px;">
|
||||
<div
|
||||
class="indexpage-container-box-point-item-inner-popover-item"
|
||||
style="margin-bottom: 8px"
|
||||
>
|
||||
<div class="indexpage-container-box-point-item-inner-popover-name">
|
||||
所属线库:
|
||||
所属线库:
|
||||
</div>
|
||||
<div class="indexpage-container-box-point-item-inner-popover-value">
|
||||
{{ item.showData.laneName || '' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="indexpage-container-box-point-item-inner-popover-value">
|
||||
{{ item.showData.laneName || '' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="indexpage-container-box-point-item-inner-popover-item" style="margin-bottom: 8px;">
|
||||
<div
|
||||
class="indexpage-container-box-point-item-inner-popover-item"
|
||||
style="margin-bottom: 8px"
|
||||
>
|
||||
<div class="indexpage-container-box-point-item-inner-popover-name">
|
||||
所属区域:
|
||||
</div>
|
||||
<div class="indexpage-container-box-point-item-inner-popover-value">
|
||||
{{ item.showData.areaName || '' }}
|
||||
</div>
|
||||
所属区域:
|
||||
</div>
|
||||
<div class="indexpage-container-box-point-item-inner-popover-value">
|
||||
{{ item.showData.areaName || '' }}
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="indexpage-container-box-point-item-inner-popover-item" style="margin-bottom: 8px;">
|
||||
<div class="indexpage-container-box-point-item-inner-popover-name">
|
||||
@ -160,7 +182,7 @@ const getPositionMapListFun = async (positionMapId) => {
|
||||
if (data && data.length > 0) {
|
||||
data.forEach((item) => {
|
||||
// console.log(JSON.parse(item.dataJson))
|
||||
item.formattedData = item.dataJson ?JSON.parse(item.dataJson):''
|
||||
item.formattedData = item.dataJson ? JSON.parse(item.dataJson) : ''
|
||||
item.showData = item.dataJson ? JSON.parse(item.dataJson)[0] : null
|
||||
item.imgUrl = formatteTypeImg(item.type)
|
||||
})
|
||||
@ -169,41 +191,46 @@ const getPositionMapListFun = async (positionMapId) => {
|
||||
pointList.value = data
|
||||
|
||||
console.log(pointList.value)
|
||||
let lineStyle = calculateDistanceAndAngle({
|
||||
left: pointList.value[0].locationX,
|
||||
top: pointList.value[0].locationY
|
||||
}, {
|
||||
left: pointList.value[1].locationX,
|
||||
top: pointList.value[1].locationY
|
||||
})
|
||||
let lineStyle = calculateDistanceAndAngle(
|
||||
{
|
||||
left: pointList.value[0].locationX,
|
||||
top: pointList.value[0].locationY
|
||||
},
|
||||
{
|
||||
left: pointList.value[1].locationX,
|
||||
top: pointList.value[1].locationY
|
||||
}
|
||||
)
|
||||
console.log(lineStyle)
|
||||
lineList.value = [{
|
||||
...lineStyle,
|
||||
color: '#1677ff',
|
||||
height: 2,
|
||||
}]
|
||||
lineList.value = [
|
||||
{
|
||||
...lineStyle,
|
||||
color: '#1677ff',
|
||||
height: 2
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
const calculateDistanceAndAngle = (point1, point2) => {
|
||||
// 计算水平和垂直方向的差值
|
||||
const dx = point2.left - point1.left;
|
||||
const dy = point2.top - point1.top;
|
||||
// 计算水平和垂直方向的差值
|
||||
const dx = point2.left - point1.left
|
||||
const dy = point2.top - point1.top
|
||||
|
||||
// 计算两点之间的长度(使用勾股定理)
|
||||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||
// 计算两点之间的长度(使用勾股定理)
|
||||
const distance = Math.sqrt(dx * dx + dy * dy)
|
||||
|
||||
// 计算两点连线与水平轴正方向的夹角(弧度)
|
||||
const angleInRadians = Math.atan2(dy, dx);
|
||||
// 计算两点连线与水平轴正方向的夹角(弧度)
|
||||
const angleInRadians = Math.atan2(dy, dx)
|
||||
|
||||
// 将弧度转换为角度
|
||||
const angleInDegrees = angleInRadians * (180 / Math.PI);
|
||||
// 将弧度转换为角度
|
||||
const angleInDegrees = angleInRadians * (180 / Math.PI)
|
||||
|
||||
return {
|
||||
distance: distance,
|
||||
angle: angleInDegrees,
|
||||
left: point1.left,
|
||||
top: point1.top
|
||||
};
|
||||
return {
|
||||
distance: distance,
|
||||
angle: angleInDegrees,
|
||||
left: point1.left,
|
||||
top: point1.top
|
||||
}
|
||||
}
|
||||
|
||||
const formatteTypeImg = (type) => {
|
||||
@ -263,14 +290,14 @@ const getMapData = async (item) => {
|
||||
})
|
||||
imgUrl.value = data
|
||||
computedRatio()
|
||||
|
||||
}
|
||||
const heightVal = ref(0)
|
||||
const radio = ref(1)
|
||||
const computedRatio = () => {
|
||||
nextTick(() => {
|
||||
if (imgUrl.value) {
|
||||
let width = getElementWidthByClass('indexpage-container')
|
||||
getImageWidth(imgUrl.value).then((res) => {
|
||||
getImageWidth(imgUrl.value,'width').then((res) => {
|
||||
// console.log(res)
|
||||
let ratioVal = width / res
|
||||
radio.value = ratioVal
|
||||
@ -280,16 +307,20 @@ const computedRatio = () => {
|
||||
})
|
||||
}
|
||||
})
|
||||
getImageWidth(imgUrl.value,'height').then((res) => {
|
||||
console.log("高",res)
|
||||
heightVal.value = res
|
||||
})
|
||||
// console.log(width)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getImageWidth = (imageUrl) => {
|
||||
const getImageWidth = (imageUrl,name) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image()
|
||||
img.onload = function () {
|
||||
resolve(img.width)
|
||||
resolve(img[name])
|
||||
}
|
||||
img.onerror = function () {
|
||||
reject(new Error('图片加载失败'))
|
||||
@ -320,6 +351,8 @@ onBeforeUnmount(() => {
|
||||
<style lang="scss" scoped>
|
||||
.affix-container {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.indexpage-container {
|
||||
width: 100%;
|
||||
@ -379,14 +412,16 @@ onBeforeUnmount(() => {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
.indexpage-container-box-point-item-inner-popover-item{
|
||||
.indexpage-container-box-point-item-inner-popover-item {
|
||||
display: flex;
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: #0D162A;
|
||||
font-family:
|
||||
PingFangSC,
|
||||
PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: #0d162a;
|
||||
}
|
||||
.line-box{
|
||||
.line-box {
|
||||
position: absolute;
|
||||
}
|
||||
</style>
|
||||
|
Loading…
Reference in New Issue
Block a user