threejs路径

路径

引用百度百科的解释:

路径通常指存在于多种计算机图形设计软件中的以贝塞尔曲线为理论基础的区域绘制方式。

路径在Canvas、SVG上都有相关定义,一般用来创建形状。在threejs中,也可以用来创建形状,除此之外,还可以用作物体运动的轨迹。下面就说说这两种用法。

在threejs中,Path类代表路径,Path继承自CurvePath(曲线路径),CurvePath继承自Curve(曲线)。CurvePath和Curve都是抽象类,在threejs文档中指出,CurvePath用来连接多条曲线(也就是Curve),其实质上就是一个Curve数组。其实,直接用Path类就可以了,对于CurvePath和Curve,无需关心。

另外还有一个ShapePath类,这个类可以将形状转成一系列路径来表示,比如将svg绘制的图形转成threejs的路径。

使用路径创建形状

关于使用路径创建形状,可以参考【创建平面几何形状一文】,其中的Shape类,就是Path类的子类,这里不多说。

使用路径作为物体运动轨迹

如果我们想要物体沿着某一条曲线运动,有两种办法:
1、算出曲线的公式,动态的计算出物体当前时刻的位置
2、创建一条代表该曲线的路径,然后动态的在该曲线上取点,将其位置赋给物体
一般,路径类会提供多种创建路径的方法,所以,第2种方式通常比较好用。

下面就使用threejs提供的Path类创建一条移动轨迹,然后把相机在这条轨迹上移动。开始的开始,先创建一条路径,如下:

       path = new THREE.Path();
       path.bezierCurveTo(10,100,20,-30,30,19);
       path.bezierCurveTo(40,-5,50,150,60,-39);
       path.closePath();

接着在render循环中动态的从路径中取点,设置成相机的位置:

var progress = 0;
function render(){
  requestAnimationFrame(render);
        progress += 0.003;
        let point = path.getPointAt(progress);
        if(point){
          camera.position.set(point.x,point.y,300);
        }else{
          progress = 0;
        }
        renderer.render(scene,camera);
}

上面的progress是比例,范围从0~1.完整示例请看【完整示例

将svg形状转成路径

svg是一种矢量图形格式,同时,javascript也有创建和修改这种图形格式的接口。各种表示矢量图形的技术,如Canvas、SVG,本质上是相同或相通的,只不过是实现和接口不一样,所以,是有转化的可能的。

在svg中,下面的代码创建了一条从(0,0)到(100,100)的直线路径:

<path d="M0 0 L 100 100"/>

而在threejs中,使用ShapePath创建一条直线路径使用:

let path = new ShapePath();
path.moveTo(0,0);
path.lineTo(100,100);

可见,两者的形式是相近的,从形式上来看,简单的转换难度也不会很大。下面是一个转换的例子:

function createShapes(){
   let dataString = getSvgData();  //获取svg数据
   let shape = transformToShapePath(dataString); //转换成ShapePath表示
   let geometry = new THREE.ShapeGeometry(shape);
   let material = new THREE.LineBasicMaterial({color:0xff0000});
   let mesh = new THREE.Line(geometry,material);
   scene.add(mesh);
   camera.lookAt(mesh.position);
}

//获取svg数据,数据来自w3cschool
function getSvgData(){
   let svgData = "M153 334 C153 334 151 334 151 334 C151 339 153 344 156 344 C164 344 171 339 171 334 C171 322 164 314 156 314 C142 314 131 322 131 334 C131 350 142 364 156 364 C175 364 191 350 191 334 C191 311 175 294 156 294 C131 294 111 311 111 334 C111 361 131 384 156 384 C186 384 211 361 211 334 C211 300 186 274 156 274";
   return svgData;
}

//转换成ShapePath表示
function transformToShapePath(dataString){
        let path = new THREE.ShapePath();
        let dataArr = dataString.split(" ");
        var currIndex = 0;
        while(currIndex<dataArr.length){
            let command = dataArr[currIndex][0];
            switch(command){
              case 'M' : {
                let inc = moveParse(currIndex,dataArr,path);
                  currIndex += inc;
                  break;
              }
              case 'C' : {
                let inc = curveParse(currIndex,dataArr,path);
                currIndex += inc;
                break;
              }
              default:{
                //出错处理
                currIndex++;
              }
           }
        }
        return path.toShapes()[0];
}


/**************下面是各种命令的转换器****************/
        //moveTo命令转换器
        function moveParse(currIndex,dataArr,path){
           let paramsLength = 2; //需要的参数个数
           let data = [dataArr[currIndex].substring(1),dataArr[currIndex+1]];
           toThreejsCoor(data);
           path.moveTo(data[0],data[1]);
           return paramsLength;
        }

        //Curve命令转换器
        function curveParse(currIndex,dataArr,path){
          let paramsLength = 6; //需要的参数个数
          let data = [ 
               dataArr[currIndex].substring(1),
               dataArr[currIndex+1],
               dataArr[currIndex+2],
               dataArr[currIndex+3],
               dataArr[currIndex+4],
               dataArr[currIndex+5]
            ];
          toThreejsCoor(data);
          path.bezierCurveTo(data[0],data[1],data[2],data[3],data[4],data[5]);
          return paramsLength;
        }

        //屏幕坐标转threejs坐标
        function toThreejsCoor(data){
          for(let i = 0 ; i < data.length; i += 2){
             data[i] = data[i] - window.innerWidth/2;
             data[i+1] = window.innerHeight/2 - data[i+1];
          }
        }

上面的代码做了下面这几件事:

  • 从svg中提取图形的定义数据,比如<path>标签的d属性
  • 将所提取数据中的坐标转换成threejs坐标
  • 分析所提取的数据里的操作,用ShapePath执行这些操作
  • 调用ShapePath类的toShapes()方法,获得一个Path对象数组
  • 用这个Path数组中的对象,创建threejs图形。

这也是将svg转成Path的几个基本步奏。经过转换之后,屏幕上会显示出如下图形:

完整效果,请戳【完整示例

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对整threeJS体系进行全面剖析。整理出全面的教学大纲,涵盖内容面非常广。此教学版本为threeJS107版本。关于版本不建议大家使用低于90的版本学习。以下是课程目录1-ThreeJS概览(基本图形简介,什么是点线面如何绘制点线面,什么是材质,什么是几何体,什么是相机,什么是渲染器,什么是场景)2-相机和渲染器(详解相机类型,渲染器如何使用,针对不同场景怎么用,怎么调效果,怎么渲染,怎么输出画布,如何解决透明问题等等)3-创建平面几何(常见的几何体如何使用,如何使用简单的几何体绘制出自定义自己想要的几何体,关于几何体的性能剖析,如何解决性能,几何体的渲染原理)4-高级图形算法常见库(求直线的斜率  计算线段与圆的交点 计算线段的长度 判断折线是否在多边形内 等等)5-sprite精灵(怎么让一个图标永远朝向屏幕,精灵的属性,精灵材质原理等,广告提示框必用)6-骨骼游戏动画(什么是模型动画,常见游戏案例,如何让人头进行各种攻击动作)7-3d模型加载(常见模型格式,如何渲染不同格式,不同格式的特点,什么格式性能优越,模型渲染异常,贴图不显示等问题详解)8-高阶动态纹理(你所不知道的纹理用法,我说你不知道,你肯定不知道)9-漫游轨迹以及其动画路径(怎么绘制贝塞尔曲线,如何使用曲线上的路径,跟随路径移动的原理,相机如何运动,物体如何运动)10-着色器(什么是着色器。初识着色器基础,着色器材质怎么用,怎么使用着色器库)11-常见渲染以及透明度问题12-对象拾取以及拖拽(3d世界里面如何拖拽物体,拖拽的原理,mousemove mouseon等的事件效果)13-世界坐标以及组的问题(什么是相对坐标,什么是世界坐标,什么是当前坐标,怎么转化父子坐标系,组的优化,为什么用组,组的优势)14-指定对象旋转中心(什么是物体的几何体中心,如何改变中心,如何绕轴转动)15-层级对象渲染(多个场景一键切换,切换的优势,针对大项目的用法)16-拓展了解系列(不定期不断更新案例,各种酷炫效果bloom,halo等,以及各种3d图表,粒子案例等,不断构建你的3d实践能力)
Three.js 是一个基于 JavaScript 的 3D 渲染库,主要用于 Web 环境中创建和展示复杂的三维图形。路径系统在 Three.js 中主要用来创建可动画的线形物体,比如粒子轨迹、线条动画或者角色的行走路线。 在 Three.js 中,你可以使用 `THREE.Geometry` 和 `THREE.Line` 或 `THREE.LineSegments` 来创建路径。以下是一些基本步骤: 1. **创建几何体(Geometry)**:定义路径的点,这些点将被连接起来形成线或线段。可以手动创建数组,或者使用 `PathGenerator` 类来自动生成从起点到终点的路径。 ```javascript const pathGeo = new THREE.Geometry(); pathGeo.vertices.push(new THREE.Vector3(0, 0, 0)); // 起点 // 添加更多路径点 ``` 2. **创建材质(Material)**:定义路径的颜色、宽度和其他视觉属性。例如,使用 `THREE.LineBasicMaterial` 或 `THREE.LineDashedMaterial`。 3. **创建线对象(Line/LineSegments)**:将几何体和材质组合,创建 `THREE.Line` 或 `THREE.LineSegments` 实例。 ```javascript const lineMaterial = new THREE.LineBasicMaterial({ color: 0x00ff00 }); const line = new THREE.Line(pathGeo, lineMaterial); ``` 4. **添加到场景(Scene)**:将线对象添加到当前的渲染场景中。 5. **动画(Animation)**:如果你想要让路径动态变化,可以使用 `THREE.Animation` 或 `THREE.Interpolant` 来创建动画效果。 6. **渲染(Render)**:最后,调用 `renderer.render(scene, camera)` 来显示你的路径
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值