当前位置:   article > 正文

既有方向又会动的线,包你学会制作按箭头方向流动的线(three.js实战3)_使用javascript实现的leaflet轨迹移动 曲线

使用javascript实现的leaflet轨迹移动 曲线

1.demo效果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2. 实现思路

实现思路比较简单,使用纹理材质创建网格对象,然后在render函数中改变纹理的偏移量(texture.offset.x),实现流动的效果

3. 实现要点

3.1 创建箭头流动线

  • 创建长条状平面
    使用THREE.PlaneGeometry类创建一个长条状平面,用来填充箭头纹理

  • 创建纹理材质
    使用TextureLoader纹理加载器加载纹理,然后需要设置水平方向重复10次,用该纹理作为map属性创建MeshBasicMaterial材质,同时将材质的side属性设置为THREE.DoubleSide,这样正反面都可以看到效果

  • 创建网格对象
    使用上面创建的几何体和材质使用THREE.Mesh直接创建网格对象并添加到场景中

示例代码如下

//创建条形平面-箭头流动的路径
const geometry = new THREE.PlaneGeometry(20, 2, 32);

//加载纹理
arrowLineTexture = new THREE.TextureLoader().load('../assets/textures/right.png');
arrowLineTexture.wrapS = arrowLineTexture.wrapT = THREE.RepeatWrapping; //每个都重复
arrowLineTexture.repeat.set(10, 1); //水平重复10次
arrowLineTexture.needsUpdate = true;

// 加载的纹理作为纹理贴图创建材质
let materials = new THREE.MeshBasicMaterial({
  map: arrowLineTexture,
  side: THREE.DoubleSide
});
const mesh = new THREE.Mesh(geometry, materials);
scene.add(mesh);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

3.2 创建流动线

  • 创建线条
    使用THREE.CatmullRomCurve3类创建一个线条路径,然后用该路径创建一个管道几何体

  • 创建纹理材质
    使用TextureLoader纹理加载器加载纹理,这次设置水平方向重复20次,使用纹理作为map属性创建MeshBasicMaterial材质,同时将材质的side属性设置为THREE.BackSide,transparent属性设置为true

  • 创建网格对象
    使用上面创建的几何体和材质使用THREE.Mesh直接创建网格对象并添加到场景中

// 创建线条路径
let curve = new THREE.CatmullRomCurve3([
  new THREE.Vector3(0, 0, 10),
  new THREE.Vector3(10, 0, 10),
  new THREE.Vector3(10, 0, 0),
  new THREE.Vector3(20, 0, -10)
]);

//依据线条路径创建管道几何体
let tubeGeometry = new THREE.TubeGeometry(curve, 80, 0.2);
//加载纹理
flowingLineTexture = new THREE.TextureLoader().load('../assets/textures/roadflowing1.png')

flowingLineTexture.wrapS = THREE.RepeatWrapping;
flowingLineTexture.wrapT = THREE.RepeatWrapping;
flowingLineTexture.repeat.set(20, 1); //水平重复20次
flowingLineTexture.needsUpdate = true;

//创建纹理贴图材质
let material = new THREE.MeshBasicMaterial({
  map: flowingLineTexture,
  side: THREE.BackSide, //显示背面
  transparent: true
});

let mesh = new THREE.Mesh(tubeGeometry, material);
mesh.position.z = 10;
scene.add(mesh);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

3.3 更新纹理偏移

在render函数中更新纹理偏移,有了这一步,线条就可以动起来

arrowLineTexture.offset.x -= 0.03; //更新箭头纹理偏移量
flowingLineTexture.offset.x -= 0.05; //更新流动线纹理偏移量
  • 1
  • 2

4. demo代码

<!DOCTYPE html>

<html>

<head>
  <title>流动的方向线</title>
  <script type="text/javascript" src="../three/build/three.js"></script>
  <script type="text/javascript" src="../three/examples/js/controls/OrbitControls.js"></script>
  <script type="text/javascript" src="../three/examples/js/libs/stats.min.js"></script>
  <style>
    body {
      margin: 0;
      overflow: hidden;
    }
  </style>
</head>

<body>

  <div id="Stats-output"></div>
  <div id="WebGL-output"></div>

  <script type="text/javascript">
    var scene, camera, renderer, arrowLineTexture, flowingLineTexture, stats, controls, clock;

    function initScene() {
      scene = new THREE.Scene();
      //用一张图加载为纹理作为场景背景
      scene.background = new THREE.TextureLoader().load("../assets/textures/starry-deep-outer-space-galaxy.jpg");
    }

    function initCamera() {
      camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
      camera.position.set(20, 30, 50);
      camera.lookAt(new THREE.Vector3(0, 0, 0));
    }

    function initLight() {
      //添加环境光
      const ambientLight = new THREE.AmbientLight(0x0c0c0c);
      scene.add(ambientLight);

      const directionalLight = new THREE.DirectionalLight('#fff')
      directionalLight.position.set(30, 30, 30).normalize()
      scene.add(directionalLight)

      //添加聚光灯
      const spotLight = new THREE.SpotLight(0xffffff);
      spotLight.position.set(-40, 60, -10);
      spotLight.castShadow = true;
      scene.add(spotLight);
    }

    function initModel() {

      initArrowLine()
      initFlowingLine();
      initPlane();

    }

    function initArrowLine() {
      //创建条形平面-箭头流动的路径
      const geometry = new THREE.PlaneGeometry(20, 2, 32);

      //加载纹理
      arrowLineTexture = new THREE.TextureLoader().load('../assets/textures/right.png');
      arrowLineTexture.wrapS = arrowLineTexture.wrapT = THREE.RepeatWrapping; //每个都重复
      arrowLineTexture.repeat.set(10, 1); //水平重复10次
      arrowLineTexture.needsUpdate = true;

      // 加载的纹理作为纹理贴图创建材质
      let materials = new THREE.MeshBasicMaterial({
        map: arrowLineTexture,
        side: THREE.DoubleSide
      });
      const mesh = new THREE.Mesh(geometry, materials);
      scene.add(mesh);
    }

    function initFlowingLine() {
      //加载纹理
      flowingLineTexture = new THREE.TextureLoader().load('../assets/textures/roadflowing1.png')

      flowingLineTexture.wrapS = THREE.RepeatWrapping;
      flowingLineTexture.wrapT = THREE.RepeatWrapping;
      flowingLineTexture.repeat.set(20, 1); //水平重复20次
      flowingLineTexture.needsUpdate = true;

      //创建纹理贴图材质
      let material = new THREE.MeshBasicMaterial({
        map: flowingLineTexture,
        side: THREE.BackSide, //显示背面
        transparent: true
      });

      // 创建线条路径
      let curve = new THREE.CatmullRomCurve3([
        new THREE.Vector3(0, 0, 10),
        new THREE.Vector3(10, 0, 10),
        new THREE.Vector3(10, 0, 0),
        new THREE.Vector3(20, 0, -10)
      ]);

      //依据线条路径创建管道几何体
      let tubeGeometry = new THREE.TubeGeometry(curve, 80, 0.2);
      let mesh = new THREE.Mesh(tubeGeometry, material);
      mesh.position.z = 10;
      scene.add(mesh);
    }

    //创建底面
    function initPlane() {
      const planeGeometry = new THREE.PlaneGeometry(50, 50, 1, 1); //创建一个平面几何对象

      //材质
      const planeMaterial = new THREE.MeshLambertMaterial({
        color: 0x080631,
        transparent: true,
        opacity: 0.8
      });
      const plane = new THREE.Mesh(planeGeometry, planeMaterial);

      //设置平面位置
      plane.rotation.x = -0.5 * Math.PI;
      plane.position.set(0, -2, 0);

      //平面添加到场景中
      scene.add(plane);
    }

    //初始化渲染器
    function initRender() {
      renderer = new THREE.WebGLRenderer({
        antialias: true,
        alpha: true
      });
      renderer.setClearColor(0x111111, 1); //设置背景颜色
      renderer.setSize(window.innerWidth, window.innerHeight);
      //renderer.shadowMap.enabled = true; //显示阴影
      document.getElementById("WebGL-output").appendChild(renderer.domElement);
    }
    //初始化轨道控制器
    function initControls() {
      clock = new THREE.Clock(); //创建THREE.Clock对象,用于计算上次调用经过的时间
      controls = new THREE.OrbitControls(camera, renderer.domElement);
      controls.autoRotate = true; //是否自动旋转
    }


    //性能监控
    function initStats() {
      stats = new Stats();
      stats.setMode(0); //0: fps, 1: ms
      document.getElementById("Stats-output").appendChild(stats.domElement);
    }

    function render() {

      arrowLineTexture.offset.x -= 0.03; //更新箭头纹理偏移量
      flowingLineTexture.offset.x -= 0.05; //更新流动线纹理偏移量

      const delta = clock.getDelta(); //获取自上次调用的时间差
      controls.update(delta); //控制器更新
      stats.update();
      requestAnimationFrame(render);
      renderer.render(scene, camera);
    }

    //页面初始化
    function init() {
      initScene();
      initCamera();
      initLight();
      initModel();
      initRender();
      initStats();
      initControls();
      render();
    }

    window.onload = init;
  </script>
</body>

</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/536712
推荐阅读
相关标签
  

闽ICP备14008679号