实现功能:
设置多个元素中,元素的拖拽,拉拽边缘实现元素缩放,设置选中元素始终在最顶层
代码:
<template>
<div id="pageBox" @mousewheel="mouseWheel" :style="{ width: imgWidth, height: imgHeight }">
设备宽度
<div v-for="(item,index) in list" :key="index" class="container" :style="select===index ? selectStyle : noselect(index)" :id="'select'+index" @click="clickBox(item, index)">
点击{{index}}
<div class="point top" v-if="select===index"></div>
<div class="point left" v-if="select===index"></div>
<div class="point right" v-if="select===index"></div>
<div class="point bottom" v-if="select===index"></div>
<div class="point top-left" v-if="select===index"></div>
<div class="point top-right" v-if="select===index"></div>
<div class="point bottom-left" v-if="select===index"></div>
<div class="point bottom-right" v-if="select===index"></div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
list: [1, 2, 3, 4, 5],
// 页面对象
pageObj: null,
// 缩放元素
zoomBox: null,
// 鼠标按下时的坐标,并在修改尺寸时保存上一个鼠标的位置
clientX: 0,
clientY: 0,
// div可修改的最小宽高
minW: 20,
minH: 20,
// 鼠标按下时的位置,使用n、s、w、e表示
direc: '',
select: '',
selectStyle: {
border: '1px dashed #19be6b',
// zIndex: 100,
cursor: 'pointer'
},
// 拖拽
moveType: '',
disX: 0,
disY: 0,
imgWidth: "500px",
imgHeight: "500px"
}
},
computed: {
// 未选择的元素保持原有的z-indx层级
noselect: function() {
return function(index) {
this.$nextTick(() => {
// dom元素更新后执行,因此这里能正确打印更改之后的值
let obj = document.getElementById('select' + index)
let sty = {
zIndex: obj.style.zIndex
}
return sty
})
return ''
}
}
},
created() {},
mounted() {
this.pageObj = document.getElementById('pageBox')
},
methods: {
// 鼠标滚轮
mouseWheel(e) {
const img = document.getElementById("pageBox")
this.imgWidth = img.offsetWidth || img.width || img.clientWidth
this.imgHeight = img.offsetHeight || img.height || img.clientHeight
if (e.deltaY > 0) {
console.log("鼠标向下滚动,图片缩小")
this.imgWidth = `${this.imgWidth - 10}px`
this.imgHeight = `${this.imgHeight - 10}px`
} else {
console.log("鼠标向上滚动,图片放大")
this.imgWidth = `${this.imgWidth + 10}px`
this.imgHeight = `${this.imgHeight + 10}px`
}
},
// 点击元素
clickBox(item, index) {
// 需要调整尺寸的div
this.zoomBox = document.getElementById('select' + index)
this.select = index
// 设置元素的层级,当前点击的层级在最大层级上+1
let zindex = this.setIndex()
this.zoomBox.style.zIndex = zindex + 1
// 鼠标按下事件
this.zoomBox.onmousedown = this.zoomDown
// 页面监听移动事件
this.pageObj.onmousemove = this.mouseMove
// 鼠标松开事件
this.pageObj.onmouseup = this.zoomUp
},
// 设置元素浮层
setIndex() {
// 获取最大层级的元素z-index
let max = 0
for (let i = 0; i < this.list.length; i++) {
let obj = document.getElementById('select' + i)
if (obj.style.zIndex) {
if (max < obj.style.zIndex) {
max = parseInt(obj.style.zIndex)
}
}
}
return max
},
// 鼠标按下
zoomDown(e) {
// 去除鼠标默认事件
document.oncontextmenu = function(e) {
e.preventDefault()
}
// 阻止冒泡
e.stopPropagation()
let oEvent = e || event
let d = this.getDirection(oEvent)
this.zoomBox.onmouseup = this.boxUp
// 当位置为四个边和四个角时才开启尺寸修改
if (d === 'move' || d === '') {
this.disX = oEvent.clientX - this.zoomBox.offsetLeft
this.disY = oEvent.clientY - this.zoomBox.offsetTop
this.moveType = 'drag'
console.log('拖拽按下', this.disX, oEvent.clientX, this.zoomBox.offsetLeft)
} else {
this.moveType = 'resizeable'
this.direc = d
this.clientX = e.clientX
this.clientY = e.clientY
console.log('缩放按下')
}
},
// 鼠标移动
mouseMove(e) {
let oEvent = e || event
let d = this.getDirection(oEvent)
let cursor = ''
if (d === 'move' || d === '') {
// 默认移动鼠标样式
cursor = 'move'
} else {
// 缩放鼠标样式
cursor = d + '-resize'
}
// 修改鼠标显示效果
this.zoomBox.style.cursor = cursor
if (this.moveType === 'resizeable') {
// 缩放
this.zoomBox.style.cursor = this.direc + '-resize'
this.zoomMove(oEvent)
} else if (this.moveType === 'drag') {
this.zoomBox.style.cursor = 'move'
this.eleMousemove(oEvent)
}
},
// 缩放移动
zoomMove(e) {
// 当开启尺寸修改时,鼠标移动会修改div尺寸
if (this.moveType === 'resizeable') {
// 鼠标按下的位置在右边,修改宽度
if (this.direc.indexOf('e') !== -1) {
this.zoomBox.style.width = Math.max(this.minW, this.zoomBox.offsetWidth + (e.clientX - this.clientX)) + 'px'
this.clientX = e.clientX
}
// 鼠标按下的位置在上部,修改高度
if (this.direc.indexOf('n') !== -1) {
this.zoomBox.style.height = Math.max(this.minH, this.zoomBox.offsetHeight + (this.clientY - e.clientY)) + 'px'
this.clientY = e.clientY
}
// 鼠标按下的位置在底部,修改高度
if (this.direc.indexOf('s') !== -1) {
this.zoomBox.style.height = Math.max(this.minH, this.zoomBox.offsetHeight + (e.clientY - this.clientY)) + 'px'
this.clientY = e.clientY
}
// 鼠标按下的位置在左边,修改宽度
if (this.direc.indexOf('w') !== -1) {
this.zoomBox.style.width = Math.max(this.minW, this.zoomBox.offsetWidth + (this.clientX - e.clientX)) + 'px'
this.clientX = e.clientX
}
}
},
// 鼠标拖拽移动
eleMousemove(oEvent) {
// 加入该判断拖拽更流畅
if (this.moveType === 'drag') {
// 计算点击元素到父级元素的定位top,left距离
let l = oEvent.clientX - this.disX
let t = oEvent.clientY - this.disY
/** 限定拖拽范围,限定拖拽元素在指定的范围内 */
// 限定左边界和上边界
if (l < 0) {
l = 0
}
if (t < 0) {
t = 0
}
// 限定右边界的距离(当l=父元素宽-子元素宽时,刚好子元素放在父元素最右边)
if (l > this.pageObj.clientWidth - this.zoomBox.clientWidth) {
l = this.pageObj.clientWidth - this.zoomBox.clientWidth
}
// 限定下边界的距离(当t=父元素高-子元素高时,刚好子元素放在父元素最下边)
if (t > this.pageObj.clientHeight - this.zoomBox.clientHeight) {
t = this.pageObj.clientHeight - this.zoomBox.clientHeight
}
this.zoomBox.style.left = l + 'px'
this.zoomBox.style.top = t + 'px'
}
},
// 操作元素的鼠标抬起事件
boxUp(e) {
// 阻止冒泡
e.stopPropagation()
let oEvent = e || event
console.log('box鼠标抬起')
// 当前选择对象鼠标抬起事件
this.moveType = ''
this.zoomBox.onmousedown = null
this.pageObj.onmousemove = null
this.pageObj.onmouseup = null
},
// 操作元素的父级元素鼠标抬起事件
zoomUp(e) {
// 阻止冒泡
e.stopPropagation()
let oEvent = e || event
console.log('父级鼠标抬起')
// 点击当前选择的任意位置鼠标抬起事件,选择状态清空
this.select = ''
this.moveType = ''
this.zoomBox.onmousedown = null
this.zoomBox.onmouseup = null
this.pageObj.onmousemove = null
this.pageObj.onmouseup = null
},
// 获取鼠标所在div的位置
getDirection(ev) {
let dir = ''
if (ev.target.className.indexOf('top') >= 0) {
dir += 'n'
} else if (ev.target.className.indexOf('bottom') >= 0) {
dir += 's'
}
if (ev.target.className.indexOf('left') >= 0) {
dir += 'w'
} else if (ev.target.className.indexOf('right') >= 0) {
dir += 'e'
}
if (ev.target.className === '') {
dir = 'move'
}
return dir
}
}
}
</script>
<style lang="less" scoped>
#pageBox{
border:1px solid red;
width:800px;
height:600px;
position: relative;
color:#fff;
}
.container {
width: 150px;
height: 150px;
box-sizing: border-box;
position: absolute;
cursor: default;
background: #757575;
}
.point{
width: 10px;
height: 10px;
border-radius: 2px;
border: 1px solid #19be6b;
position: absolute;
}
.top{
top: -5px;
left: 50%;
}
.bottom{
bottom: -5px;
left: 50%;
}
.left{
left: -5px;
top: 50%;
}
.right{
right: -5px;
top: 50%;
}
.top-left{
top: -5px;
left: -5px;
}
.bottom-left{
bottom: -5px;
left: -5px;
}
.top-right{
top: -5px;
right: -5px;
}
.bottom-right{
bottom: -5px;
right: -5px;
}
</style>
解决上文中的拖拽缩放时左边缩放宽高不正确的问题,仅供参考
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
* {
margin: 0;
padding: 0
}
.box {
width: 300px;
height: 300px;
position: absolute;
top: 100px;
left: 100px;
}
/*四边*/
.box .t,
.box .b,
.box .l,
.box .r {
position: absolute;
z-index: 1;
background: #666;
}
.box .l,
.box .r {
width: 5px;
height: 100%;
cursor: col-resize;
}
.box .t,
.box .b {
width: 100%;
height: 5px;
cursor: row-resize;
}
.box .t {
top: 0;
}
.box .b {
bottom: 0;
}
.box .l {
left: 0;
}
.box .r {
right: 0;
}
/*四角*/
.box .tl,
.box .bl,
.box .br,
.box .tr {
width: 20px;
height: 20px;
position: absolute;
background: #fff;
border:1px solid #666;
z-index: 2;
cursor: nwse-resize
}
.box .tl,
.box .bl {
left: -5px;
}
.box .tr,
.box .br {
right: -5px;
}
.box .br,
.box .bl {
bottom: -5px;
}
.box .tl,
.box .tr {
top: -5px;
}
.box .tr,
.box .bl {
cursor: nesw-resize;
}
/*内核*/
.inner {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<!-- 将边线的缩放也加了 -->
<div class="box" id="odiv">
<span class="r"></span>
<span class="l"></span>
<span class="t"></span>
<span class="b"></span>
<span class="br"></span>
<span class="bl"></span>
<span class="tr"></span>
<span class="tl"></span>
<div class="inner"></div>
</div>
<script>
window.onload = function () {
var oDiv = document.getElementsByTagName('div')[0];
oDiv.style.width = '500px';
var aSpan = oDiv.getElementsByTagName('span');
for (var i = 0; i < aSpan.length; i++) {
dragFn(aSpan[i]);
}
function dragFn(obj) {
obj.onmousedown = function (ev) {
var oEv = ev || event;
oEv.stopPropagation();
// 元素的宽高
var oldWidth = oDiv.offsetWidth;
var oldHeight = oDiv.offsetHeight;
// 当前边框元素鼠标点击到浏览器的距离
var oldX = oEv.clientX;
var oldY = oEv.clientY;
// 当前点击元素到最近父元素的偏移距离
var oldLeft = oDiv.offsetLeft;
var oldTop = oDiv.offsetTop;
document.onmousemove = function (ev) {
var oEv = ev || event;
// 居上面的距离
let disY = (oldTop + (oEv.clientY - oldY)),
// 鼠标点击到浏览器距离
disX = (oldLeft + (oEv.clientX - oldLeft));
if(disX>oldLeft+oldWidth){
// 距离父元素的距离不能小于:距离父元素距离+自身宽高
disX=oldLeft+oldWidth
}
if(disY>oldTop+oldHeight){
disY=oldTop+oldHeight
}
// 左上角
if (obj.className == 'tl') {
// 自身宽高=原来宽高加(或者减去)缩放的宽高
oDiv.style.width = oldWidth - (oEv.clientX - oldX) + 'px';
oDiv.style.height = oldHeight - (oEv.clientY - oldY) + 'px';
// 定位=距离父级元素的偏移距离
oDiv.style.left = disX + 'px';
oDiv.style.top = disY + 'px';
}
// 左下角
else if (obj.className == 'bl') {
oDiv.style.width = oldWidth - (oEv.clientX - oldX) + 'px';
oDiv.style.height = oldHeight + (oEv.clientY - oldY) + 'px';
oDiv.style.left = disX + 'px';
// oDiv.style.bottom = oldTop + (oEv.clientY + oldY) + 'px';
console.log('左下角', oDiv.style.bottom, oldTop, oEv.clientY, oldY)
}
// 右上角
else if (obj.className == 'tr') {
oDiv.style.width = oldWidth + (oEv.clientX - oldX) + 'px';
oDiv.style.height = oldHeight - (oEv.clientY - oldY) + 'px';
oDiv.style.right = oldLeft - (oEv.clientX - oldX) + 'px';
oDiv.style.top = disY + 'px';
}
// 右下角
else if (obj.className == 'br') {
oDiv.style.width = oldWidth + (oEv.clientX - oldX) + 'px';
oDiv.style.height = oldHeight + (oEv.clientY - oldY) + 'px';
oDiv.style.right = oldLeft - (oEv.clientX - oldX) + 'px';
oDiv.style.bottom = oldTop + (oEv.clientY + oldY) + 'px';
}
else if (obj.className == 't') {
oDiv.style.height = oldHeight - (oEv.clientY - oldY) + 'px';
oDiv.style.top = disY + 'px';
}
else if (obj.className == 'b') {
oDiv.style.height = oldHeight + (oEv.clientY - oldY) + 'px';
oDiv.style.bottom = disY + 'px';
}
else if (obj.className == 'l') {
oDiv.style.height = oldHeight + 'px';
oDiv.style.width = oldWidth - (oEv.clientX - oldX) + 'px';
oDiv.style.left = disX + 'px';
}
else if (obj.className == 'r') {
oDiv.style.height = oldHeight + 'px';
oDiv.style.width = oldWidth + (oEv.clientX - oldX) + 'px';
oDiv.style.right = disX + 'px';
}
};
document.onmouseup = function () {
document.onmousemove = null;
};
return false;
};
}
document.getElementById("odiv").onmousedown = function (ev) {
var oevent = ev || event;
oevent.preventDefault();
var distanceX = oevent.clientX - oDiv.offsetLeft;
var distanceY = oevent.clientY - oDiv.offsetTop;
document.onmousemove = function (ev) {
var oevent = ev || event;
oDiv.style.left = oevent.clientX - distanceX + 'px';
oDiv.style.top = oevent.clientY - distanceY + 'px';
};
document.onmouseup = function () {
document.onmousemove = null;
document.onmouseup = null;
};
}
};
</script>
</body>
</html>