本例实现的功能有
- 鼠标拖动可动态添加div区域(可多次添加),
- 鼠标拖动div的两侧来调整div的大小
- 鼠标拖动div可左右移动div的位置
父组件
<template>
<div class="wrap" id="wrap" ref="wrap"
@mousedown="startDrag">
<div id="drag" :style="{width: position.width + 'px', left: position.left + 'px'}" class="inner" v-show="isShow" />
<div>
<template v-for="(item, index ) in areaList">
<drag1 @mousedown.native="editGrid(item, index)" :style="{width: item.position.width + 'px', left: item.position.left + 'px'}" class="inner" v-model="item.position" />
</template>
</div>
</div>
</template>
<script setup>
import drag1 from './drag1.vue'
import { onMounted, reactive, ref, toRef, toRefs } from "vue";
let left = ref(0), width = ref(0), dragging = ref(false), areaList = reactive([])
let isShow = ref(true)
let position = reactive({})
let wrap = ref(null)
onMounted(() => {
init()
})
function init() {
let dom = wrap.value
dom.addEventListener('mousedown', start)
}
function startDrag(){
let dom = wrap.value
dom.addEventListener('mousedown', start)
}
function editGrid(item, index) {
let dom = wrap.value
dom.removeEventListener('mousedown', start)
document.removeEventListener('mousemove', drag)
document.removeEventListener("mouseup", stopDrag);
}
function start(event) {
dragging.value = true
position.left = event.offsetX
position.width = 0
document.addEventListener("mousemove", drag);
document.addEventListener("mouseup", stopDrag);
isShow.value = true
}
function drag(event) {
if(event.offsetX > 800) {
position.width = 800 - position.left
} else{
position.width = event.offsetX - position.left
}
}
function stopDrag() {
document.removeEventListener('mousemove', drag)
document.removeEventListener("mouseup", stopDrag);
let result = toRefs(position)
areaList.push({ position: { left: result.left.value, width: result.width.value } })
isShow.value = false
}
</script>
<style scoped>
.wrap {
position: relative;
width: 800px;
height: 100px;
border: 1px solid #000;
margin: 0 auto;
}
.inner {
background: rgba(0, 0, 0, 0.2);
height: 100%;
position: absolute;
}
</style>
子组件
<template>
<div class="resize" id="resize" ref="resize">
<div class="left resize-handle" ref="left"></div>
<div class="right resize-handle" ref="right"></div>
<slot></slot>
</div>
</template>
<script setup lang="ts">
import { inject, onMounted, reactive, ref, unref, watch } from "vue";
let resize = ref(null);
let left = ref(null)
let right = ref(null)
let $emit = defineEmits(['update: modelValue'])
const model = defineModel()
let message = inject('value')
let props = defineProps(['fun'])
onMounted(() => {
resize.value.style.width = model.value.width
resize.value.style.left = model.value.left
mousedown(); // 拖拽功能
handleResize()
});
function mousedown() {
resize.value.addEventListener("mousedown", startDrag);
}
// 拖拽功能
function startDrag(event) {
let dragElement = resize.value
event.preventDefault();
const currentHandle = event.target;
const isResizeHandle = currentHandle.className.includes("resize-handle");
if (isResizeHandle) return;
const startX = event.clientX;
const startY = event.clientY;
const startLeft = dragElement.offsetLeft;
const startTop = dragElement.offsetTop;
const width = dragElement.offsetWidth
document.addEventListener("mousemove", drag);
document.addEventListener("mouseup", stopDrag);
let newLeft = startLeft
function drag(event) {
const dx = event.clientX - startX;
const dy = event.clientY - startY;
newLeft = startLeft + dx;
const newTop = startTop + dy;
dragElement.style.left = newLeft + "px";
// dragElement.style.top = newTop + "px";
}
function stopDrag() {
document.removeEventListener("mousemove", drag);
document.removeEventListener("mouseup", stopDrag);
// $emit('update: modelValue',{left: newLeft + 'px', width: width + 'px'})
model.value = {left: newLeft+'px', width: width+'px'}
}
}
// 缩放功能
function handleResize() {
let domLeft = left.value
let domRight = right.value
domLeft.addEventListener('mousedown', (event:any) =>startResize(event,'left'))
domRight.addEventListener('mousedown', (event:any) => startResize(event,'right'))
}
function startResize(event,type){
event.preventDefault();
let dragElement = resize.value
const startX = event.clientX;
const startWidth = dragElement.offsetWidth;
const startLeft = dragElement.offsetLeft;
document.addEventListener("mousemove", handleResize);
document.addEventListener("mouseup", stopResize);
var width, left
function handleResize(event){
const dx = event.clientX - startX;
width = startWidth, left=startLeft
if(type === 'left'){
width = startWidth - dx;
left = startLeft + dx;
}
if(type === 'right'){
width = startWidth + dx;
left = startLeft
}
dragElement.style.width = width + 'px';
dragElement.style.left = left + 'px';
}
function stopResize(){
if(width < 30) {
return alert('宽度不能小于30像素')
}
document.removeEventListener("mousemove", handleResize);
document.removeEventListener("mouseup", stopResize);
model.value = {left: left+'px', width: width+'px'}
}
}
</script>
<style scoped>
.resize {
width: 120px;
height: 200px;
background: rgba(0, 0, 0, 0.2);
position: absolute;
top: 0;
}
.resize .left {
position: absolute;
height: 100%;
border-left: 1px dashed #000;
left: 0;
width: 10px;
cursor: pointer;
}
.resize .right {
position: absolute;
height: 100%;
border-left: 1px dashed #000;
right: -10px;
width: 10px;
cursor: pointer;
}
</style>