前一段时间遇到一个需求是在要求前端页面写出,随意点击任意一点,会生成新增弹窗,再弹窗中选择要新增的类型。保存后生成新的子dom元素节点,并且新增的每一个新的元素,都可以托拉拽任意更改位置,可以实现编辑修改删除等操作。
思路:1.首先想到的就是画布canvas,需要很多的数据计算所以我暂时先没考虑。
2.先确定需求,任意点击触发事件,新的元素支持修改编辑删除,支持托拉拽功能
3.确定方向,需要考虑的是获取鼠标的坐标,并且生成的节点为动态的坐标,脱离文档流布局,动态 left top ,每次托拉拽后的动态 left top
话不多说,代码搞上:
<template>
<div class="canvas">
<div class="operation">
<div class="increase"
@click="operClick(1)"
:class="[this.lampType !== 1 ? 'oper' : 'opers']">新增</div>
<div class="delete"
@click="operClick(2)"
:class="[this.lampType !== 2 ? 'oper' : 'opers']">删除</div>
<div class="drag_drop"
@click="operClick(3)"
:class="[this.lampType !== 3 ? 'oper' : 'opers']">拖拽</div>
<div class="editor"
@click="operClick(4)"
:class="[this.lampType !== 4 ? 'oper' : 'opers']">编辑</div>
<div class="view"
@click="operClick(5)"
:class="[this.lampType !== 5 ? 'oper' : 'opers']">查看</div>
</div>
<div class="contentsss">
<div class="canvas_con"
@click="getmous($event)">
<div class="dingwei">
<div v-for="(item,index) in lists"
:key="index"
style="position: absolute">
<div :class="['tub'+index]"
:style="{width:item.width,height:item.height,position:'absolute',border:item.border,top:item.top,left:item.left,textAlign:'center',lineHeight:'100px'}"
@click="domClick(index)"
@mousedown="move"
:data-song='index'
ref="demodiv">
{{item.name}}
<img :src="item.img"
style="width:20px;height:20px;">
</div>
</div>
</div>
</div>
</div>
<el-dialog title=""
:visible.sync="dialogFormVisible">
<el-form :model="form">
<el-form-item label="设施类型"
label-width="120px">
<el-select v-model="form.region"
placeholder="请选择设施类型"
style="width:100%">
<el-option label="灯"
value="1"></el-option>
<el-option label="空调"
value="2"></el-option>
<el-option label="桌子"
value="3"></el-option>
<el-option label="椅子"
value="4"></el-option>
<el-option label="消防栓箱子"
value="5"></el-option>
<el-option label="垃圾桶"
value="6"></el-option>
<el-option label="饮水机"
value="7"></el-option>
</el-select>
</el-form-item>
<el-form-item label="设施区组号"
label-width="120px">
<el-input v-model="form.name"
autocomplete="off"></el-input>
</el-form-item>
</el-form>
<div slot="footer"
class="dialog-footer">
<el-button @click="clearClick()">取 消</el-button>
<el-button type="primary"
@click="saveClick()">确 定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
data () {
return {
domtop: '',
domleft: '',
lists: [],
dialogFormVisible: false,
form: {
name: '',
region: ''
},
images: '',
clickDomeType: false,
lampType: 0,
viewType: 0,
editorType: 0,
dragType: 0,
deleteType: 0,
increaseType: 0,
tub: null
}
},
components: {
},
watch: {
lists () {
// this.tub
}
},
methods: {
//点击选项
operClick (index) {
if (index === 1) {
this.lampType = 1
}
if (index === 2) {
this.lampType = 2
}
if (index === 3) {
this.lampType = 3
}
if (index === 4) {
this.lampType = 4
}
if (index === 5) {
this.lampType = 5
}
},
//拖拽设施
move (e) {
if (this.lampType === 3) {
console.log(e.srcElement.dataset.song, '/')
// e.preventDefault()//取消一系列点击事件
var content = document.querySelector('.canvas_con')
var tub = document.querySelector('.tub' + e.srcElement.dataset.song)
console.log(content, 'content')
console.log(tub, 'tub')
var x = e.clientX - tub.offsetLeft
var y = e.clientY - tub.offsetTop
content.addEventListener('mousemove', move)
}
function move (e) {
tub.style.left = e.pageX - x + 'px'
tub.style.top = e.pageY - y + 'px'
}
// 添加鼠标抬起事件,鼠标抬起,将事件移除
tub.addEventListener('mouseup', function () {
content.removeEventListener('mousemove', move)
})
// 鼠标离开父级元素,把事件移除
content.addEventListener('mouseout', function () {
content.removeEventListener('mousemove', move)
})
},
//点击dome删除操作
domClick (index) {
this.clickDomeType = true
if (this.lampType === 2) {
console.log(index, 'index')
this.$confirm('此操作将永久删除该文件, 是否继续? 注意此demo没有加编辑功能,后期项目加!!!', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.lists.splice(index, 1)
this.clickDomeType = false
this.$message({
type: 'success',
message: '删除成功!'
});
}).catch(() => {
this.clickDomeType = false
this.$message({
type: 'info',
message: '已取消删除'
});
});
}
},
// 点击取消
clearClick () {
this.dialogFormVisible = false
},
// 点击确定提交
saveClick () {
this.images = ''
if (this.form.region === '1') {
this.images = require('@/assets/img/liang.png')
} else if (this.form.region === '2') {
this.images = require('@/assets/img/loading.png')
} else if (this.form.region === '3') {
this.images = require('@/assets/img/touying.png')
} else if (this.form.region === '4') {
this.images = require('@/assets/img/11.jpg')
} else if (this.form.region === '5') {
this.images = require('@/assets/img/111.jpg')
}
this.lists.push({
name: this.form.name,
type: this.form.region,
height: '100px',
width: '100px',
position: 'absolute',
border: '1px solid #000',
top: this.domtop,
left: this.domleft,
img: this.images
})
// this.lists.forEach((item) => {
// this.tub =
// })
console.log(this.lists, 'lists')
this.dialogFormVisible = false
},
//点击全屏
getmous (e) {
this.clickDomeType = false
// debugger
if (this.lampType === 1) {
this.form = {
name: '',
region: ''
}
this.domleft = e.clientX - 50 + 'px'
this.domtop = e.clientY - 150 + 'px'
if (this.clickDomeType === true) {
this.dialogFormVisible = false
} else {
this.dialogFormVisible = true
}
console.log(e, 'es')
}
}
}
}
</script>
<style lang="scss">
.canvas_con {
width: 1000px;
height: 700px;
// position: relative;
border: 1px solid #000;
.dingwei {
position: absolute;
}
}
.operation {
.pointer {
float: right;
width: 100px;
height: 40px;
border: 1px solid #000;
margin-left: 10px;
margin-top: 10px;
text-align: center;
line-height: 40px;
background: rgb(9, 103, 243);
color: #fff;
font-weight: 600;
cursor: pointer;
}
.move {
float: right;
width: 100px;
height: 40px;
border: 1px solid #000;
margin-left: 10px;
margin-top: 10px;
text-align: center;
line-height: 40px;
background: rgb(9, 103, 243);
color: #fff;
font-weight: 600;
cursor: move;
}
.opers {
float: right;
width: 100px;
height: 40px;
border: 3px solid #000;
margin-left: 10px;
margin-top: 10px;
text-align: center;
line-height: 40px;
background: rgb(9, 103, 243);
color: #fff;
font-weight: 600;
cursor: pointer;
}
.oper {
float: right;
width: 100px;
height: 40px;
border: 3px solid #000;
margin-left: 10px;
margin-top: 10px;
text-align: center;
line-height: 40px;
cursor: pointer;
}
}
.xiaoshou {
cursor: pointer;
}
.yidong {
cursor: move;
}
</style>
代码就这么多,数据交互没有写,这需要阅读者自己操作一下啦。
存储每次点击确定生成新的dom的信息和坐标信息,存储每次托拉拽后的位置坐标信息。
有看不明白的地方可以留言一下