首页 > 技术文章 > THREE.JS(如何想场景中添加物体对象)

createGod 原文

这篇主要实现向模型对象中添加头像,并组成一个矩形

一、three.js是什么?

上篇说了点TWEEN这篇又来一根THREE是不是两兄弟啊?还真有点像,当想要做3D动画的时候,可能会考虑用TWEEN的动画函数。

其实THREE.JS就是实现3D效果的WEBGL的模型库。内容涵盖量大,目前的技术博文较少,要领会其中部分API需要一点功夫啊。

二、如何建立一个3D模型呢?

先来一个HTML代码。看看我们需要哪些东西

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Demo</title>
    <style>
        html,body{
            width: 100%;
            height: 100%;
            background: #000;
        }
        a {
            color: #8888ff;
        }
        #info {
            position: absolute;
            width: 100%;
            color: #000000;
            padding: 5px;
            font-family: Monospace;
            font-size: 13px;
            font-weight: bold;
            text-align: center;
            z-index: 1;
        }
        .element {
            width: 100px;
            height: 100px;
            box-shadow: 0px 0px 12px rgba(0,255,255,0.5);
            border: 1px solid rgba(127,255,255,0.25);
            text-align: center;
            cursor: default;
            border-radius: 50%;
            overflow: hidden;
        }

        .element2:hover {
            box-shadow: 0px 0px 12px rgba(0,255,255,0.75);
            border: 1px solid rgba(127,255,255,0.75);
        }

        .element .number {
            position: absolute;
            top: 20px;
            right: 20px;
            font-size: 12px;
            color: rgba(127,255,255,0.75);
            display: none;
        }

        .element .symbol {
            position: absolute;
            top: 0;
            left: 0px;
            right: 0px;
            width: 100%;
            height: 100%;
        }

        .element .details {
            position: absolute;
            bottom: 10px;
            left: 0px;
            right: 0px;
            font-size: 12px;
            color: rgba(127,255,255,0.75);
            height:15px;
            line-height:15px;
            font-size: 12px;
            font-weight: bold;
            color: rgba(255,255,255,0.75);
            text-shadow: 0 0 10px rgba(0,255,255,0.95);
            overflow: hidden;
            display: none;
        }
        #container img{
            border-radius: 0!important;
        }
        #animation{
            -webkit-animation:rollOut .5s .2s ease both;
            -moz-animation:rollOut .5s .2s ease both;
        }
        @-webkit-keyframes rollOut{
            0%{
                opacity:1;
                -webkit-transform:translateX(0px) rotate(0deg);
                left: 0px;
                top:0px;
                width: 200px;
            }

            100%{
                opacity:0;
                -webkit-transform:translateX(100%) rotate(240deg);
                left:800px;
                top:500px;
                width: 0px;
            }
        }
        @-moz-keyframes rollOut{
            0%{
                opacity:1;
                -moz-transform:translateX(0px) rotate(0deg);
                left: 0px;
                top:0px;
                width: 200px;
            }
            100%{
                opacity:0;
                -moz-transform:translateX(100%) rotate(120deg);
                left:1400px;
                top:500px;
                width: 0px;
            }
        }
    </style>
</head>
<body>
    <div id="container"></div> </body> <script src="js/jquery-1.12.4.js"></script> <script src="js/three.js"></script> <script src="js/CSS3DRenderer.js"></script> <script src="js/tween.min.js"></script> <script src="js/TrackballControls.js"></script> <script src="js/demo.js"></script> </html>

从上面看到主要引进了three.js。CSS3DRenderer.js(css3模型渲染器)。TrackballControls.js(可以理解为场景控制器吧); tween.min.js 这篇就不说了。也用不上。

var demoConfig = {
    'fakeNum': 500,       //500张头像图片
    'fakeUserImgTpl': "head/pic_#id#.jpg", //图片路径
    'fakeUserTpl': {     //对每个图片的描述
        "id": "#id#",
        "cont": "爽歪歪",
        "name": "3D模型",
        "img": "#img#"
    }
};
var camera,scene,renderer,contols,obj;
//相机, 场景, 渲染器, 控制器, 物体对象。
var fakeUserArr = (function () {
    var arr = [], picNum = demoConfig['fakeNum'];
    var fakeUserTpl = demoConfig['fakeUserTpl'], fakeUserImgTpl = demoConfig['fakeUserImgTpl'];
    for (var i = 0; i < picNum; i++) {
        var userId = (i + 1), img = fakeUserImgTpl.replace(/#id#/gi, (i + 1));
        userId = 'fake' + userId;
        var fakeUser = $.extend({}, fakeUserTpl, {"id": userId, "img": img});
        arr.push(fakeUser);
    }
    return arr;
})();
var appendImg = function(userJson,i){
    var image = document.createElement('img');
    var element = document.createElement('div');
    var objId = 'user_' + userJson['id'];
    element.setAttribute("id", objId);
    element.className = 'element fakeuser';

    element.style.backgroundColor = 'rgba(0,127,127,' + ( Math.random() * 0.5 + 0.25 ) + ')';

    image.className = 'symbol';
    element.appendChild(image);
    image.src = userJson['img'];

    // var object = new THREE.CSS3DSprite( element );//头像正对镜头
    var object = new THREE.CSS3DObject(element);//头像平贴平面
    object.objId = objId;

    object.position.x = Math.random() * 3000 - 2000; //随机位置
    object.position.y = Math.random() * 3000 - 2000;
    object.position.z = Math.random() * 3000 - 2000;
    obj.add(object);
}
var width = window.innerWidth,height = window.innerHeight,doc = document;
var init = function () {
    //创建相机
    camera = new THREE.PerspectiveCamera(75, width / height, 1, 5000);
    camera.position.z = 2500;  //相机的位置
    //参数啥意思呢?
    //设置透视投影的相机,默认情况下相机的上方向为Y轴,右方向为X轴,
    // 沿着Z轴朝里(视野角:fov 纵横比:aspect 相机离视体积最近的距离:near 相机离视体积最远的距离:far)

    scene = new THREE.Scene();//创建场景
    obj = new THREE.Object3D(); //物体对象
    scene.add(obj);  //把物体放置到场景中

    for(var i = 0,l = fakeUserArr.length; i < l; i++ ){
        appendImg(fakeUserArr[i],i);
    }

    //创建渲染器
    renderer = new THREE.CSS3DRenderer();
    renderer.setSize(width,height); //设置尺寸
    renderer.domElement.style.position = 'absolute'; //渲染器的style
    doc.getElementById('container').appendChild(renderer.domElement); //把渲染器添加到场景中


    //创建场景控制器
    contols = new THREE.TrackballControls(camera,renderer.domElement);
    contols.rotateSpeed = 0.5;  //旋转速度
    contols.minDistance = 500;   //滚动滚动时的缩放距离 最大
    contols.maxDistance = 10000; // 最小

    renderer.render(scene,camera);  //把物体对象添加到渲染器中
};

init();

这样就把头像点放到渲染器里面去了。那怎么拼成各种图形呢?

三、如何把像素点拼成各种图形?

1.矩形。

其实我们仔细想如何才能把头像拼成矩形呢?我们可以把一个矩形先画出来,再取像素点,把位置头像放到对应位置不就行了吗?写个方法把坐标点保存下来。

table = function (i) {
    var x = i / 18;
    var y = i % 18;
    var object = new THREE.Object3D();
    object.position.x = ( x * 140 ) - 1330;
    object.position.y = -( y * 180 ) + 1100;
    return object;
}

完整代码:

/**
 * Created by Administrator on 2017/6/13.
 */
var demoConfig = {
    'fakeNum': 500,       //500张头像图片
    'fakeUserImgTpl': "head/pic_#id#.jpg", //图片路径
    'fakeUserTpl': {     //对每个图片的描述
        "id": "#id#",
        "cont": "爽歪歪",
        "name": "3D模型",
        "img": "#img#"
    }
};
var camera,scene,renderer,contols,obj;
//相机, 场景, 渲染器, 控制器, 物体对象。
var fakeUserArr = (function () {
    var arr = [], picNum = demoConfig['fakeNum'];
    var fakeUserTpl = demoConfig['fakeUserTpl'], fakeUserImgTpl = demoConfig['fakeUserImgTpl'];
    for (var i = 0; i < picNum; i++) {
        var userId = (i + 1), img = fakeUserImgTpl.replace(/#id#/gi, (i + 1));
        userId = 'fake' + userId;
        var fakeUser = $.extend({}, fakeUserTpl, {"id": userId, "img": img});
        arr.push(fakeUser);
    }
    return arr;
})();
var appendImg = function(userJson,i){
    var image = document.createElement('img');
    var element = document.createElement('div');
    var objId = 'user_' + userJson['id'];
    element.setAttribute("id", objId);
    element.className = 'element fakeuser';

    element.style.backgroundColor = 'rgba(0,127,127,' + ( Math.random() * 0.5 + 0.25 ) + ')';

    image.className = 'symbol';
    element.appendChild(image);
    image.src = userJson['img'];

    // var object = new THREE.CSS3DSprite( element );//头像正对镜头
    var object = new THREE.CSS3DObject(element);//头像平贴平面
    object.objId = objId;

    object.position.x = tableArr[i].position.x; //随机位置
    object.position.y = tableArr[i].position.y;
    object.position.z = tableArr[i].position.z;
    obj.add(object);
}
table = function (i) {
    var x = i / 18;
    var y = i % 18;
    var object = new THREE.Object3D();
    object.position.x = ( x * 140 ) - 1330;
    object.position.y = -( y * 180 ) + 1100;
    return object;
}
var width = window.innerWidth,height = window.innerHeight,doc = document,tableArr = [];

for(var i = 0 ; i < 500; i++){
    tableArr.push(table(i));
}
var init = function () {
    //创建相机
    camera = new THREE.PerspectiveCamera(75, width / height, 1, 5000);
    camera.position.z = 2500;  //相机的位置
    //参数啥意思呢?
    //设置透视投影的相机,默认情况下相机的上方向为Y轴,右方向为X轴,
    // 沿着Z轴朝里(视野角:fov 纵横比:aspect 相机离视体积最近的距离:near 相机离视体积最远的距离:far)

    scene = new THREE.Scene();//创建场景
    obj = new THREE.Object3D(); //物体对象
    scene.add(obj);  //把物体放置到场景中

    for(var i = 0,l = fakeUserArr.length; i < l; i++ ){
        appendImg(fakeUserArr[i],i);
    }

    //创建渲染器
    renderer = new THREE.CSS3DRenderer();
    renderer.setSize(width,height); //设置尺寸
    renderer.domElement.style.position = 'absolute'; //渲染器的style
    doc.getElementById('container').appendChild(renderer.domElement); //把渲染器添加到场景中


    //创建场景控制器
    contols = new THREE.TrackballControls(camera,renderer.domElement);
    contols.rotateSpeed = 0.5;  //旋转速度
    contols.minDistance = 500;   //滚动滚动时的缩放距离 最大
    contols.maxDistance = 10000; // 最小

    renderer.render(scene,camera);  //把物体对象添加到渲染器中
};

init();

好,本篇到此为止。主要是讲如何把像素点渲染到场景中去,下面几篇会结合TWEEN讲述动画,以及如何生成定制LOGO。如何让每个头像动起来,并且停在相应的位置。

四、结束篇。

每天学习一点,坚持做同一样事情,离老菜鸟就不远了。还是那句话, 当一个东西要入门的话,一定要敲,要写demo,去推演,不然你永远不知道

哪些地方埋有炸弹。

推荐阅读