九宫格拖拽

作者: HeroXin | 来源:发表于2018-06-20 20:12 被阅读0次

    效果实例

    简单了解Grid布局(网格布局)

    什么是网格布局

    CSS网格布局(又称“网格”),是一种二维网格布局系统。CSS在处理网页布局方面一直做的不是很好。一开始我们用的是table(表格)布局,然后用float(浮动),position(定位)和inline-block(行内块)布局,但是这些方法本质上是hack,遗漏了很多功能,例如垂直居中。后来出了flexbox(盒子布局),解决了很多布局问题,但是它仅仅是一维布局,而不是复杂的二维布局,实际上它们(flexbox与grid)能很好的配合使用。Grid布局是第一个专门为解决布局问题而创建的CSS模块.

    简单说说网格布局的属性

    • display:
      • grid: 生成块级网格
      • inline-grid: 生成行内网格
      • subgrid: 如果网格容器本身是网格项(嵌套网格容器),此属性用来继承其父网格容器的列、行大小。
    • grid-template-columns
      • 设置网格列大小
    • grid-template-rows
      • 设置网格行大小
    • grid-template-areas
      • 设置网格区域
    • grid-column-gap
      • 设置网格列间距
    • grid-row-gap
      • 设置网格行间距
    • grid-gap
      • 缩写形式 grid-gap: <grid-row-gap> <grid-column-gap>
    • justify-items
      • 水平方向对齐方式(在这里只是简单说明)
      • start: 左对齐
      • end: 右对齐
      • center: 居中对齐
      • stretch: 填满(默认)
    • align-items
      • 垂直方向对齐方式
      • start: 顶部对齐
      • end: 底部对齐
      • center: 居中对齐
      • stretch:填满(默认)

    当然,如果看不懂也不要紧,这里有一篇个人十分喜欢的网格布局的文章。里面介绍得十分详细。可以供大家深入学习网格布局内容。

    传送门:Grid布局指南

    Vue实现九宫格拖拽

    Demo地址: Demo以及完整代码

    实现九宫格布局

    /*css*/
    
      .container{
        position: relative;   /*实现定位,使得滑块定位相对于此*/
        display: grid;        /*定义网格布局*/
        width: 300px;
        height: 300px;
        grid-template-columns: 100px 100px 100px;     /*实现九宫格,行列各三*/
        grid-template-rows: 100px 100px 100px;
        grid-template-areas: "head1 head2 head3"      /*定义个格子的名称,方便计算*/
                              "main1 main2 main3"
                              "footer1 footer2 footer3";
        border: 1px solid #000;
        margin: 0 auto;
      }
      .block{
        position: absolute;     /*相对于container定位*/
        width: 100px;
        height: 100px;
        display: flex;        /*flex布局,使得文字在中央*/
        justify-content: center;
        justify-items: center;
        align-items: center;
        align-content: center;
        user-select: none;      /*用户不可选定文字*/
        background: olivedrab;
        border: 1px solid #000
      }
    
    
    //app.vue
    
    <div id="app">
      <div class="container">
        <transition >
          <div class="block animated"  :style="{top:this.positionY,left:this.positionX,gridArea:'main2'}" @mousedown="move" ref="block">
            {{positionX}}
            {{positionY}}
          </div>
        </transition>
      </div>
    </div>
    
    

    实现拖拽的JS代码部分

    在这里我选取一些核心代码出来讲解。代码有所省略,因为代码着实有点长,太占篇幅而且没多大意义,如果需要浏览全部代码可以点击上面的Demo连接。

    <script>
    //引入animate.css 没有手撕css动画,直接用了animate.css实现我们的动画效果
    import animate from 'animate.css';
    
    export default {
      name: 'app',
      data () {
        return {
          positionX:0,      //定义方块的两个坐标
          positionY:0,
        }
      },
      methods:{
        move(e){
          let oDiv = e.target;      //获取点击的目标元素
          let gDiv = e.path[1];     //获取点击元素的父级元素
    
          /*获取点击时的偏移位置,在这里要注意一下
          **由于我们用的是网格布局,每在一个格子中相对位置都是相对格子来算的,不是相对于父级盒子左上角
          **也就是说当你把方块移动到九个格子中任意一个时,方块的位置都是top:0和left:0
          */
    
          //所以这里我们直接取鼠标点击的位置减去点击盒子的偏移位置,也就是0
          let disX = e.clientX - 0;     
          let disY = e.clientY - 0;
          document.onmousemove = (e)=>{
    
            //当拖动时,算出的值就刚好是方块的top和left值
            let left = e.clientX - disX;
            let top = e.clientY - disY;
            switch (oDiv.style.gridArea){
              case "head1 / head1 / head1 / head1":this.rangeOfHead1(left,top,oDiv);break;    //实现head1的移动范围
              case "head2 / head2 / head2 / head2":this.rangeOfHead2(left,top,oDiv);break;    //实现head2的移动范围
              case "head3 / head3 / head3 / head3":this.rangeOfHead3(left,top,oDiv);break;    //实现head3的移动范围
              case "main1 / main1 / main1 / main1":this.rangeOfMain1(left,top,oDiv);break;    //实现main1的移动范围
              ...
            }
          };
          document.onmouseup = (e)=>{
            //当鼠标抬起时,我们要做的事
            //通过点击位置和父级元素的偏移判断方块在哪个区域
            if(e.clientY-gDiv.offsetTop<100&&e.clientX-gDiv.offsetLeft<100){
    
              //将方块移动到该区域中
              this.changeBlock("head1",oDiv); 
    
            }else if(e.clientY-gDiv.offsetTop>100&&e.clientX-gDiv.offsetLeft<100&&e.clientY-gDiv.offsetTop<200){
              this.changeBlock("main1",oDiv);
            }else if(e.clientY-gDiv.offsetTop>200&&e.clientX-gDiv.offsetLeft<100){
              this.changeBlock("footer1",oDiv);
            }else if(e.clientY-gDiv.offsetTop<100&&e.clientX-gDiv.offsetLeft>100&&e.clientX-gDiv.offsetLeft<200){
              this.changeBlock("head2",oDiv);
            }else if(e.clientY-gDiv.offsetTop<100&&e.clientX-gDiv.offsetLeft>200){
              this.changeBlock("head3",oDiv);
            }else if(e.clientY-gDiv.offsetTop>100&&e.clientX-gDiv.offsetLeft>200&&e.clientY-gDiv.offsetTop<200){
              this.changeBlock("main3",oDiv);
            }else if(e.clientY-gDiv.offsetTop>200&&e.clientX-gDiv.offsetLeft>200){
              this.changeBlock("footer3",oDiv);
            }else if(e.clientY-gDiv.offsetTop>200&&e.clientX-gDiv.offsetLeft>100&&e.clientX-gDiv.offsetLeft<200){
              this.changeBlock("footer2",oDiv);
            }else {
              this.changeBlock("main2",oDiv);
            }
            document.onmousemove=null;      //需要把事件监听取消
            document.onmousedown = null;    //需要把事件监听取消
    
            //当然,不能忘记我们的动画hhh
            oDiv.className = "block animated wobble";
            let removeClass = setTimeout(()=>{
              oDiv.className = "block animated";
            },500);
    
          };
        },
        rangeOfHead1(x,y,oDiv){     //判断head1格子中的可以移动范围
          if(x>=200){
            x=200;
          }else if(x<=0){
            x=0;
          }
          if(y>=200){
            y=200;
          }else if(y<=0){
            y=0;
          }
          oDiv.style.left = x + 'px';
          oDiv.style.top = y + 'px';
          this.positionX = x;
          this.positionY = y;
    
        },
        rangeOfHead2(x,y,oDiv){     //判断head2格子中的可以移动范围
          if(x>=100){
            x=100;
          }else if(x<=-100){
            x=-100;
          }
          if(y>=200){
            y=200;
          }else if(y<=0){
            y=0;
          }
          oDiv.style.left = x + 'px';
          oDiv.style.top = y + 'px';
    
          this.positionX = x;
          this.positionY = y;
    
        },
        ...
        changeBlock(blockName,oDiv){    //将方块移入到对应的区域中
          this.positionX = 0;
          this.positionY = 0;
          oDiv.style.gridArea=blockName;
        }
      },
    }
    </script>
    

    相关文章

      网友评论

        本文标题:九宫格拖拽

        本文链接:https://www.haomeiwen.com/subject/xlbxyftx.html