一、思路

1.每次push到list数组的时候,新增一个z用来管理图层的叠放,z应该有个默认值0,如果有z值去多个z值中比较获取最大的,这样拖拽的时候,会是最高层级的的

2.样式的话z-index因为我们用的依赖,所以直接赋值就可以了

二、置顶和置底

1.首先右击的时候获取当前图层的焦点传一个item过来,然后设置一个focused状态,遍历list中的id,跟当前点击的id是否一样,一样就true,否则为flase

2.先找到数组中被选中的项,通过list中多个z值比较,最大最小,从而实现置底和置顶

   //封装 左键点击,让当前项获取焦点,其他项取消焦点clickDrageeronFoucus(currentItem) {currentItem.focused = true;this.list.forEach((item)=>{item.focused = item.id === currentItem.id })},//右键菜单-打开的时候获取当前焦点onContextMenuOpen(e, item) {this.$refs.contextMenu.open(e);//打开右键菜单this.clickDrageeronFoucus(item);//右击的时候获取焦点},//封装去找最小值findBottomLayer(currentItem) {const minZ = Math.min(...this.list.map(item => item.z)) || 0//获取最小值if (currentItem.z === minZ) {alert('已经是最底层了')return false;//因为还有一个最上层,所以改为false}return minZ},//封装去找最大值findTopLayer(currentItem) {const maxZ = Math.max(...this.list.map(item => item.z)) || 0//获取最大值if (currentItem.z === maxZ) {alert('已经是最顶层了')return;}return maxZ},
//右键菜单项-置顶onLayerTop() {//先找到数组当中被选中的那项const currentItem = this.list.find(item => item.focused)const maxZ = this.findTopLayer(currentItem)//找最大值if (!maxZ) {//判断最大值是否存在,注意0的时候是不存在的return;}currentItem.z = maxZ + 1;//// this.sortList()//排序// this.record()//记录},//右键菜单项-置底onLayerBottom() {//先找到数组当中被选中的那项const currentItem = this.list.find(item => item.focused)const minZ = this.findBottomLayer(currentItem)//找最小值if (minZ === false) {//0是一个默认值   // 如果 !minZ 相当于!0 就为true就不对了所以要        写===false return;}// 因为显示不了负数比如-1,最小只能为0,所以要做逻辑处理if (minZ - 1 < 0) {this.list = this.list.map(item => {item.z -= minZ - 1;return item})currentItem.z = 0} else {currentItem.z = minZ - 1}// this.sortList()//排序// this.record()//记录},

三、全部代码

<template><div id="app"><!-- 图层列表 --><el-tabs v-model="activeName" class="sidebar"><el-tab-pane label="图层列表" name="layer"><!-- 图层列表 --><div class="layer" v-for="item in list" :key="item.id">{{ item.label }}</div></el-tab-pane><el-tab-pane label="组件列表" name="widget"><Widget-List :list="widgetList" @onWidgetMouseDown="onWidgetMouseDown" /></el-tab-pane></el-tabs><!-- 操作面板 --><div class="panel"  @dragover.prevent @drop="onDrop" ><Drageer v-for="(item, i) in list" :key="item.id" ref="widget" class="box" :x="item.x" :y="item.y" :z="item.z" :w="item.w" :h="item.h" @contextmenu.native.prevent="onContextMenuOpen($event, item)"><component :value="item.value" class="inner-widget" :is="item.component" :styles="item.styles" /></Drageer></div><!-- 样式配置区域 --><!-- <style-sider></style-sider> --><!-- 右键菜单 --><Context-menu ref="contextMenu"><li><a href="#" @click.prevent="onLayerTop">置顶</a></li><li><a href="#" @click.prevent="onLayerBottom">置底</a></li><li><a href="#" @click.prevent="onLayerUp">上移图层</a></li><li><a href="#" @click.prevent="onLayerDown">下移图层</a></li><li><a href="#" @click.prevent="onLayerRemove">删除</a></li><!-- 可能会冒泡加stop --></Context-menu><!-- 对齐线 纵向 --><!-- <div></div> --></div>
</template><script>
let currentId = 0; //id计数器
let widgetX = 0;//差值
let widgetY = 0;//差值
let currentWidget = null;//获取当前点击的图层数据//右键菜单
import ContextMenu from 'vue-context';//出现在panel上的组件
import BarChart from '@/components/bar-chart'
import AreaChart from '@/components/area-chart'
import CustomText from '@/components/custom-text'
import CustomVideo from '@/components/custom-video'
import MianjiChart from '@/components/mianji-chart'//左侧小组件列表
import WidgetList from '@/components/widget-list/'//静态配置
import * as CONFIG from '@/components/constants/config'export default {name: 'App',components: {WidgetList,BarChart,AreaChart,CustomText,CustomVideo,MianjiChart,ContextMenu,},data(){return{activeName:'widget',list:[],widgetList: CONFIG.WIDGET_LTST,//组件的数据结构}},methods:{//放置组件onDrop(e,i){//放置的距离左侧的距离-鼠标落下鼠标距离左侧的距离=当前box的x轴位置let x = e.offsetX - widgetX;let y = e.offsetY - widgetY;if (i !== undefined) {x += this.list[i].x;y += this.list[i].y;}const newItem = ({id: currentId++,//key绑定idx,y,z: !this.list.length ? 0 : Math.max(...this.list.map(item => item.z)) + 1,//因为一开是空  所以给个默认值0...currentWidget.default,// w:this.currentWidget.w,//盒子初始值宽// h:this.currentWidget.h,label: currentWidget.label,//文字component: currentWidget.component, // 新增的组件名type: currentWidget.type,//新增组件的类型styles: currentWidget.styles,//新增组件的样式});this.list.push(newItem)// this.clickDrageeronFoucus(newItem)this.$refs.contextMenu.close()//关闭右键菜单},//在小组件鼠标落下的时候onWidgetMouseDown(e, widget) {//获取   鼠标距离左侧的距离widgetX = e.offsetX;widgetY = e.offsetY;currentWidget = widget;//当前点击的图层数据赋值},//右键菜单打开事件onContextMenuOpen(e, item) {this.$refs.contextMenu.open(e);//打开右键菜单this.clickDrageeronFoucus(item);//右击的时候获取焦点},//封装去找最小值findBottomLayer(currentItem) {const minZ = Math.min(...this.list.map(item => item.z)) || 0//获取最小值if (currentItem.z === minZ) {alert('已经是最底层了')return false;//因为还有一个最上层,所以改为false}return minZ},//封装去找最大值findTopLayer(currentItem) {const maxZ = Math.max(...this.list.map(item => item.z)) || 0//获取最大值if (currentItem.z === maxZ) {alert('已经是最顶层了')return;}return maxZ},//右键菜单项-置顶onLayerTop() {//先找到数组当中被选中的那项const currentItem = this.list.find(item => item.focused)const maxZ = this.findTopLayer(currentItem)//找最大值if (!maxZ) {//判断最大值是否存在,注意0的时候是不存在的return;}currentItem.z = maxZ + 1;//// this.sortList()//排序// this.record()//记录},//右键菜单项-置底onLayerBottom() {//先找到数组当中被选中的那项const currentItem = this.list.find(item => item.focused)const minZ = this.findBottomLayer(currentItem)//找最小值if (minZ === false) {//0是一个默认值   // 如果 !minZ 相当于!0 就为true就不对了所以要写===false return;}// 因为显示不了负数比如-1,最小只能为0,所以要做逻辑处理if (minZ - 1 < 0) {this.list = this.list.map(item => {item.z -= minZ - 1;return item})currentItem.z = 0} else {currentItem.z = minZ - 1}// this.sortList()//排序// this.record()//记录},// 左键点击,让当前项获取焦点,其他项取消焦点clickDrageeronFoucus(currentItem) {currentItem.focused = true;this.list.forEach((item)=>{item.focused = item.id === currentItem.id })},}
}
</script><style>
body {margin: 0;
}#app {display: flex;width: 100vw;height: 100vh;/* 可视高度的多少1vh=视窗高度的1% */
}.sidebar {width: 200px;background: #e9e9e9;
}.panel {flex: 1;background: #f6f6f6;position: relative;/* 给相对定位主要是因为 要根据panel盒子的左上角来进行绝对定位*/
}.widget {width: 100px;height: 100px;outline: 1px solid red;font-size: 24px;text-align: center;line-height: 100px;margin: 24px;
}.box {/* width: 100px;height: 100px; *//* 插件自带宽高 *//* outline: 1px solid blue; */outline: 1px solid rgba(0, 0, 0, 0);position: absolute;
}.inner-widget {width: 100%;height: 100%;
}.layer {width: 100%;height: 50px;line-height: 50px;background: #e9e9e9;
}.layer:hover {background: #fff;
}.currentbgm {background: #fff;
}.sider {width: 200px;background: #e9e9e9;
}.sider.right {width: 300px;
}.standard-line {width: 2px;height: 100%;/* background: rgba(31, 29, 29, 1); */border-left: 2px #0f0f0f dashed;position: absolute;left: 200px;
}.standard-line.correnct {/* background: red; */border-left: 2px red dashed;
}#frame {position: absolute;outline: 2px dashed red;
}
</style>

6.效果展示

3.BI可视化编辑器之右击菜单的“置顶、置底“实现相关推荐

  1. maptalks常见操作——图层置顶置底、添加清空图层、添加标注、切换底图、添加缩放工具、事件监听(点击面出弹框)、右键菜单、绘制mark、锁定视角

    maptalks常见操作--图层置顶置底.添加清空图层.添加标注.切换底图.添加缩放工具.事件监听(点击面出弹框).右键菜单.绘制mark.锁定视角 1.图层置顶 置底 layer.show().br ...

  2. power bi可视化表_如何使用Power BI可视化数据?

    power bi可视化表 什么是数据可视化? (What is Data Visualization?) With the technological revolution, data went fr ...

  3. bi可视化工具_适用于您的BI解决方案的最佳数据可视化和Web报告工具

    bi可视化工具 通过智能数据分析使复杂变得简单 (Making the complex simple with smart data analysis) It is hard to overestim ...

  4. power bi可视化表_在Power BI报表视图中创建可视化

    power bi可视化表 The Report View in Power BI can be used to create beautiful visualizations in Power BI. ...

  5. 编辑器之神——vim编辑器

    编辑器之神--vim编辑器 一.vi介绍 Vi编辑器是所有Unix及Linux系统下标准的编辑器,类似于windows系统下的notepad(记事本)编辑器,由于在Unix及Linux系统的任何版本, ...

  6. BI可视化分析之Pentaho

    简介 我们在上一篇数据仓库选型中已经确定了用使用Pentaho作为BI可视化分析工作. Pentaho的中文文档多,国际化做的比较好. 巧合的是我们之前使用的ETL数据清洗工具kettle也是属于Pe ...

  7. php 可视化编辑建站源码,CmsEasy可视化编辑商城系统 v7.3.1

    网站系统主要功能模块 商城模块: 自定义商品筛选 商品项自定义 物流查询 优惠劵 会员积分 会员充值 库存 自定义销售量 多语言: 自定义默认语言 多语种添加 定义语言图标 语言绑定域名 可视化编辑: ...

  8. cms可视化编辑php,AyaCMS与We7CMS可视化编辑模板功能对比

    愈来愈多的CMS会考虑到一些入门级站长对建站程序的需求,那就是功能强大.使用简单!其中使用简单就包括了一个模板的修改,对入门站长来说这是个不小的难题.一般的CMS模板在后台都是纯代码显示,直接代码修改 ...

  9. java 协作编辑,在线协作编辑器之周报收集

    在线协作编辑器之周报收集 一.实验说明 下述介绍为实验楼默认环境,如果您使用的是定制环境,请修改成您自己的环境介绍. 1. 环境登录 无需密码自动登录,系统用户名shiyanlou 2. 环境介绍 本 ...

最新文章

  1. 查看TensorFlow的版本和路径
  2. 进程(process)和线程(thread)
  3. 前端面试题-数组去重和排序
  4. iOS开发--TableView详细解释
  5. HTML+CSS+JS实现 ❤️ html5响应式图片轮播❤️
  6. 前端:CSS/12/display属性,overflow属性,cursor光标类型,CSS定位,综合案例:今日闪价
  7. 混合架构、暗数据...这些云原生安全 bug 稍不留神会带来灾难!
  8. logging日志模块 , 序列化json pickle , 随机数random
  9. StanfordDB class自学笔记 (1) 数据库系统简介
  10. 基于动态优先级的时间片轮转调度算法c语言
  11. 集中化Linux日志管理系统
  12. Futura字体和Logo设计实践
  13. 10分钟也不一定学会的灵敏度分析
  14. cortex a8 java_ARM Cortex-
  15. Altium 在PCB重新编号更新到SCH原理图的方法
  16. 【DOTS学习笔记】DOTS简介
  17. The Shawshank Redemption-15
  18. 无名管道(pipe)--实现管道双向通信
  19. 在《css禅意花园》中所学到的
  20. 【学习笔记】builtin函数

热门文章

  1. 关于写小米手机必败另一面
  2. java给手机发短信_java给手机发送短信验证码
  3. java toast_【转】【Java/Android】Toast使用方法大全
  4. PHP 检查网站是否宕机
  5. 入门学习ui设计就业方向有哪些?
  6. 网络教育计算机统考-Outlook操作题
  7. 你是个靠谱的程序员吗?
  8. win7运行java配色方案_Win7系统提示“配色方案已更改为Windows7 Basic”如何解决?...
  9. redis报错,Could not get a resource from the pool,Unable to validate object找不到可用的连接池
  10. memcpy,memmove,memcmp,memset内存函数