zoukankan      html  css  js  c++  java
  • 可拖拽的3D盒子

    代码地址如下:
    http://www.demodashi.com/demo/11453.html

      一直想做一个立体的盒子,前段时间刚好看见掘金上有位朋友发了篇关于3d盒子的文章,看了决定自己做一下,再写一些和盒子互动的操作。

    一、程序实现

      首先看下怎么做一个静止的盒子,用到了css3transform。将盒子六个面放在一个div里,将这个div定位好,用transform属性改变不同的面的朝向,再将其向前移动盒子宽度的一半,盒子就做好了。html结构如下:

        <div class="wraper">
            <div class="cube">
                <div class="front">Front</div>
                <div class="end">End</div>
                <div class="left">Left</div>
                <div class="right">Right</div>
                <div class="top">Top</div>
                <div class="bottom">Bottom</div>
            </div>
        </div>

      设置css,不熟悉transform可以看下下边这张图,需要注意的是元素的轴是跟着元素转动而转动的,所以几个面的translateZ属性的值都是一样的,旋转到正确的朝向然后向前平移盒子一半的宽度。

    3d_axes.png

    body,
    html {
        height: 100%;
        padding: 0;
        margin: 0;
        /*将border和padding绘制在设置宽高之内*/
        box-sizing: border-box;      
        overflow: hidden;
    }
    .wraper {
         260px;
        height: 260px;
        margin: 128px auto;
        /*景深,可以理解为视角到3D物体的距离,设置于舞台元素上*/
        perspective: 1000px;
    }
    .cube {
        height: 100%;
         100%;
        position: relative;
        /*子元素继承3D效果*/
        transform-style: preserve-3d;
        /*加上下边这句可以体现出立体感*/
        /*transform: rotateX(-30deg) rotateY(-45deg);*/
    }
    .cube>div {
         100%;
        height: 100%;
        position: absolute;
        top: 0;
        left: 0;
        background-color: rgba(0, 0, 0, .8);
        text-align: center;
        line-height: 260px;
        color: #fff;
        font-size: 48px;
        border: 2px solid #fff;
        /*设置文本内容不可选*/
        user-select: none;
    }
    .front {
        /*正面不用旋转,直接向前平移半个盒子宽*/
        transform: translateZ(130px);
    }
    .end {
        /*向后旋转,以确保盒子上的文字朝向盒子外*/
        transform: rotateY(180deg) translateZ(130px);
    }
    .top {
        transform: rotateX(90deg) translateZ(130px);
    }
    .bottom {
        transform: rotateX(-90deg) translateZ(130px);
    }
    .left {
        transform: rotateY(-90deg) translateZ(130px);
    }
    .right {
        transform: rotateY(90deg) translateZ(130px);
    }

      下来就是鼠标拖动盒子的核心代码了,先理一下思路,鼠标拖动盒子,就是记录下盒子的角度,然后点击鼠标并拖动的时候根据鼠标移动方向和距离重新计算出盒子的旋转角度,鼠标松开时取消监听,记录盒子角度。这和我之前写的一个例子鼠标拖动div 有点相似:

    var cube = document.querySelector(".cube"),
        downX, downY, moveX, moveY, tempX, tempY, degX = 0, degY = 0;
    
    window.onmousedown = function (e) {
        e = e || event;
        downX = e.clientX;          //获取鼠标点下去时的坐标
        downY = e.clientY;
    
        window.onmousemove = function (e) {
            e = e || event;
            moveX = e.clientX - downX;          //算出鼠标移动的距离
            moveY = e.clientY - downY;
            //根据一定比例将变化反应在盒子上,改变比例5可以调节拖动的速度
            tempX = degX + moveX / 5;           
            tempY = degY - moveY / 5;
            cube.style.transform = "rotatex(" + tempY + "deg) rotatey(" + tempX + "deg)";
        };
    
    };
    
    window.onmouseup = function (e) {
        e = e || event;
        degX += moveX / 5;          //鼠标松开时将拖动期间改变的最终结果保存
        degY += - moveY / 5;
        window.onmousemove = null;          //取消监听
    };

      再加一个使用滚轮改变景深的函数,因为景深太小视角会到盒子里边,并不是很好看,所以限制了一下,在景深小于300px时将不会减小。

    !function () {
        var n = 1000;
        var wraper = document.querySelector('.wraper');
        wraper.style.perspective = n + 'px';
        window.onmousewheel = function (e) {
            e = e || event;
            if (e.wheelDelta) {  //判断浏览器IE,谷歌滑轮事件
                if (e.wheelDelta > 0) { //当滑轮向上滚动时减小景深
                    wraper.style.perspective = n - 50 + 'px';
                    if (n > 350) {
                        n = n - 50;
                    }
                }
                if (e.wheelDelta < 0) { //当滑轮向下滚动时增加景深
                    wraper.style.perspective = n + 50 + 'px';
                    n += 50;
                }
            } else if (e.detail) {  //Firefox滑轮事件
                if (e.detail > 0) {
                    wraper.style.perspective = n - 50 + 'px';
                    if (n > 350) {
                        n = n - 50;
                    }
                }
                if (e.detail < 0) {
                    wraper.style.perspective = n + 50 + 'px';
                    n += 50;
                }
            }
        };
    }();

    二、最终效果图:

    3Dbox.gif

    三、代码文件图

    本例子只有一个文件如下:
    V08C0HMKxD7MA0oWGUX.png

    四、补充

      好了,到这里这个盒子看起来已经很3D了,这里是我的博客,欢迎来访。

    可拖拽的3D盒子

    代码地址如下:
    http://www.demodashi.com/demo/11453.html

    注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权

  • 相关阅读:
    URAL 2067 Friends and Berries (推理,数学)
    URAL 2070 Interesting Numbers (找规律)
    URAL 2073 Log Files (模拟)
    URAL 2069 Hard Rock (最短路)
    URAL 2068 Game of Nuts (博弈)
    URAL 2066 Simple Expression (水题,暴力)
    URAL 2065 Different Sums (找规律)
    UVa 1640 The Counting Problem (数学,区间计数)
    UVa 1630 Folding (区间DP)
    UVa 1629 Cake slicing (记忆化搜索)
  • 原文地址:https://www.cnblogs.com/twodog/p/12137397.html
Copyright © 2011-2022 走看看