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个多小时,中途多次告诉自己该做事了,可是大拇指向上滑的功夫是一点没落下,得想个办法保持回家时的状态。。回家前先洗澡?这可能是个好办法,明天试试。

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

夜深了,困~

全部评论

相关推荐

ldyllic:飞神,985+美团+腾讯+京东,无敌飞飞神
点赞 评论 收藏
分享
老粉都知道小猪猪我很久没更新了,因为秋招非常非常不顺利,emo了三个月了,接下来说一下我的情况吧本人是双非本&nbsp;专业是完全不着计算机边的非科班,比较有优势的是有两段大厂实习,美团和字节。秋招面了50+场泡池子泡死的:滴滴&nbsp;快手&nbsp;去哪儿&nbsp;小鹏汽车&nbsp;不知名的一两个小厂其中字节13场&nbsp;两次3面挂&nbsp;两次2面挂&nbsp;一次一面挂其中有2场面试题没写出来,其他的都是全a,但该挂还是挂,第三次三面才面进去字节,秋招加暑期总共面了22次字节,在字节的面评可以出成书了快手面了8场,2次实习的,通过了但没去,一次2面挂&nbsp;最后一次到录用评估&nbsp;至今无消息滴滴三面完&nbsp;没几天挂了&nbsp;所有技术面找不出2个问题是我回答不上来的,三面还来说我去过字节,应该不会考虑滴滴吧,直接给我干傻了去哪儿一天速通&nbsp;至今无消息小鹏汽车hr&nbsp;至今无消息美团2面挂&nbsp;然后不捞我了,三个志愿全部结束,估计被卡学历了虾皮二面挂&nbsp;这个是我菜,面试官太牛逼了拼多多二面挂&nbsp;3道题也全写了&nbsp;也没问题是回答不出来的&nbsp;泡一周后挂腾讯面了5次&nbsp;一次2面挂&nbsp;三次一面挂,我宣布腾讯是世界上最难进的互联网公司然后还有一些零零散散的中小厂,但是数量比较少,约面大多数都是大厂。整体的战况非常惨烈,面试机会少,就算面过了也需要和各路神仙横向对比,很多次我都是那个被比下去的人,不过这也正常,毕竟谁会放着一个985的硕士不招,反而去招一个双非读化学的小子感觉现在互联网对学历的要求越来越高了,不仅仅要985还要硕士了,双非几乎没啥生存空间了,我感觉未来几年双非想要进大厂开发的难度应该直线上升了,唯一的打法还是从大二刷实习,然后苟个转正,不然要是去秋招大概率是炮灰。而且就我面字节这么多次,已经开始问很多ai的东西了,你一破本科生要是没实习没科研懂什么ai啊,纯纯白给了
不知名牛友_:爸爸
秋招你被哪家公司挂了?
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务