|
|
@@ -0,0 +1,655 @@
|
|
|
+<template>
|
|
|
+ <div>
|
|
|
+ <div @click="show">
|
|
|
+ <slot>
|
|
|
+ <div v-if="value.heatMapData.length" class="cursor-pointer">
|
|
|
+ 已选<span class="text-primary p-[4px]">{{ value.heatMapData.length }}</span
|
|
|
+ >个热区
|
|
|
+ </div>
|
|
|
+ <div v-else class="cursor-pointer">添加热区</div>
|
|
|
+ </slot>
|
|
|
+ </div>
|
|
|
+ <el-dialog v-model="showDialog" title="热区设置" width="810px" :destroy-on-close="true" :close-on-click-modal="false">
|
|
|
+ <div class="flex">
|
|
|
+ <div
|
|
|
+ class="hot-area-img-wrap content-box relative bg-gray-100 border border-dashed border-gray-500 bg-no-repeat"
|
|
|
+ :style="{ backgroundImage: 'url(' + img(value.imageUrl) + ')', width: contentBoxWidth + 'px', height: contentBoxHeight + 'px' }"
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ v-for="(item, index) in dragBoxArr"
|
|
|
+ :id="'box_' + index"
|
|
|
+ :key="index"
|
|
|
+ class="area-box border border-solid border-[#ccc] w-[100px] h-[100px] absolute top-0 left-0 select-none p-[5px]"
|
|
|
+ :style="{ left: item.left + item.unit, top: item.top + item.unit, width: item.width + item.unit, height: item.height + item.unit }"
|
|
|
+ @mousedown="mouseDown($event, index)"
|
|
|
+ >
|
|
|
+ <span>{{ Number(index) + 1 }}</span>
|
|
|
+ <template v-if="item.link">
|
|
|
+ <span class="p-[4px]">|</span>
|
|
|
+ <span>{{ item.link }}</span>
|
|
|
+ </template>
|
|
|
+ <span class="box1" @mousedown.stop="resizeMouseDown($event, index)"></span>
|
|
|
+ <span class="box2" @mousedown.stop="resizeMouseDown($event, index)"></span>
|
|
|
+ <span class="box3" @mousedown.stop="resizeMouseDown($event, index)"></span>
|
|
|
+ <span class="box4" @mousedown.stop="resizeMouseDown($event, index)"></span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-form label-width="80px" class="pl-[20px]">
|
|
|
+ <h3 class="mb-[10px] text-lg text-black">热区管理</h3>
|
|
|
+ <el-button type="primary" plain size="small" class="mb-[10px]" @click="addArea">添加热区</el-button>
|
|
|
+ <div class="overflow-y-auto h-[300px]">
|
|
|
+ <template v-for="(item, index) in dragBoxArr" :key="index">
|
|
|
+ <div class="mb-[16px]" v-if="item">
|
|
|
+ <el-form-item :label="'热区' + (Number(index) + 1)">
|
|
|
+ <div class="flex items-center">
|
|
|
+ <div style="width: 230px">
|
|
|
+ <WebLinkInput v-model="item.link" placeholder="请输入或选择链接" />
|
|
|
+ </div>
|
|
|
+ <icon
|
|
|
+ class="del cursor-pointer mx-[10px]"
|
|
|
+ name="element CircleCloseFilled"
|
|
|
+ color="#bbb"
|
|
|
+ size="20px"
|
|
|
+ @click="dragBoxArr.splice(index, 1)"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <template #footer>
|
|
|
+ <span class="dialog-footer">
|
|
|
+ <el-button @click="showDialog = false">返回</el-button>
|
|
|
+ <el-button type="primary" @click="save">确定</el-button>
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script lang="ts" setup>
|
|
|
+import { ref, reactive, computed } from 'vue';
|
|
|
+import { ElMessage } from 'element-plus';
|
|
|
+import { img, deepClone } from '@/utils/common';
|
|
|
+
|
|
|
+const prop = defineProps({
|
|
|
+ modelValue: {
|
|
|
+ type: String,
|
|
|
+ default: ''
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+const emit = defineEmits(['update:modelValue']);
|
|
|
+
|
|
|
+const value: any = computed({
|
|
|
+ get() {
|
|
|
+ return prop.modelValue;
|
|
|
+ },
|
|
|
+ set(value) {
|
|
|
+ emit('update:modelValue', value);
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+/**
|
|
|
+ * 公式:
|
|
|
+ * 宽度:400
|
|
|
+ * 比例:原图高/原图宽,示例:466/698=0.66
|
|
|
+ * 高度:宽度*比例,示例:400*0.66=264
|
|
|
+ */
|
|
|
+
|
|
|
+const showDialog = ref(false);
|
|
|
+const contentBoxWidth = ref(400);
|
|
|
+const contentBoxHeight = ref(400);
|
|
|
+const dragBoxArr: any = reactive([]);
|
|
|
+
|
|
|
+const imgRatio = ref(1); // 图片比例
|
|
|
+
|
|
|
+// 热区尺寸
|
|
|
+const areaRadio = ref(0.25); // 占位图比例
|
|
|
+const areaWidth = ref(100);
|
|
|
+const areaHeight = ref(100);
|
|
|
+const areaNum = ref(4); // 每行显示的数量
|
|
|
+
|
|
|
+// 添加热区
|
|
|
+const addArea = () => {
|
|
|
+ let left = (dragBoxArr.length % areaNum.value) * areaWidth.value;
|
|
|
+ let top = Math.floor(dragBoxArr.length / areaNum.value) * areaHeight.value;
|
|
|
+ const edgeHeight = top + areaHeight.value / 2;
|
|
|
+ if (top >= contentBoxHeight.value || edgeHeight >= contentBoxHeight.value) {
|
|
|
+ top = 0;
|
|
|
+ left = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ dragBoxArr.push({
|
|
|
+ left,
|
|
|
+ top,
|
|
|
+ width: areaWidth.value,
|
|
|
+ height: areaHeight.value,
|
|
|
+ unit: 'px',
|
|
|
+ link: ''
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+// 移动事件
|
|
|
+const mouseDown = (e: any, index: any) => {
|
|
|
+ const box: any = document.getElementById('box_' + index);
|
|
|
+ const disX = e.clientX - box.offsetLeft;
|
|
|
+ const disY = e.clientY - box.offsetTop;
|
|
|
+
|
|
|
+ // 鼠标移动时
|
|
|
+ document.onmousemove = function (e) {
|
|
|
+ box.style.left = e.clientX - disX + 'px';
|
|
|
+ box.style.top = e.clientY - disY + 'px';
|
|
|
+
|
|
|
+ // 边界判断
|
|
|
+ if (e.clientX - disX < 0) {
|
|
|
+ box.style.left = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (e.clientX - disX > contentBoxWidth.value - box.offsetWidth) {
|
|
|
+ box.style.left = contentBoxWidth.value - box.offsetWidth + 'px';
|
|
|
+ }
|
|
|
+
|
|
|
+ if (e.clientY - disY < 0) {
|
|
|
+ box.style.top = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (e.clientY - disY > contentBoxHeight.value - box.offsetHeight) {
|
|
|
+ box.style.top = contentBoxHeight.value - box.offsetHeight + 'px';
|
|
|
+ }
|
|
|
+
|
|
|
+ dragBoxArr[index].left = box.offsetLeft;
|
|
|
+ dragBoxArr[index].top = box.offsetTop;
|
|
|
+ dragBoxArr[index].width = box.offsetWidth;
|
|
|
+ dragBoxArr[index].height = box.offsetHeight;
|
|
|
+ dragBoxArr[index].unit = 'px';
|
|
|
+ };
|
|
|
+
|
|
|
+ // 鼠标抬起时
|
|
|
+ document.onmouseup = function (e) {
|
|
|
+ document.onmousemove = null;
|
|
|
+ };
|
|
|
+};
|
|
|
+
|
|
|
+// 拖拽大小事件
|
|
|
+const resizeMouseDown = (e: any, index: any) => {
|
|
|
+ const oEv = e;
|
|
|
+ oEv.stopPropagation();
|
|
|
+ const box: any = document.getElementById('box_' + index);
|
|
|
+ const className = e.target.className;
|
|
|
+
|
|
|
+ // 获取移动前盒子的宽高,
|
|
|
+ const oldWidth = box.offsetWidth;
|
|
|
+ const oldHeight = box.offsetHeight;
|
|
|
+
|
|
|
+ // 获取鼠标距离屏幕的left和top值
|
|
|
+ const oldX = oEv.clientX;
|
|
|
+ const oldY = oEv.clientY;
|
|
|
+
|
|
|
+ // 元素相对于最近的父级定位
|
|
|
+ const oldLeft = box.offsetLeft;
|
|
|
+ const oldTop = box.offsetTop;
|
|
|
+
|
|
|
+ // 设置最小的宽度
|
|
|
+ const minWidth = 50;
|
|
|
+ const minHeight = 50;
|
|
|
+
|
|
|
+ document.onmousemove = function (e) {
|
|
|
+ const oEv = e;
|
|
|
+ // console.log('move', "width:" + oldWidth,
|
|
|
+ // ',oldLeft: ' + oldLeft, ',oldTop: ' + oldTop,
|
|
|
+ // ',oldX:clientX-- ' + oldX + ':' + oEv.clientX,
|
|
|
+ // ',oldY:clientY-- ' + oldY + ':' + oEv.clientY,
|
|
|
+ // )
|
|
|
+
|
|
|
+ // 左上角
|
|
|
+ if (className == 'box1') {
|
|
|
+ let width = oldWidth - (oEv.clientX - oldX);
|
|
|
+ const maxWidth = contentBoxWidth.value;
|
|
|
+
|
|
|
+ let height = oldHeight - (oEv.clientY - oldY);
|
|
|
+ const maxHeight = contentBoxHeight.value - oldTop;
|
|
|
+
|
|
|
+ let left = oldLeft + (oEv.clientX - oldX);
|
|
|
+ let top = oldTop + (oEv.clientY - oldY);
|
|
|
+
|
|
|
+ if (width < minWidth) {
|
|
|
+ width = minWidth;
|
|
|
+ }
|
|
|
+ if (width > maxWidth) {
|
|
|
+ width = maxWidth;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (height < minHeight) {
|
|
|
+ height = minHeight;
|
|
|
+ }
|
|
|
+ if (height > maxHeight) {
|
|
|
+ height = maxHeight;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (oldLeft == 0 && oldTop == 0) {
|
|
|
+ // 坐标:left = 0,top = 0
|
|
|
+
|
|
|
+ if (width == minWidth && height == minHeight) {
|
|
|
+ // 宽高 = 最小值,left = 最小宽度,top = 最小高度
|
|
|
+ left = minWidth;
|
|
|
+ top = minHeight;
|
|
|
+ } else if (width == minWidth && height > minHeight) {
|
|
|
+ // 宽 = 最小值,高 > 最小值,left = 最小宽度,top = 不予处理
|
|
|
+ left = minWidth;
|
|
|
+ } else if (width > minWidth && height == minHeight) {
|
|
|
+ // 宽 > 最小值,高 = 最小值,left = 不予处理,top = 最小高度
|
|
|
+ top = minHeight;
|
|
|
+ } else if (width > minWidth && height > minHeight) {
|
|
|
+ // 宽 > 最小值,高 > 最小值,left = 不予处理,top = 不予处理
|
|
|
+ }
|
|
|
+ } else if (oldLeft == 0 && oldTop > 0) {
|
|
|
+ // 坐标:left = 0,top > 0
|
|
|
+
|
|
|
+ if (width == minWidth && height == minHeight) {
|
|
|
+ // 宽高 = 最小值,left = 最小宽度,top = 元素上偏移位置
|
|
|
+ left = minWidth;
|
|
|
+ top = box.offsetTop;
|
|
|
+ } else if (width == minWidth && height > minHeight) {
|
|
|
+ // 宽 = 最小值,高 > 最小值,left = 最小宽度,top = 元素上偏移位置
|
|
|
+ left = minWidth;
|
|
|
+ top = box.offsetTop;
|
|
|
+ } else if (width > minWidth && height == minHeight) {
|
|
|
+ // 宽 > 最小值,高 = 最小值,left = 不予处理,top = 元素上偏移位置
|
|
|
+ top = box.offsetTop;
|
|
|
+ } else if (width > minWidth && height > minHeight) {
|
|
|
+ // 宽 > 最小值,高 > 最小值,left = 不予处理,top = 不予处理
|
|
|
+ }
|
|
|
+ } else if (oldLeft > 0 && oldTop == 0) {
|
|
|
+ // 坐标:left > 0,top = 0
|
|
|
+
|
|
|
+ if (width == minWidth && height == minHeight) {
|
|
|
+ // 宽高 = 最小值,left = 元素左偏移位置,top = 元素上偏移位置
|
|
|
+ left = box.offsetLeft;
|
|
|
+ top = box.offsetTop;
|
|
|
+ } else if (width == minWidth && height > minHeight) {
|
|
|
+ // 宽 = 最小值,高 > 最小值,left = 元素左偏移位置,top = 0
|
|
|
+ left = box.offsetLeft;
|
|
|
+ top = 0;
|
|
|
+ } else if (width > minWidth && height == minHeight) {
|
|
|
+ // 宽 > 最小值,高 = 最小值,left = 不予处理,top = 元素上偏移位置
|
|
|
+ top = box.offsetTop;
|
|
|
+ } else if (width > minWidth && height > minHeight) {
|
|
|
+ // 宽 > 最小值,高 > 最小值,left = 不予处理,top = 不予处理
|
|
|
+ }
|
|
|
+ } else if (oldLeft > 0 && oldTop > 0) {
|
|
|
+ // 坐标:left > 0,top > 0
|
|
|
+
|
|
|
+ if (width == minWidth && height == minHeight) {
|
|
|
+ // 宽高 = 最小值,left = 元素左偏移位置,top = 元素上偏移位置
|
|
|
+ left = box.offsetLeft;
|
|
|
+ top = box.offsetTop;
|
|
|
+ } else if (width == minWidth && height > minHeight) {
|
|
|
+ // 宽 = 最小值,高 > 最小值,left = 元素左偏移位置,top = 元素上偏移位置
|
|
|
+ left = box.offsetLeft;
|
|
|
+ top = box.offsetTop;
|
|
|
+ } else if (width > minWidth && height == minHeight) {
|
|
|
+ // 宽 > 最小值,高 = 最小值,left = 不予处理,top = 元素上偏移位置
|
|
|
+ top = box.offsetTop;
|
|
|
+ } else if (width > minWidth && height > minHeight) {
|
|
|
+ // 宽 > 最小值,高 > 最小值,left = 不予处理,top = 不予处理
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 左上宽
|
|
|
+ if (left < 0) {
|
|
|
+ left = 0;
|
|
|
+ width = oldWidth - (oEv.clientX - oldX) + (oldLeft + (oEv.clientX - oldX));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 左上 高
|
|
|
+ if (top < 0) {
|
|
|
+ top = 0;
|
|
|
+ height = oldTop + (oEv.clientY - oldY) + (oldHeight - (oEv.clientY - oldY));
|
|
|
+ }
|
|
|
+
|
|
|
+ box.style.width = width + 'px';
|
|
|
+ box.style.height = height + 'px';
|
|
|
+ box.style.left = left + 'px';
|
|
|
+ box.style.top = top + 'px';
|
|
|
+ } else if (className == 'box2') {
|
|
|
+ // 右上角
|
|
|
+
|
|
|
+ let width = oldWidth + (oEv.clientX - oldX);
|
|
|
+ const maxWidth = contentBoxWidth.value - oldLeft;
|
|
|
+
|
|
|
+ let height = oldHeight - (oEv.clientY - oldY);
|
|
|
+ const maxHeight = contentBoxHeight.value - oldTop;
|
|
|
+
|
|
|
+ let top = oldTop + (oEv.clientY - oldY);
|
|
|
+
|
|
|
+ if (width < minWidth) {
|
|
|
+ width = minWidth;
|
|
|
+ }
|
|
|
+ if (width > maxWidth) {
|
|
|
+ width = maxWidth;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (height < minHeight) {
|
|
|
+ height = minHeight;
|
|
|
+ }
|
|
|
+ if (height > maxHeight) {
|
|
|
+ height = maxHeight;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (oldLeft == 0 && oldTop == 0) {
|
|
|
+ // 坐标:left = 0,top = 0
|
|
|
+
|
|
|
+ if (width == minWidth && height == minHeight) {
|
|
|
+ // 宽高 = 最小值,top = 最小高度
|
|
|
+ top = minHeight;
|
|
|
+ } else if (width == minWidth && height > minHeight) {
|
|
|
+ // 宽 = 最小值,高 > 最小值,不予处理
|
|
|
+ } else if (width > minWidth && height == minHeight) {
|
|
|
+ // 宽 > 最小值,高 = 最小值,top = 最小高度
|
|
|
+ top = minHeight;
|
|
|
+ } else if (width > minWidth && height > minHeight) {
|
|
|
+ // 宽 > 最小值,高 > 最小值,不予处理
|
|
|
+ }
|
|
|
+ } else if (oldLeft == 0 && oldTop > 0) {
|
|
|
+ // 坐标:left = 0,top > 0
|
|
|
+
|
|
|
+ if (width == minWidth && height == minHeight) {
|
|
|
+ // 宽高 = 最小值,top = 元素上偏移位置
|
|
|
+ top = box.offsetTop;
|
|
|
+ } else if (width == minWidth && height > minHeight) {
|
|
|
+ // 宽 = 最小值,高 > 最小值,top = 元素上偏移位置
|
|
|
+ top = box.offsetTop;
|
|
|
+ } else if (width > minWidth && height == minHeight) {
|
|
|
+ // 宽 > 最小值,高 = 最小值,top = 元素上偏移位置
|
|
|
+ top = box.offsetTop;
|
|
|
+ } else if (width > minWidth && height > minHeight) {
|
|
|
+ // 宽 > 最小值,高 > 最小值,不予处理
|
|
|
+ }
|
|
|
+ } else if (oldLeft > 0 && oldTop == 0) {
|
|
|
+ // 坐标:left = 0,top = 0
|
|
|
+
|
|
|
+ if (width == minWidth && height == minHeight) {
|
|
|
+ // 宽高 = 最小值,top = 元素上偏移位置
|
|
|
+ top = box.offsetTop;
|
|
|
+ } else if (width == minWidth && height > minHeight) {
|
|
|
+ // 宽 = 最小值,高 > 最小值,top = 0
|
|
|
+ top = 0;
|
|
|
+ } else if (width > minWidth && height == minHeight) {
|
|
|
+ // 宽 > 最小值,高 = 最小值,top = 元素上偏移位置
|
|
|
+ top = box.offsetTop;
|
|
|
+ } else if (width > minWidth && height > minHeight) {
|
|
|
+ // 宽 > 最小值,高 > 最小值,不予处理
|
|
|
+ }
|
|
|
+ } else if (oldLeft > 0 && oldTop > 0) {
|
|
|
+ // 坐标:left > 0,top > 0
|
|
|
+
|
|
|
+ if (width == minWidth && height == minHeight) {
|
|
|
+ // 宽高 = 最小值,top = 元素上偏移位置
|
|
|
+ top = box.offsetTop;
|
|
|
+ } else if (width == minWidth && height > minHeight) {
|
|
|
+ // 宽 = 最小值,高 > 最小值,top = 元素上偏移位置
|
|
|
+ top = box.offsetTop;
|
|
|
+ } else if (width > minWidth && height == minHeight) {
|
|
|
+ // 宽 > 最小值,高 = 最小值,top = 元素上偏移位置
|
|
|
+ top = box.offsetTop;
|
|
|
+ } else if (width > minWidth && height > minHeight) {
|
|
|
+ // 宽 > 最小值,高 > 最小值,不予处理
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 右上高
|
|
|
+ if (top < 0) {
|
|
|
+ top = 0;
|
|
|
+ height = oldTop + (oEv.clientY - oldY) + (oldHeight - (oEv.clientY - oldY));
|
|
|
+ }
|
|
|
+
|
|
|
+ box.style.width = width + 'px';
|
|
|
+ box.style.height = height + 'px';
|
|
|
+ box.style.top = top + 'px';
|
|
|
+ } else if (className == 'box3') {
|
|
|
+ // 左下角
|
|
|
+
|
|
|
+ let width = oldWidth - (oEv.clientX - oldX);
|
|
|
+ const maxWidth = contentBoxWidth.value;
|
|
|
+
|
|
|
+ let height = oldHeight + (oEv.clientY - oldY);
|
|
|
+ const maxHeight = contentBoxHeight.value - oldTop;
|
|
|
+
|
|
|
+ let left = oldLeft + (oEv.clientX - oldX);
|
|
|
+
|
|
|
+ if (width < minWidth) {
|
|
|
+ width = minWidth;
|
|
|
+ }
|
|
|
+ if (width > maxWidth) {
|
|
|
+ width = maxWidth;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (height < minHeight) {
|
|
|
+ height = minHeight;
|
|
|
+ }
|
|
|
+ if (height > maxHeight) {
|
|
|
+ height = maxHeight;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (oldLeft == 0 && oldTop == 0) {
|
|
|
+ // 坐标:left = 0,top = 0
|
|
|
+
|
|
|
+ if (width == minWidth && height == minHeight) {
|
|
|
+ // 宽高 = 最小值,left = 最小宽度
|
|
|
+ left = minWidth;
|
|
|
+ } else if (width == minWidth && height > minHeight) {
|
|
|
+ // 宽 = 最小值,高 > 最小值,left = 最小宽度
|
|
|
+ left = minWidth;
|
|
|
+ } else if (width > minWidth && height == minHeight) {
|
|
|
+ // 宽 > 最小值,高 = 最小值,不予处理
|
|
|
+ } else if (width > minWidth && height > minHeight) {
|
|
|
+ // 宽 > 最小值,高 > 最小值,不予处理
|
|
|
+ }
|
|
|
+ } else if (oldLeft == 0 && oldTop > 0) {
|
|
|
+ // 坐标:left = 0,top > 0
|
|
|
+
|
|
|
+ if (width == minWidth && height == minHeight) {
|
|
|
+ // 宽高 = 最小值,left = 最小宽度
|
|
|
+ left = minWidth;
|
|
|
+ } else if (width == minWidth && height > minHeight) {
|
|
|
+ // 宽 = 最小值,高 > 最小值,left = 最小宽度
|
|
|
+ left = minWidth;
|
|
|
+ } else if (width > minWidth && height == minHeight) {
|
|
|
+ // 宽 > 最小值,高 = 最小值,不予处理
|
|
|
+ } else if (width > minWidth && height > minHeight) {
|
|
|
+ // 宽 > 最小值,高 > 最小值,不予处理
|
|
|
+ }
|
|
|
+ } else if (oldLeft > 0 && oldTop == 0) {
|
|
|
+ // 坐标:left > 0,top = 0
|
|
|
+
|
|
|
+ if (width == minWidth && height == minHeight) {
|
|
|
+ // 宽高 = 最小值,left = 元素左偏移位置
|
|
|
+ left = box.offsetLeft;
|
|
|
+ } else if (width == minWidth && height > minHeight) {
|
|
|
+ // 宽 = 最小值,高 > 最小值,left = 元素左偏移位置
|
|
|
+ left = box.offsetLeft;
|
|
|
+ } else if (width > minWidth && height == minHeight) {
|
|
|
+ // 宽 > 最小值,高 = 最小值,不予处理
|
|
|
+ } else if (width > minWidth && height > minHeight) {
|
|
|
+ // 宽 > 最小值,高 > 最小值,不予处理
|
|
|
+ }
|
|
|
+ } else if (oldLeft > 0 && oldTop > 0) {
|
|
|
+ // 坐标:left > 0,top > 0
|
|
|
+
|
|
|
+ if (width == minWidth && height == minHeight) {
|
|
|
+ // 宽高 = 最小值,left = 元素左偏移位置
|
|
|
+ left = box.offsetLeft;
|
|
|
+ } else if (width == minWidth && height > minHeight) {
|
|
|
+ // 宽 = 最小值,高 > 最小值,left = 元素左偏移位置
|
|
|
+ left = box.offsetLeft;
|
|
|
+ } else if (width > minWidth && height == minHeight) {
|
|
|
+ // 宽 > 最小值,高 = 最小值,不予处理
|
|
|
+ } else if (width > minWidth && height > minHeight) {
|
|
|
+ // 宽 > 最小值,高 > 最小值,不予处理
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (left < 0) {
|
|
|
+ left = 0;
|
|
|
+ width = oldWidth - (oEv.clientX - oldX) + (oldLeft + (oEv.clientX - oldX));
|
|
|
+ }
|
|
|
+
|
|
|
+ box.style.width = width + 'px';
|
|
|
+ box.style.height = height + 'px';
|
|
|
+ box.style.left = left + 'px';
|
|
|
+ } else if (className == 'box4') {
|
|
|
+ // 右下角
|
|
|
+
|
|
|
+ let width = oldWidth + (oEv.clientX - oldX);
|
|
|
+ const maxWidth = contentBoxWidth.value - oldLeft;
|
|
|
+
|
|
|
+ let height = oldHeight + (oEv.clientY - oldY);
|
|
|
+ const maxHeight = contentBoxHeight.value - oldTop;
|
|
|
+
|
|
|
+ if (width < minWidth) {
|
|
|
+ width = minWidth;
|
|
|
+ }
|
|
|
+ if (width > maxWidth) {
|
|
|
+ width = maxWidth;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (height < minHeight) {
|
|
|
+ height = minHeight;
|
|
|
+ }
|
|
|
+ if (height > maxHeight) {
|
|
|
+ height = maxHeight;
|
|
|
+ }
|
|
|
+
|
|
|
+ box.style.width = width + 'px';
|
|
|
+ box.style.height = height + 'px';
|
|
|
+ }
|
|
|
+
|
|
|
+ dragBoxArr[index].left = box.offsetLeft;
|
|
|
+ dragBoxArr[index].top = box.offsetTop;
|
|
|
+ dragBoxArr[index].width = box.offsetWidth;
|
|
|
+ dragBoxArr[index].height = box.offsetHeight;
|
|
|
+ dragBoxArr[index].unit = 'px';
|
|
|
+ };
|
|
|
+
|
|
|
+ // 鼠标抬起时
|
|
|
+ document.onmouseup = function () {
|
|
|
+ document.onmousemove = null;
|
|
|
+ document.onmouseup = null;
|
|
|
+ };
|
|
|
+};
|
|
|
+
|
|
|
+const show = () => {
|
|
|
+ // 每次打开时赋值
|
|
|
+ if (!value.value.imageUrl) {
|
|
|
+ ElMessage({
|
|
|
+ type: 'warning',
|
|
|
+ message: '请上传图片'
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计算图片比例
|
|
|
+ imgRatio.value = value.value.imgHeight / value.value.imgWidth;
|
|
|
+
|
|
|
+ // 根据图片比例,调整图片高度
|
|
|
+ contentBoxHeight.value = Math.floor(contentBoxWidth.value * imgRatio.value);
|
|
|
+
|
|
|
+ areaWidth.value = Math.floor(areaRadio.value * contentBoxHeight.value);
|
|
|
+ areaHeight.value = areaWidth.value;
|
|
|
+ areaNum.value = Math.floor(contentBoxWidth.value / areaWidth.value);
|
|
|
+
|
|
|
+ if (Object.keys(value.value.heatMapData).length) {
|
|
|
+ dragBoxArr.splice(0, dragBoxArr.length, ...value.value.heatMapData);
|
|
|
+ } else {
|
|
|
+ dragBoxArr.splice(0, dragBoxArr.length);
|
|
|
+ addArea();
|
|
|
+ }
|
|
|
+ showDialog.value = true;
|
|
|
+};
|
|
|
+
|
|
|
+const save = () => {
|
|
|
+ let isOk = true;
|
|
|
+ for (let i = 0; i < dragBoxArr.length; i++) {
|
|
|
+ if (!dragBoxArr[i].link) {
|
|
|
+ ElMessage({
|
|
|
+ type: 'warning',
|
|
|
+ message: '请选择热区' + (i + 1) + '的链接地址'
|
|
|
+ });
|
|
|
+ isOk = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!isOk) return;
|
|
|
+
|
|
|
+ dragBoxArr.forEach((item: any, index: number) => {
|
|
|
+ const box: any = document.getElementById('box_' + index);
|
|
|
+ item.width = Number(((box.offsetWidth / contentBoxWidth.value) * 100).toFixed(2));
|
|
|
+ item.height = Number(((box.offsetHeight / contentBoxHeight.value) * 100).toFixed(2));
|
|
|
+ item.left = Number(((box.offsetLeft / contentBoxWidth.value) * 100).toFixed(2));
|
|
|
+ item.top = Number(((box.offsetTop / contentBoxHeight.value) * 100).toFixed(2));
|
|
|
+ item.unit = '%';
|
|
|
+ });
|
|
|
+
|
|
|
+ value.value.heatMapData = deepClone(dragBoxArr);
|
|
|
+
|
|
|
+ showDialog.value = false;
|
|
|
+};
|
|
|
+
|
|
|
+defineExpose({
|
|
|
+ showDialog
|
|
|
+});
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.area-box {
|
|
|
+ background-color: rgba(255, 255, 255, 0.7);
|
|
|
+}
|
|
|
+
|
|
|
+.hot-area-img-wrap {
|
|
|
+ // width: 1200px;
|
|
|
+
|
|
|
+ background-size: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.box1,
|
|
|
+.box2,
|
|
|
+.box3,
|
|
|
+.box4 {
|
|
|
+ width: 10px;
|
|
|
+ height: 10px;
|
|
|
+ background-color: #fff;
|
|
|
+ position: absolute;
|
|
|
+ border-radius: 50%;
|
|
|
+ border: 1px solid #333;
|
|
|
+}
|
|
|
+
|
|
|
+.box1 {
|
|
|
+ top: -5px;
|
|
|
+ left: -5px;
|
|
|
+ cursor: nw-resize;
|
|
|
+}
|
|
|
+
|
|
|
+.box2 {
|
|
|
+ top: -5px;
|
|
|
+ right: -5px;
|
|
|
+ cursor: ne-resize;
|
|
|
+}
|
|
|
+
|
|
|
+.box3 {
|
|
|
+ left: -5px;
|
|
|
+ bottom: -5px;
|
|
|
+ cursor: sw-resize;
|
|
|
+}
|
|
|
+
|
|
|
+.box4 {
|
|
|
+ bottom: -5px;
|
|
|
+ right: -5px;
|
|
|
+ cursor: se-resize;
|
|
|
+}
|
|
|
+</style>
|