css3d--淘宝造物节demo

502 阅读4分钟
原文链接: qxfuture.com

前言

如今css3d全景已经运用到各方各面,比较好玩的一个例子就是淘宝造物节的3d例子,这个看起来还是蛮酷炫的,其实原理并不是很复杂就是利用了css3d。

css3d知识

  1. transform 属性应用于元素的2D或3D转换。这个属性允许你将元素旋转,缩放,移动,倾斜等
  2. transform-origin 属性允许您更改转换元素的位置。2D转换元素可以改变元素的X和Y轴。 3D转换元素,还可以更改元素的Z轴(transform-origin: x-axis y-axis z-axis;)
  3. translate(x,y) 沿着 X 和 Y 轴移动元素
  4. translateY(n) 沿着 X 轴移动元素
  5. translateY(n) 沿着 Y 轴移动元素
  6. translateZ(n) 沿着 Z 轴移动元素
  7. scale(x,y) 定义 2D 缩放, 改变元素的宽度和高度
  8. scale3d(x,y,z) 定义 3D 缩放
  9. scaleX(x) scaleY(y) scaleZ(z) 对应所在轴的缩放
  10. rotate3d(x,y,z,angle) 3D 旋转
  11. rotateX(angle) 沿 X 轴的 3D 旋转。
  12. rotateY(angle) 沿 Y 轴的 3D 旋转。
  13. rotateZ(angle) 沿 Z 轴的 3D 旋转。
  14. perspective(n) 属性定义 3D 元素距视图的距离,以像素计。该属性允许您改变 3D 元素查看 3D 元素的视图。当为元素定义 perspective 属性时,其子元素会获得透视效果,而不是元素本身。perspective 属性只影响 3D 转换元素。可以简单的理解为视距,用来设置用户和元素3D空间Z平面之间的距离。而其效应由他的值来决定,值越小,用户与3D空间Z平面距离越近,视觉效果更令人印象深刻;反之,值越大,用户与3D空间Z平面距离越远,视觉效果就很小。
  15. perspective-origin 属性是3D变形中另一个重要属性,主要用来决定perspective属性的源点角度。它实际上设置了X轴和Y轴位置(或者说基点),在该位置观看者好像在观看该元素的子元素。

实战淘宝造物节demo

实现简介

首先我们需要找一张全景图,然后等分分成多分,越多分组成的圆越越平滑。把各个图片分配到div,首先通过旋转div的Y轴,旋转后再在Z轴进行位移就可以组成一个类似圆筒,然后通过调节视距和源点来调节最佳角度,最后使用js监听触摸事件来移动盒子最终实现3d的效果。
拼接的计算公式如下

图1 图1

html代码

<div id="container" class="container">
    <div id='box'>
        <div>0</div>
        <div>1</div>
        <div>2</div>
        <div>3</div>
        <div>4</div>
        <div>5</div>
        <div>6</div>
        <div>7</div>
        <div>8</div>
        <div>9</div>
        <div>10</div>
        <div>11</div>
        <div>12</div>
        <div>13</div>
        <div>14</div>
        <div>15</div>
        <div>16</div>
        <div>17</div>
        <div>18</div>
        <div>19</div>
    </div>
</div>


css代码

.container{
    margin: 0 auto 0 auto;
    width: 8.0625rem;
    perspective: 25rem;/*视距*/
}

#box{
    -webkit-transform-style: preserve-3d;/*表示所有子元素在3D空间中呈现*/
    height: 100%;
    -webkit-perspective-origin: 50% 50%;/*源点角度*/
}

#box > div{
    position: absolute;
    width: 8.0625rem;
    height: 73.125rem;
    
}


js代码

var container = document.getElementById('container');
var box = document.getElementById('box');//获取盒子
var arr = box.getElementsByTagName('div');//获取需要拼接的div
var radius = calculateRadius(129, 20);//计算Z轴需要的位移

for (var i = 0; i < arr.length; i++) {//给div赋值 背景图片
    arr[i].style.background = 'url("./img/p' + (i + 1) + '.png") no-repeat';
    arr[i].style.WebkitTransform = "rotateY(" + 360 / arr.length * i + 'deg) translatez(' + radius + 'px)';
}

/**
* 通过三角函数计算出距离
* @param {素材宽度} length 
* @param {素材总数} totalNum 
*/
function calculateRadius(length, totalNum) {
    return Math.round(length / (2 * Math.tan(Math.PI / totalNum))) - 3;
}


var startX = 0,//开始时的坐标
    x = 0,//旋转的差值
    endX = 0;//手离开时候的坐标
var flag = true;//区分 手触摸 还是 陀螺仪
//手开始触碰时的监听
$('#box').on('touchstart', function(event) {
    event.preventDefault();
    var touch = event.targetTouches[0];//触碰的范围会返回很多坐标点 取第一个即可
    startX = touch.pageX - x;//记录手开始触碰时的 X坐标,由于我们是左右移动只要记录X就行了
})
//手移动时的监听
$('#box').on('touchmove', function(event) {
    if (flag) {
        event.preventDefault();
        var touch = event.targetTouches[0];
        endX = touch.pageX;
        x = endX - startX;//在移动中 用 endX与startX相减就得到 差值,box旋转差值即可
        box.style.transform = 'rotateY(' + x + 'deg)';
    } else {
        return false;
    }

})
//手离开屏幕时的监听
$('#box').on('touchend', function(event) {
    console.log("over");
});


window.addEventListener('deviceorientation', function(event) {

    var gamma = event.gamma;
    if (Math.abs(gamma) > 1) {
        flag = false;
        box.style.transform = 'rotateY(' + gamma * 3 + 'deg)';
    } else {
        flag = true;
    }

})


demo演示

淘宝造物节demo