Threejs 实现虚拟摇杆遨游星空 ✨✨

在做和做好是两码事,在这个人均摆烂的时代,前者足以感动自己了。

写在最前

今天短视频刷着刷着,刷到了Uzi要复出加入EDG的视频,刚开始看到熟悉的营销号的开场白感觉一眼假,于是乎我像往常一样打开评论区看看有没有比视频更精彩的评论,但刷着刷着感觉不对劲了怎么上热搜了啊,真复出了,贴吧不得狂欢人人升三级?期待一波。

扯远了,回到正题,本文将使用 threejs 实现 虚拟摇杆遨游星空的交互,通过本文你能学习到如何的实现虚拟摇杆粒子效果按键操控运动等知识,并且内容知识非常简单,相信你看完本文内容后自己动手也能实现美丽的效果。

虽说是狠久之前的学习DEMO,但稍微加工一下效果也是很NICE的~ )。

话不多说,直接开冲!

美丽的粒子效果 ??

粒子效果可以说是很多前端小伙伴入 Web3D 的理由之一,非常炫酷。

今天我们通过物体点 Points + 自定义几何体 BufferGeometry 来实现简单的星空场景

原理非常简单: 将镜头设置在一个超大的点物体内

在THREEJS中物体是通过材质和几何体构成的。

点材质

点材质是点物体默认使用的材质。他的参数值跟其他材质类似,你可以设置点的大小、颜色甚至还可以贴贴图 ~

  const material = new THREE.PointsMaterial({
    color: '#ffff00',
    size: 2,
    transparent: true,
    opacity: 0.5,
  });
  

自定义几何体

THREEJs为我们封装了非常多的网格几何体,我们也有自定义形状的需求,这个时候就需要用到BufferGeometry。从之前的文章可以了解到,几何体由无数的点形成的,所以需要提供顶点位置与颜色数据。下面是一个通过随机点生成正方体的案例。

  let vertexPoint: number[] = [];
  let size = 1000;

  for (let i = 0; i < 10000; i++) {
    let x, y, z;

    x = Math.random() * (size) - 1000 / 2;
    y = Math.random() * (size) - 1000 / 2;
    z = Math.random() * (size) - 1000 / 2;

    vertexPoint.push(x);
    vertexPoint.push(y);
    vertexPoint.push(z);
  }

  let geometry = new THREE.BufferGeometry();


  geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(vertexPoint), 3));

因为一个点需要在3D 空间中确定位置,需要设置x、y、z的3个顶点坐标。

我们通过循环生成 10000个 x、y、z方向 -500 到 500 之间的顶点数据,以此生成正方体的粒子效果。
你可以脑洞打开,生成点是最基础的,比如可以9个顶点生成三角形、12个顶点生成矩形,只要你能将点摆放好位置,你能生成各种各样的图形,非常自由~

也可以为每个点设置不同的颜色。

geometry.setAttribute('color', new THREE.BufferAttribute(colorPointer, 3))

和 WebGL Shader 是不是非常像。

最终我们通过Points生成物体

point = new THREE.Points(geometry, material)

星空效果

再设置物体绕Y轴自转,于是效果如下:

start.gif

谁不会为星点天空着迷呢?

虚拟摇杆

相信大家比我还懂什么是虚拟摇杆,他的实现方式也非常的简单,各位实现交互肯定不在话下。

拖拽 + 判断是否在圆内

拖拽无需多说,判断点是否在园内,只需要使用勾股定理

判断x到圆心的距离平方与y轴到圆心的距离平方是否小于半径的平方。

(Math.abs(x) ^ 2) + (Math.abs(y) ^ 2) < (r ^ 2)

优化: 我们知道,摇杆在拖拽滑动脱离摇杆区域时,点会停靠在中心点到当前点的线段与圆相交的地方。所以也是求中心点到当前点与中心点的X轴形成的夹角。

这时候我们的三角函数又入场了。

Math.atan2

文档

文档写的非常详细,这里就不水文字了,直接贴代码

 angle = (Math.atan2(-y, x) * 180) / Math.PI;
 angle = angle < 0 ? angle + 360 : angle; //-180 - 180 to 0 - 360

虚拟摇杆逻辑源码如下

摇杆源码

let dragControl = (e: MouseEvent) => {
  let steeringWheel = document.querySelector(".steering-wheel") as HTMLElement;
  let controlDot = document.querySelector(".control-dot") as HTMLElement;
  if (controlDot instanceof HTMLElement) {
    let {
      top: ft,
      left: fl,
      height: fh,
      width: fw,
    } = steeringWheel.getBoundingClientRect();

    window.onmousemove = (mouse) => {
      let centerPoint = {
        y: ft + fh / 2,
        x: fl + fw / 2,
      };


      let x = mouse.pageX - centerPoint.x;
      let y = mouse.pageY - centerPoint.y;
      let r = fh / 2;
      const judgePointInCircle = () => {
        if ((Math.abs(x) ^ 2) + (Math.abs(y) ^ 2) < (r ^ 2)) {
          return true;
        } else {
          return false;
        }
      };

      angle = (Math.atan2(-y, x) * 180) / Math.PI;
      angle = angle < 0 ? angle + 360 : angle;

      let isInCircle = judgePointInCircle();
      if (isInCircle) {
        controlDot.style.left = mouse.pageX - fl + "px";
        controlDot.style.top = mouse.pageY - ft + "px";
      } else {
        let x = Math.cos((angle * Math.PI) / 180) * r;
        let y = Math.sin((angle * Math.PI) / 180) * r;

        controlDot.style.left = x + r + "px";
        controlDot.style.top = -y + r + "px";
      }
    };

    window.onmouseup = () => {
      controlDot.style.left = "50%";
      controlDot.style.top = "50%";

      angle = 0;
      window.onmousemove = null;
      window.onmouseup = null;
    };
  }
};

control.gif

当算出角度后,接下来的操作都一气呵成了。

剩下的都是可自由发挥的内容,我这里举个小例子,控制小球移动。

control1.gif

虽然小球朴素了一些,但整个效果也是被漂亮的星空包裹着,瑕不掩瑜~

结尾

我们通过本文学习到了,如何渲染星空、一些2D 几何的操作和判断等。

碎碎念

每次回到家都是以一种半清醒的状态躺着刷短视频刷个1个多小时,中途多次告诉自己该做事了,可是大拇指向上滑的功夫是一点没落下,得想个办法保持回家时的状态。。回家前先洗澡?这可能是个好办法,明天试试。

各位帅哥美女们点点赞呀,你人还怪好的嘞,每次点赞都能给我无穷大的动力!!!

夜深了,困~

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYvICh0s' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片