306 lines
8.1 KiB
Vue
306 lines
8.1 KiB
Vue
<template>
|
|
<div class="detail" ref="detailDom"
|
|
@mousemove="mousemove($event)"
|
|
@touchmove="touchmove($event)"
|
|
>
|
|
<div class="layer">
|
|
<div class="layer-item button" @click="canvasGeneral.createLayer">
|
|
Add Layer
|
|
</div>
|
|
<div class="layer-item-box-scroll">
|
|
<div class="layer-item-box" :style="{'height':layerList.length * 6 + 'rem'}">
|
|
<div class="layer-item"
|
|
v-for="item,index in layerList"
|
|
:key="item"
|
|
:style="item?.style"
|
|
@click.stop="canvasGeneral.selectLayer(item.id)"
|
|
@mousedown.stop="mousedown($event,item,index)"
|
|
@touchstart.stop="touchstart($event,item,index)"
|
|
|
|
@contextmenu.stop="openMenu($event,item,index)"
|
|
|
|
:class="{'active':item.id == canvasGeneral.layer.selectLayer.id}">
|
|
<!-- <div @click.stop="canvasGeneral.layerShowHide(item.id,item)">{{ item.isShow }}</div> -->
|
|
<i class="fi" :class="[(item.isShow)?'fi-rr-eye':'fi-rr-eye-crossed']" @click.stop="canvasGeneral.layerShowHide(item.id,item)"></i>
|
|
<img :src="item.img" alt="">
|
|
<div>
|
|
{{ item.name }}
|
|
</div>
|
|
<div @click.stop="canvasGeneral.layerDelete(index,item.id)" :class="{noDelete:canvasGeneral.layer.list.length == 1}">
|
|
<i class="fi fi-rr-trash icon_delete" style="height: 100%;padding: 0;"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
<div class="layer-menu" :style="styleMenu">
|
|
<div class="layer-menu-item" @click="canvasGeneral.copyLayer(itemMenu.id)">Copy</div>
|
|
<div class="layer-menu-item" @click="canvasGeneral.layerDelete(itemMenu.index,itemMenu.id)">Delete</div>
|
|
<div class="layer-menu-item" v-if="itemMenu.groupType == 'Object'" @click="canvasGeneral.setGridOrObject(itemMenu.id,'Grid')">Rasterize layer</div>
|
|
<div class="layer-menu-item" v-if="itemMenu.groupType == 'Grid'" @click="canvasGeneral.setGridOrObject(itemMenu.id,'Object')">Cancal rasterization</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { defineComponent,ref,reactive,nextTick,toRefs,inject,watch,computed} from 'vue'
|
|
import { getMousePosition } from "@/tool/mdEvent";
|
|
|
|
export default defineComponent({
|
|
component:{},
|
|
setup(){
|
|
let canvasGeneral:any = inject('canvasObj')
|
|
const data = reactive({
|
|
detailDom:null as any,
|
|
layerList:computed(()=>canvasGeneral.layer.list) as any,
|
|
styleMenu:{
|
|
left:0+'px',
|
|
top:0+'px',
|
|
display:'none',
|
|
},
|
|
itemMenu:{} as any,
|
|
})
|
|
watch(()=>canvasGeneral.layer.list.length, (newValue, oldValue) => {
|
|
let sortedArr = data.layerList.map((item:any) => ({ ...item })).sort((a:any, b:any) => b.index - a.index)
|
|
sortedArr.forEach((item:any,index:any)=>{
|
|
item.index = sortedArr.length - index
|
|
})
|
|
data.layerList.forEach((item:any) => {
|
|
//图层高度50px 下边距10px
|
|
sortedArr.forEach((sortedArrItem:any)=>{
|
|
if(item.id == sortedArrItem.id){
|
|
item.index = sortedArrItem.index
|
|
}
|
|
let style = {
|
|
top:(data.layerList.length - item.index) * 60 + 'px',
|
|
transition:'all .3s',
|
|
}
|
|
item.style = style
|
|
})
|
|
|
|
});
|
|
},{immediate:true});
|
|
const incident:any = reactive({
|
|
isDown:false,
|
|
selectStyleTop:null,
|
|
selectStyle:null,
|
|
downPoint:null,
|
|
select:null,
|
|
radius:25,
|
|
})
|
|
const openMenu = (event:any,item:any,index:number)=>{
|
|
if(event.preventDefault)event.preventDefault();
|
|
data.itemMenu = item;
|
|
// data.itemMenu.index = index
|
|
let position = data.detailDom.getBoundingClientRect();
|
|
data.styleMenu = {
|
|
left:event.clientX - position.left+'px',
|
|
top:event.clientY - position.top+'px',
|
|
display:'block',
|
|
}
|
|
}
|
|
document.onclick = ()=>{
|
|
data.styleMenu.display = 'none'
|
|
data.itemMenu = {};
|
|
}
|
|
let mousedown = (event:any,item:any,index:number)=>{
|
|
if(event.button != 0)return
|
|
let e:any = getMousePosition(event,false)
|
|
mouseDownOperation(e,item,index)
|
|
}
|
|
let ipadDownTime:any = null
|
|
let touchstart = (event:any,item:any,index:number)=>{
|
|
let e:any = getMousePosition(event,true)
|
|
mouseDownOperation(e,item,index)
|
|
clearTimeout(ipadDownTime)
|
|
ipadDownTime = setTimeout(()=>{
|
|
openMenu(e,item,index)
|
|
},1000)
|
|
|
|
}
|
|
let mouseDownOperation = (e:any,item:any,index:number)=>{
|
|
incident.isDown = true
|
|
incident.selectStyleTop = item.style.top
|
|
incident.selectStyle = item.style
|
|
incident.selectStyle.transition = 'none'
|
|
incident.select = item
|
|
incident.downPoint = e.clientY
|
|
}
|
|
|
|
let mousemove = (event:any)=>{
|
|
let e:any = getMousePosition(event,false)
|
|
mouseMoveOperation(e)
|
|
}
|
|
let touchmove = (event:any)=>{
|
|
let e:any = getMousePosition(event,true)
|
|
clearTimeout(ipadDownTime)
|
|
if(data.styleMenu.display != 'none')data.styleMenu.display = 'none'
|
|
mouseMoveOperation(e)
|
|
}
|
|
let mouseMoveOperation = (e:any)=>{
|
|
if(incident.isDown){
|
|
let domTop = Number(incident.selectStyleTop.split('px')[0])
|
|
|
|
let gTop = domTop + (e.clientY - incident.downPoint)
|
|
if(gTop < 0){
|
|
gTop = 0
|
|
}
|
|
incident.select.style.top = gTop + 'px'
|
|
data.layerList.forEach((item:any,index:number) => {
|
|
let itemTop = Number(item.style.top.split('px')[0])
|
|
if(Math.abs(gTop - itemTop) < 30 && item.id != incident.select.id){
|
|
let itemIndex = item.index
|
|
// if(gTop - itemTop > 0){
|
|
// console.log('从下往上');
|
|
// }
|
|
// if(gTop - itemTop < 0){
|
|
// console.log('从上往下');
|
|
// }
|
|
item.index = incident.select.index
|
|
incident.select.index = itemIndex
|
|
|
|
}
|
|
})
|
|
sort(data.layerList,'move')
|
|
}
|
|
}
|
|
const mouseUp = ()=>{
|
|
if(data.styleMenu.display == 'none')clearTimeout(ipadDownTime)
|
|
if(incident.isDown){
|
|
if(incident.selectStyle)incident.selectStyle.transition = 'all .3s'
|
|
incident.selectStyleTop = null
|
|
incident.isDown = false
|
|
incident.selectStyle = null
|
|
incident.select = null
|
|
sort(data.layerList,'up')
|
|
}
|
|
}
|
|
document.onmouseup = mouseUp
|
|
document.ontouchend = mouseUp
|
|
//排序
|
|
let time:any = null
|
|
let sort = (list:any,str:string)=>{
|
|
clearTimeout(time)
|
|
// list = list.sort((a:any, b:any) =>{
|
|
// return b.index - a.index;
|
|
// });
|
|
list.forEach((item:any) => {
|
|
if(str == 'move'){
|
|
if(item.id != incident.select.id)item.style.top = (list.length - item.index) * 60 + 'px'
|
|
}else{
|
|
item.style.top = (list.length - item.index) * 60 + 'px'
|
|
}
|
|
});
|
|
if(str == 'up')time = setTimeout(()=>canvasGeneral.upLayerIndex(list),500)
|
|
}
|
|
return {
|
|
canvasGeneral,
|
|
...toRefs(data),
|
|
openMenu,
|
|
mousedown,
|
|
touchstart,
|
|
mousemove,
|
|
touchmove,
|
|
}
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<style lang='less' scoped>
|
|
.detail{
|
|
width: 100%;
|
|
height: 100%;
|
|
padding: 1rem;
|
|
border: 1px solid #dcdfe6;
|
|
position: relative;
|
|
* {
|
|
-webkit-user-drag: none;
|
|
-moz-user-drag: none;
|
|
-ms-user-drag: none;
|
|
user-drag: none;
|
|
-moz-user-select: none;
|
|
-webkit-user-select: none;
|
|
-ms-user-select: none;
|
|
-khtml-user-select: none;
|
|
user-select: none;
|
|
}
|
|
.layer{
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: 100%;
|
|
.layer-button{
|
|
|
|
}
|
|
.layer-item{
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: .5rem 2rem;
|
|
border: 1px solid #e6e6e6;
|
|
margin-bottom: 10px;
|
|
height: 50px;
|
|
border-radius: 4px;
|
|
i{
|
|
font-size: 18px;
|
|
}
|
|
&.active{
|
|
background: #e6e6e6;
|
|
}
|
|
.noDelete{
|
|
background: #e6e6e6;
|
|
opacity: .4;
|
|
pointer-events: none;
|
|
}
|
|
&.button{
|
|
justify-content: center;
|
|
cursor: pointer;
|
|
}
|
|
img{
|
|
height: 100%;
|
|
width: 35px;
|
|
object-fit: contain;
|
|
}
|
|
div{
|
|
cursor: pointer;
|
|
}
|
|
&:last-child{
|
|
margin-bottom: 0;
|
|
}
|
|
}
|
|
.layer-item-box-scroll{
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
.layer-item-box{
|
|
position: relative;
|
|
.layer-item{
|
|
position: absolute;
|
|
width: 100%;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
.layer-menu{
|
|
position: absolute;
|
|
width: 60%;
|
|
line-height: 4rem;
|
|
background: #fff;
|
|
border-radius: 4px;
|
|
border: 1px solid;
|
|
overflow: hidden;
|
|
>div{
|
|
border-bottom: 1px solid;
|
|
padding: 0 2rem;
|
|
cursor: pointer;
|
|
}
|
|
>div:hover{
|
|
background: #e6e6e6;
|
|
}
|
|
>div:last-child{
|
|
border-bottom: none;
|
|
}
|
|
}
|
|
}
|
|
|
|
</style> |