如何使用three.js在运行时绘制线段

Posted

技术标签:

【中文标题】如何使用three.js在运行时绘制线段【英文标题】:How to draw a line segment at run time using three.js 【发布时间】:2014-05-21 10:05:31 【问题描述】:

我是 Three.js 的新手,我正在尝试实现 Microsoft Paint 中用于绘制线段的技术。我正在尝试获取点 onMouseDown 的坐标,然后用 onMouseMove 延伸一条线,直到 onMouseDown。请帮忙!

【问题讨论】:

【参考方案1】:

three.js 主要用于 3D 绘图。如果您想复制像绘画这样的 2D 绘图应用程序,那么使用 2D 画布可能会更容易:canvas.getContext("2d");

我假设您确实想在three.js 中进行绘制。在这种情况下,我将 this example 放在一起。请按以下步骤操作:

    单击页面上的任意位置并拖动鼠标以绘制一条线。这条线是在 z 平面上绘制的。 单击“形状”按钮,注意一个形状靠得更近,而另一个靠得更远,这是因为一个在 z 平面上方,另一个在后面。 单击旋转按钮,这将导致相机缩小并围绕轴旋转。请注意,当您通过 z 平面时,您的所有绘图都在该平面上。

看一下代码,主要部分是:

您需要将鼠标点击坐标投影到平面上。这是通过这个函数完成的:

function get3dPointZAxis(event)

    var vector = new THREE.Vector3(
                ( event.clientX / window.innerWidth ) * 2 - 1,
                - ( event.clientY / window.innerHeight ) * 2 + 1,
                0.5 );
    projector.unprojectVector( vector, camera );
    var dir = vector.sub( camera.position ).normalize();
    var distance = - camera.position.z / dir.z;
    var pos = camera.position.clone().add( dir.multiplyScalar( distance ) );    
    return pos;

然后从前一个点画线:

geometry.vertices.push(lastPoint);
geometry.vertices.push(pos);
var line = new THREE.Line(geometry, material);
scene.add(line);

请注意,当您在旋转时接近通过 z 平面时,到 Z 的投影距离很远,您会超出界限,为防止这种情况发生,请执行以下检查:

if( Math.abs(lastPoint.x - pos.x) < 500 && Math.abs(lastPoint.y - pos.y) < 500 && Math.abs(lastPoint.z - pos.z) < 500 )

作为参考,我找到了有关投影鼠标坐标here(SO 答案)和here(three.js 示例)的信息。

更新

要从 mousedown 位置到 mouseup 位置画一条线,请参阅 this demo。代码更改是改为只在鼠标向上的点之间进行绘制。

function stopDraw(event)

     if( lastPoint )
    
        var pos = get3dPointZAxis(event);
        var material = new THREE.LineBasicMaterial(
            color: 0x0000ff
        );
        var geometry = new THREE.Geometry();
        if( Math.abs(lastPoint.x - pos.x) < 2000 && Math.abs(lastPoint.y - pos.y) < 2000 && Math.abs(lastPoint.z - pos.z) < 2000 )
        
            geometry.vertices.push(lastPoint);
            geometry.vertices.push(pos);

            var line = new THREE.Line(geometry, material);
            scene.add(line);
            lastPoint = pos;        
        
        else
        
            console.debug(lastPoint.x.toString() + ':' + lastPoint.y.toString() + ':' + lastPoint.z.toString()  + ':' + 
                        pos.x.toString() + ':' + pos.y.toString()  + ':' + pos.z.toString());
        
    
      

【讨论】:

非常感谢!这个例子给出了很多想法。我一直在寻找画一条直线。该示例给出了在 Paint 中使用钢笔/铅笔而不是线条的效果。你能告诉我如何转换上面的代码来完成从鼠标向下到鼠标向上事件绘制一条直线。提前致谢。 好的!现在我明白了。万分感谢!还有一个疑问,就是如何在x-y平面上实现这段代码?我知道这是微不足道的,但我无法得到结果:( @user3359133 这条线将在 z=0 处绘制,即 xy 平面。如果您的意思是如何仅使用 2D 来执行此操作,那么您应该使用 html 5 Canvas 而不是 three.js。然后您将使用canvas.getContext("2d");LineTo。请参阅html5canvastutorials.com/tutorials/html5-canvas-lines 和 html5canvastutorials.com/tutorials/html5-canvas-line-caps 和 tutorialspoint.com/html5/canvas_drawing_lines.htm。 你是如何在这个位置选择值 2000 的:- if( Math.abs(lastPoint.x - pos.x)

以上是关于如何使用three.js在运行时绘制线段的主要内容,如果未能解决你的问题,请参考以下文章

如何在three.js的3空间中绘制扁平形状?

如何让 three.js 在 React Native 中运行(没有 WebView)?

三维空间中绘制点线面UV贴图,万能的BufferGeometry(three.js实战4)

如何在使用three.js和jsonLoader时制作加载屏幕?

绘制不断变色的台体,BufferGeometry和ShaderMaterial的黄金组合(three.js实战5)

#yyds干货盘点#愚公系列2022年12月 微信小程序-three.js绘制球体