飞行者动画 根据Three.js动画飞行者改编而成

32 篇文章 0 订阅
2 篇文章 0 订阅

飞行者动画 根据Three.js动画飞行者改编而成

这里写图片描述
这是图片

HTML部分

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Page Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <style>
    #world {
   position: absolute;
   width: 100%;
   height: 100%;
   overflow: hidden;
   background: linear-gradient(#e4e0ba, #f7d9aa);
}
    </style>
</head>
<body>
    <div id="world"></div>
</body>
<script src="js/three.js"></script>

<script src="js/stats.js"></script>
<script src="js/main.2.js"></script>
</html>

JS部分

var Colors = {
    red: 0xf25346,
    yellow: 0xedeb27,
    white: 0xd8d0d1,
    brown: 0x59332e,
    pink: 0xF5986E,
    brownDark: 0x23190f,
    blue: 0x404040,
    green: 0x458248,
    purple: 0x551A8B,
    lightgreen: 0x629265,
    a: 0x666666,
    b: 0x7B68EE,
    c: 0x8C8C8C,
    d: 0xDBDBDB
};
//
var scene, 
    camera, fieldOfView, aspectRatio, nearPlane, farPlane, 
    renderer, container;
//不可以使用width,height小写  不了你都不知道自己错在哪
var WIDTH,HEIGHT,
    mousePos = {x:0,y:0};


function createScene() {
    HEIGHT = window.innerHeight;
    WIDTH = window.innerWidth;

    //创建场景
    scene = new THREE.Scene();
    //设置相机宽高比
    aspectRatio = WIDTH / HEIGHT;
    //设置相机垂直视角角度
    fieldOfView = 60;
    //设置最近距离
    nearPlane = 1;
    //设置最远距离
    farPlane = 10000;
    //创建相机
    camera = new THREE.PerspectiveCamera(
        fieldOfView,
        aspectRatio,
        nearPlane,
        farPlane
    );
   scene.fog = new THREE.Fog(0xf7d9aa, 100, 950);
    //设置相机位置

    // camera.position.x = 0;
    // camera.position.z = 200;
    // camera.position.y = 100;

    camera.position.x = -300;
    camera.position.z = 0;
    camera.position.y = 300;
    camera.lookAt(scene.position);

    //创建渲染器
    renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
    //定义渲染器尺寸
    renderer.setSize(WIDTH, HEIGHT);
    //打开渲染器阴影地图
    renderer.shadowMap.enabled = true;

    //将渲染器添加到HTML中
    container = document.getElementById('world');
    container.appendChild(renderer.domElement);
    //监听屏幕尺寸,如果屏幕尺寸发生变化 我们需要更新渲染器和相机
    window.addEventListener('resize', windowResize, false);
}

function windowResize() {
    HEIGHT = window.innerHeight;
    WIDTH = window.innerWidth;
    //渲染器大小重新赋值
    renderer.setSize(WIDTH, HEIGHT);
    //相机宽高比重新赋值
    camera.aspect = WIDTH / HEIGHT;
    camera.updateProjectionMatrix();
}
//创建光源函数

var ambientLight,hemisphereLight,shadowLight;

function createLights() {
    //半球光//
    hemisphereLight = new THREE.HemisphereLight(0xaaaaaa, 0x000000, 0.9);
    // scene.add(hemisphereLight);
    //平行光
    shadowLight = new THREE.DirectionalLight(0xffffff, 0.9);
    //设置平行光方向
    shadowLight.position.set(150, 350, 350);
    //开启投影
    shadowLight.castShadow = true;
    //定义可见投影
    shadowLight.shadow.camera.left = -400;
    shadowLight.shadow.camera.right = 400;
    shadowLight.shadow.camera.top = 400;
    shadowLight.shadow.camera.bottom = -400;
    shadowLight.shadow.camera.near = 1;
    shadowLight.shadow.camera.far = 1000;
    // 定义阴影的分辨率(精准度)
    shadowLight.shadow.mapSize.width = 1024;
    shadowLight.shadow.mapSize.height = 1024;
    //将光源添加到场景中
    scene.add(hemisphereLight);
     scene.add(shadowLight);
    // 环境光源修改场景中的全局颜色和使阴影更加柔和
    ambientLight = new THREE.AmbientLight(0xdc8874, .5); scene.add(ambientLight);
    scene.add(ambientLight);
}

//现在开始我们要制作飞机了

var AirPlane = function () {
    //老套路  先创建一个容器
    this.mesh = new THREE.Object3D();
    this.mesh.name = "airPlane";
    //创建机舱(长宽高分段)
    var geomCockpit = new THREE.BoxGeometry(60,50,50,1,1,1);
    //这里   访问它的定点改变定点的位置
    //4 5是在飞机尾部上方的两个点
    //6 7是飞机尾部下方的两个点
    geomCockpit.vertices[4].y -= 10;
    geomCockpit.vertices[4].z += 20;
    geomCockpit.vertices[5].y -= 10;
    geomCockpit.vertices[5].z -= 20;
    geomCockpit.vertices[6].y += 20;
    geomCockpit.vertices[6].z += 20;
    geomCockpit.vertices[7].y += 20;
    geomCockpit.vertices[7].z -= 20;
    //创建材质
    var matCockpit = new THREE.MeshPhongMaterial({
        color: Colors.red,
        //着色模式
        shading: THREE.FlatShading
    });

    var cockpit = new THREE.Mesh(geomCockpit, matCockpit);
    //设置机舱接收阴影和生成阴影
    cockpit.castShadow = true;
    cockpit.receiveShadow = true;
    //把机舱添加到容器中
    this.mesh.add(cockpit);
    //创建引擎
    var geomEngine = new THREE.BoxGeometry(20,50,50,1,1,1);
    //创建引擎材质
    var matEngine = new THREE.MeshPhongMaterial({
        color: Colors.white,
        shading: THREE.FlatShading
    });
    var engine = new THREE.Mesh(geomEngine, matEngine);
    //改变引擎位置
    engine.position.x = 40;
    //设置引擎生成阴影和接收阴影
    engine.castShadow = true;
    engine.receiveShadow = true;
    //将引擎添加到容器中
    this.mesh.add(engine);

    // 创建机尾(长 宽 高 分段)
    var geomTailPlane = new THREE.BoxGeometry(15,20,5,1,1,1);
    //这里我们访问机尾的定点
    geomTailPlane.vertices[1].x -= 5;
    geomTailPlane.vertices[0].x -= 5;
    //创建机尾材质
    var matTailPlane = new THREE.MeshPhongMaterial({
        color: Colors.red,
        shading: THREE.FlatShading
    });
    var tailPlane = new THREE.Mesh(geomTailPlane, matTailPlane);
    //机尾位置
    tailPlane.position.set(-22, 15, 0);
    //生成阴影和接收阴影
    tailPlane.castShadow = true;
    tailPlane.receiveShadow = true;
    //添加至容器
    this.mesh.add(tailPlane);

    var geomSideWing = new THREE.BoxGeometry(40, 8, 150, 1, 1, 1);
    var matSideWing = new THREE.MeshPhongMaterial({ 
        color: Colors.red, 
        shading: THREE.FlatShading 
    });
    var sideWing = new THREE.Mesh(geomSideWing, matSideWing);
    sideWing.position.set(0, 0, 0);
    sideWing.castShadow = true;
    sideWing.receiveShadow = true;
    this.mesh.add(sideWing);

    // 创建螺旋桨
    var geomPropeller = new THREE.BoxGeometry(20,10,10,1,1,1);
    var matPropeller = new THREE.MeshPhongMaterial({
        color: Colors.brown,
        shading: THREE.FlatShading
    });
    this.propeller = new THREE.Mesh(geomPropeller, matPropeller);
    this.propeller.castShadow = true;
    this.propeller.receiveShadow = true;

    // 创建螺旋桨的桨叶
    var geomBlade = new THREE.BoxGeometry(1,100,20,1,1,1);
    var matBlade = new THREE.MeshPhongMaterial({
        color: Colors.brownDark,
        shading: THREE.FlatShading
    });

    var blade = new THREE.Mesh(geomBlade, matBlade);
    blade.position.set(8,0,0);
    blade.castShadow = true;
    blade.receiveShadow = true;
    //将螺旋桨叶添加到螺旋桨中
    this.propeller.add(blade);
    //定义螺旋桨位置
    this.propeller.position.set(50, 0, 0);
    this.mesh.add(this.propeller);

};

// 定义一个天空对象
Sky = function () {
    // 创建一个空的容器
    this.mesh = new THREE.Object3D();

    // 选取若干朵云散布在天空中
    this.nClouds = 50;
    this.clouds = [];
    // 把云均匀地散布
    // 我们需要根据统一的角度放置它们
    var stepAngle = Math.PI * 2 / this.nClouds;

    // 创建云对象
    for (var i = 0; i < this.nClouds; i++) {
        var c = new Cloud();

        // 设置每朵云的旋转角度和位置
        // 因此我们使用了一点三角函数
        var a = stepAngle * i; //这是云的最终角度
        var h = 750 + Math.random() * 100; // 这是轴的中心和云本身之间的距离

        // 三角函数!!!希望你还记得数学学过的东西 :)
        // 假如你不记得:
        // 我们简单地把极坐标转换成笛卡坐标
        c.mesh.position.y = Math.sin(a) * h;
        c.mesh.position.x = Math.cos(a) * h;

        // 根据云的位置旋转它
        c.mesh.rotation.z = a + Math.PI / 2;

        // 为了有更好的效果,我们把云放置在场景中的随机深度位置
        c.mesh.position.z = -800 + Math.random() * 1900;
      //  c.mesh.position.z = -400 - Math.random() * 400;

        // 而且我们为每朵云设置一个随机大小
        var s = 1 + Math.random() * 2;
        c.mesh.scale.set(s, s, s);

        // 不要忘记将每朵云的网格添加到场景中
        this.mesh.add(c.mesh);
    }
}


Sea = function () {
    //创建大海  先创建一个圆柱体(顶面半径,底部半径,高,半径分段,高分段)
    var geom = new THREE.CylinderGeometry(600, 600, 1400, 40, 10);
    //在x轴向上逆时针旋转90 //这里用rosition不可以吗?
    geom.applyMatrix(new THREE.Matrix4().makeRotationX(-Math.PI / 2));
    //创建材质
    var mat = new THREE.MeshPhongMaterial({
        //颜色
        color: Colors.blue,
        //透明度
        opacity: 1,
        //貌似是是否透明
        transparent: true,
        //shading着色模式可选值:THREE.SmoothShading、THREE.FlatShading。
        shading: THREE.FlatShading,

    });
    this.mesh = new THREE.Mesh(geom, mat);
    this.mesh.receiveShadow = true;
}


Cloud = function () {
    //一个容器
    this.mesh = new THREE.Object3D();
    this.mesh.name = "cloud";
    //正方体
    var geom = new THREE.BoxGeometry(20, 20, 20);
    //材质
    var mat = new THREE.MeshPhongMaterial({
        color: Colors.white
    });
    //随机复制3-8个几何体
    var nBlocs = 3 + Math.floor(Math.random() * 3);
    //开始循环创建
    for (var i = 0; i < nBlocs; i++) {
        //创建网络
        var m = new THREE.Mesh(geom.clone(), mat);
        //随机设置每个正方体的旋转角度以及每个正方体的位置
        m.position.x = i * 15; //固定x
        m.position.y = Math.random() * 10; //随机y轴位置 大于0
        m.position.z = Math.random() * 10; //随机z轴位置
        m.rotation.y = Math.random() * Math.PI * 2;//随机y轴旋转角度
        m.rotation.z = Math.random() * Math.PI * 2;//随机z轴旋转角度
        // 随机设置正方体的大小
        var s = .1 + Math.random() * 0.9;
        m.scale.set(s, s, s);

        // 允许每个正方体生成投影
        m.castShadow = true;
        //允许每个正方体接收投影
        m.receiveShadow = true;
        //添加至容器
        this.mesh.add(m);
    }
}
var petalColors = [Colors.a, Colors.b, Colors.c];
Build = function () {
    //创建一个容器
    this.mesh = new THREE.Object3D();
    //设置一个长方体
    var geonBuildBase = new THREE.BoxGeometry(30, 170, 30);
    var petalColor = petalColors[Math.floor(Math.random() * 3)];
    //设置材质
    var matBuildBase = new THREE.MeshPhongMaterial({ color: petalColor });
    //添加到BuildBase中
    var buildBase = new THREE.Mesh(geonBuildBase, matBuildBase);
    buildBase.castShadow = true;
    buildBase.receiveShadow = true;
    //加入容器中
    this.mesh.add(buildBase);
}
Building = function () {
    this.mesh = new THREE.Object3D();
    // 建筑物的数量
    this.nBuilds = 900;
    // 根据统一的角度平均放置他们
    var stepAngle = Math.PI * 2 / this.nBuilds;
    // 创建建筑物
    for (var i = 0; i < this.nBuilds; i++) {
        var t = new Build();
        //这是建筑物最终的角度
        var a = stepAngle * i;
        // 这是轴中心与地面之间的距离
        var h = 605;
        t.mesh.position.y = Math.sin(a) * h;
        t.mesh.position.x = Math.cos(a) * h;

        //摆正建筑物的角度
        t.mesh.rotation.z = a + (Math.PI / 2) * 3;

        // 随机放到0到1400的随机位置
        t.mesh.position.z = 0 - Math.random() * 1400;

        // 0.3到1之间随机创建大小
        var s = .3 + Math.random() * .75;
        t.mesh.scale.set(s, s, s);

        this.mesh.add(t.mesh);
    }


}


var sea;
var airplane;
var building;
function createPlane() {
    airplane = new AirPlane();
    airplane.mesh.scale.set(.25, .25, .25);
    airplane.mesh.position.y = 100;
    scene.add(airplane.mesh);
}

function createSea() {
    sea = new Sea();
    sea.mesh.position.y = -600;
  //  sea.mesh.position. = -300;
    scene.add(sea.mesh);
}



// 现在我们实例化天空对象,而且将它放置在屏幕中间稍微偏下的位置。
function createSky() {
    sky = new Sky();
    sky.mesh.position.y = -600;
    scene.add(sky.mesh);
}

function createBuildings() {
    building = new Building();
    building.mesh.position.y = -600;
    building.mesh.position.z = 600;
    scene.add(building.mesh);
}




//渲染我们的场景


function loop() {
    updatePlane();
    // 螺旋桨旋转
    airplane.propeller.rotation.x += 0.3;
    //天空沿z轴旋转
    sea.mesh.rotation.z += .005;
    //大海沿z轴旋转
    sky.mesh.rotation.z += .01;
    building.mesh.rotation.z += .005;
    // 更新每帧的飞机
   // updatePlane();

    // 重新渲染场景
    renderer.render(scene, camera);

    // 重新调用 render() 函数
    requestAnimationFrame(loop);
}
    var mousePos = {x:0,y:0};
function init(event) {
    //监听器监听鼠标移动
    document.addEventListener('mousemove', getMousePos, false);
    createScene();
    createLights();
    createPlane();
    createSea();
    createSky();
    createBuildings();
    loop();
}
//当鼠标发生移动时 调用getMousePos函数
function getMousePos(event) {
    var tx = + (event.clientX / WIDTH) * 2 - 1;

    // 对于 y 轴,我们需要一个逆公式
    // 因为 2D 的 y 轴与 3D 的 y 轴方向相反

    var ty = 1 - (event.clientY / HEIGHT) * 2;
    mousePos = { x: tx, y: ty };
    //推到过程 https://blog.csdn.net/ruangong1203/article/details/60476721
}

function updatePlane() {
    var targetZ = normalize(mousePos.x, -1, 1, -200, 200);
    var targetY = normalize(mousePos.y, -1, 1, 50, 175);
   // var targetY = mousePos.y;
    airplane.mesh.position.z = targetZ;
    airplane.mesh.position.y = targetY;
    //airplane.mesh.position.y = targetY;

}


//
function normalize(v, vmin, vmax, tmin, tmax) {

    var nv = Math.max(Math.min(v, vmax), vmin);
    var dv = vmax - vmin;
    var pc = (nv - vmin) / dv;
    var dt = tmax - tmin;
    var tv = tmin + (pc * dt);
    return tv;
}



window.addEventListener('load', init, false)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值