4

I am new to Three.js and I'm trying to implement the technique used in Microsoft Paint for drawing a line segment. I'm trying to get coordinates of a point onMouseDown then extend a line with onMouseMove until onMouseDown. Please help!

1 Answer 1

8

three.js is mainly for drawing in 3D. If you want to copy a 2D drawing application like paint then using the 2D canvas will probably be easier: canvas.getContext("2d");.

I will assume that you do want to draw in three.js. In which case I have put together this example. Follow these steps:

  1. Click anywhere on the page and drag the mouse around to draw a line. The line is drawn on the z plane.
  2. Click the Shapes button and notice how one shape is closer in and the other further, that is because one is above the z plane and the other behind.
  3. Click the Rotate button, this will cause the camera to zoom out and rotate around the axes. Notice that when you pass through the z plane all your drawing is on that plane.

Have a look at the code, the main parts are:

You need to project the mouse click coordinates onto the plane. This is done with this function:

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;
}

Then draw the line from previous to this point:

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

Note that when you get close to passing through the z plane while rotating, the projection to Z is very far off and you go out of bounds, to prevent this the following check is done:

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

For reference, I found information for projecting the mouse coordinate here (SO answer) and here (three.js sample).

Update

To draw a line from the mousedown position to the mouseup position see this demo. The code changes are to instead just do the draw between points on mouse up.

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());
        }
    }
}      
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks a lot! The example gave a lot of idea. I was looking for drawing a straight line. The example gives effect of using a pen/pencil in Paint and not a line. Could u tell me how I can transform the above code to accomplish drawing a straight line from mouse down till mouse up event. Thanks in advance.
okay! Now I see. Thanks a ton! One doubt remains, that is, how to implement this code in the x-y plane? I know it is trivial, but I'm unable to get the result :(
@user3359133 The line will be drawn at z=0 which is the xy plane. If you mean how do you do this with just 2D then you should use the html 5 Canvas and not three.js. You would then use canvas.getContext("2d"); and LineTo. See html5canvastutorials.com/tutorials/html5-canvas-lines and html5canvastutorials.com/tutorials/html5-canvas-line-caps and tutorialspoint.com/html5/canvas_drawing_lines.htm.
how did u choose the value 2000 in this loc :- if( Math.abs(lastPoint.x - pos.x) < 2000 && Math.abs(lastPoint.y - pos.y) < 2000 && Math.abs(lastPoint.z - pos.z) < 2000 ) {

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.