一,演示项目的代码地址:
https://gitee.com/liuhongdi/move
二,编写代码:
Home.vue
<template>
<div class="main" >
<div id="preview" style="float:left;background:url(/static/img/mao.jpeg);background-size:640px;width: 640px; height: 1290px; position: relative;background-color:#FF0004;"
@mousedown="drawBegin($event)" @mousemove="drawMove($event)" @mouseup="drawEnd($event)">
</div>
</div>
</template>
<script>
export default {
name: "Home",
setup() {
//let objX
let objX=null;
let objY=null;
let setid=100;
let isCDown = false;
let curSetId = 0;
function getOffsetTop(obj){
var tmp = obj.offsetTop;
var val = obj.offsetParent;
while(val != null){
tmp += val.offsetTop;
val = val.offsetParent;
}
return tmp;
}
function getOffsetLeft(obj){
var tmp = obj.offsetLeft;
var val = obj.offsetParent;
while(val != null){
tmp += val.offsetLeft;
val = val.offsetParent;
}
return tmp;
}
//创建div,开始按下鼠标
const drawBegin = (event) => {
let id = event.srcElement.id;
//console.log('id:'+id);
if (id !== 'preview') {
return;
}
var objTop = getOffsetTop(document.getElementById("preview"));//对象x位置
var objLeft = getOffsetLeft(document.getElementById("preview"));//对象y位置
var scrollTop = window.pageYOffset || document.documentElement.scrollTop ||document.body.scrollTop || 0;
var mouseX = event.clientX+document.body.scrollLeft;//鼠标x位置
var mouseY = event.clientY+scrollTop;//鼠标y位置
//计算点击的相对位置
objX = mouseX-objLeft;
objY = mouseY-objTop;
//生成div
var oDiv = document.createElement('div');
oDiv.style.position='absolute';
oDiv.style.top=objY+'px';
oDiv.style.left=objX+'px';
oDiv.style.border='2px solid #000000';
oDiv.style.background='#ffffff';
oDiv.style.opacity=0.7;
oDiv.style.pointerEvents='none';
oDiv.dataset.origin_l = 0;
oDiv.dataset.origin_t = 0;
oDiv.dataset.origin_w = 0;
oDiv.dataset.origin_h = 0;
oDiv.id=setid;
oDiv.style.zIndex=setid;
document.getElementById("preview").appendChild(oDiv);
}
//创建div,移动中
const drawMove = (event) => {
//如果在缩放div
if (isCDown == true){
//var e = window.event || arguments.callee.caller.arguments[0];
let e = window.event;
let nx = e.clientX;
let ny = e.clientY;
//console.log('nx:'+nx+";ny:"+ny);
let nl = nx - cx;
let nt = ny - cy;
//console.log('nl:'+nl+";nt:"+nt);
let destw = parseInt(origin_w)+nl;
let desth = parseInt(origin_h)+nt;
//console.log('destw:'+destw+";desth:"+desth);
document.getElementById(curSetId).style.width = destw+"px";
document.getElementById(curSetId).style.height = desth+"px";
return;
}
//如果在移动div
if (isDown == true){
let e = window.event;
let nx = e.clientX;
let ny = e.clientY;
//计算移动后的左偏移量和顶部的偏移量
let nl = nx - (x - l);
let nt = ny - (y - t);
document.getElementById(curSetId).style.left = nl + 'px';
document.getElementById(curSetId).style.top = nt + 'px';
return;
}
//如果是在创建div时
if(objX!=null){
var objTop = getOffsetTop(document.getElementById("preview"));//对象x位置
var objLeft = getOffsetLeft(document.getElementById("preview"));//对象y位置
var scrollTop = window.pageYOffset || document.documentElement.scrollTop ||document.body.scrollTop || 0;
var mouseX = event.clientX+document.body.scrollLeft;//鼠标x位置
var mouseY = event.clientY+scrollTop;//鼠标y位置
//计算点击的相对位置
let movingX = mouseX-objLeft;
let movingY = mouseY-objTop;
if(movingX>=objX){
document.getElementById(setid).style.width=movingX-objX+'px';
}else{
document.getElementById(setid).style.left=movingX+'px';
document.getElementById(setid).style.width=objX-movingX+'px';
}
if(movingY>=objY){
document.getElementById(setid).style.height=movingY-objY+'px';
}else{
document.getElementById(setid).style.top=movingY+'px';
document.getElementById(setid).style.height=objY-movingY+'px';
}
}
}
//创建div,停止移动,完成
const drawEnd = (event) => {
console.log(event);
objX=objY=null;
if (isCDown == true){
return;
}
if (document.getElementById(setid) == null){
return;
}
if ('' == document.getElementById(setid).style.width || ''==document.getElementById(setid).style.height || '0px'==document.getElementById(setid).style.width || '0px'==document.getElementById(setid).style.height) {
document.getElementById(setid).parentElement.removeChild(document.getElementById(setid));
return;
}
document.getElementById(setid).innerHTML = "<div id='inner"+setid+"' style='pointer-events:auto;width:100%;height:100%;' onMouseDown='divmousedown("+setid+")' onMouseUp='divmouseup("+setid+",0)' onMouseMove='divmousemoving("+setid+")' ></div>";
document.getElementById(setid).innerHTML += '<div id="coor'+setid+'" class="coor" onMouseDown="coormousedown('+setid+')" onMouseMove="coormousemoving('+setid+')" onMouseUp="coormouseup('+setid+',0)"></div>';
document.getElementById(setid).innerHTML += '<div id="edit'+setid+'" class="edit" onclick="edit('+setid+',0)">E</div>';
document.getElementById(setid).innerHTML += '<div id="del'+setid+'" class="del" onclick="del('+setid+')">X</div>';
setid++;
}
//coor module for div resize---------------------------------------------------------
//移动div
let cx = 0;
let cy = 0;
let origin_w ;
let origin_h ;
//缩放div,coor按下鼠标,开始
const coormousedown = (setid) => {
if (isCDown == true) {
return false;
}
//计算点击的相对位置
var e = window.event ;
//获取x坐标和y坐标
cx = e.clientX;
cy = e.clientY;
//获取左部和顶部的偏移量
origin_w = document.getElementById(setid).style.width;
origin_h = document.getElementById(setid).style.height;
isCDown = true;
curSetId = setid;
}
//缩放div,coor松开
const coormouseup = (setid,content_id) => {
console.log('===============coormouseup');
isCDown = false;
var width = parseInt(document.getElementById(setid).style.width);
var height = parseInt(document.getElementById(setid).style.height);
if (content_id>0){
console.log("width:"+width+";origin_w:"+document.getElementById(setid).dataset.origin_w+";height:"+height+";origin_h:"+document.getElementById(setid).dataset.origin_h);
if (width == document.getElementById(setid).dataset.origin_w && height == document.getElementById(setid).dataset.origin_h){
//未修改大小,do nothing
} else {
document.getElementById(setid).dataset.origin_w = width;
document.getElementById(setid).dataset.origin_h = height;
}
}
}
//缩放div,coor移动中
const coormousemoving = (setid) => {
if (isCDown == false){
return;
}
var e = window.event ;
var nx = e.clientX;
var ny = e.clientY;
//计算移动后的左偏移量和顶部的偏移量
console.log('nx:'+nx+";ny:"+ny);
var nl = nx - cx;
var nt = ny - cy;
var destw = parseInt(origin_w)+nl;
var desth = parseInt(origin_h)+nt;
//console.log('destw:'+destw+";desth:"+desth);
document.getElementById(setid).style.width = destw+"px";
document.getElementById(setid).style.height = desth+"px";
}
window.coormousedown = coormousedown;
window.coormousemoving = coormousemoving;
window.coormouseup = coormouseup;
//移动div -----------------------------移动手动创建的div
let x = 0;
let y = 0;
let l = 0;
let t = 0;
let isDown = false;
let curDivId = 0;
//移动div,按下鼠标,开始
const divmousedown = (id) => {
if (isDown == true) {
return false;
}
var e = window.event;
//获取x坐标和y坐标
x = e.clientX;
y = e.clientY;
//获取左部和顶部的偏移量
l = document.getElementById(id).offsetLeft;
t = document.getElementById(id).offsetTop;
//开关打开
isDown = true;
curSetId = id;
curDivId = id;
}
//移动div,正在移动时
const divmousemoving = (id) => {
if (id!=curDivId) {
return;
}
var e = window.event ;
if (isCDown == true){
let nx = e.clientX;
let ny = e.clientY;
console.log('nx:'+nx+";ny:"+ny);
let nl = nx - cx;
let nt = ny - cy;
console.log('nl:'+nl+";nt:"+nt);
var destw = parseInt(origin_w)+nl;
var desth = parseInt(origin_h)+nt;
console.log('destw:'+destw+";desth:"+desth);
document.getElementById(curSetId).style.width = destw+"px";
document.getElementById(curSetId).style.height = desth+"px";
return;
}
if (isDown == false) {
return;
}
//获取x和y
let nx = e.clientX;
let ny = e.clientY;
//计算移动后的左偏移量和顶部的偏移量
let nl = nx - (x - l);
let nt = ny - (y - t);
document.getElementById(id).style.left = nl + 'px';
document.getElementById(id).style.top = nt + 'px';
}
//移动div结束
const divmouseup = (setid,content_id) => {
isDown = false;
//得到它的位置:
var left = parseInt(document.getElementById(setid).style.left);
var top = parseInt(document.getElementById(setid).style.top);
if (content_id>0) {
if (left == document.getElementById(setid).dataset.origin_l && top == document.getElementById(setid).dataset.origin_t){
//未修改位置,do nothing
} else {
document.getElementById(setid).dataset.origin_l = left;
document.getElementById(setid).dataset.origin_t = top;
}
}
}
window.divmousedown = divmousedown;
window.divmousemoving = divmousemoving;
window.divmouseup = divmouseup;
//div的删除功能,加了一个淡出效果
const del = (idNumber) => {
if (confirm("确认要删除当前div吗?"+idNumber)) {
let delDom = document.getElementById(idNumber);
delDom.style.opacity = 0;
delDom.style.transition = "all 0.5s";
setTimeout(function () {
document.getElementById("preview").removeChild(delDom);
}, 520);
}
}
window.del = del;
//div的编辑功能,只写了一个alert
const edit = (idNumber,contentId) => {
alert("edit:"+idNumber+":content:"+contentId);
}
window.edit = edit;
return {
drawBegin,
drawMove,
drawEnd,
coormousemoving,
coormouseup,
coormousedown,
del,
edit,
}
}
}
</script>
<style scoped>
.main {
width:100vw;
height:100vh;
background: #ff0000;
}
/deep/ .coor {pointer-events:auto; width: 10px; height: 10px; overflow: hidden; cursor: se-resize; position: absolute; right: 0; bottom: 0; background-color: #00FFFF; z-index: 5000;}
/deep/ .edit {pointer-events:auto; width: 18px; height: 18px;line-height: 18px; overflow: hidden; cursor: se-resize; position: absolute; left: 0px; bottom: -18px; text-align: center;background-color: #ADFF2F; }
/deep/ .del {pointer-events:auto; width: 18px; height: 18px;line-height: 18px; overflow: hidden; cursor: se-resize; position: absolute; left: 18px; bottom: -18px;text-align: center; background-color: #09C; }
/deep/ .number {pointer-events:auto; width: 18px; height: 18px;line-height: 18px; overflow: hidden; cursor: se-resize; position: absolute; left: 0px; top: -18px;text-align: center; background-color: #09C; }
</style>
说明:刘宏缔的架构森林—专注it技术的博客,
网址:https://imgtouch.com
本文: https://blog.imgtouch.com/index.php/2023/05/28/vue-js-3-2-20-tuo-dong-chuang-jian-div-ji-yi-dong%e3%80%81-suo/
代码: https://github.com/liuhongdi/ 或 https://gitee.com/liuhongdi
说明:作者:刘宏缔 邮箱: 371125307@qq.com
三,测试效果
四,查看vue的版本:
liuhongdi@lhdpc:/data/vue/move$ npm list vue move@0.1.0 /data/vue/move ├─┬ @vue/cli-plugin-babel@4.5.14 │ └─┬ @vue/babel-preset-app@4.5.14 │ └── vue@3.2.20 deduped └─┬ vue@3.2.20 └─┬ @vue/server-renderer@3.2.20 └── vue@3.2.20 deduped