preface

You may have seen a lot about picture movement and rectangle movement in Canvas. But why am I even writing this article? I’ve done 3D graphics before. This involves moving an edge on a cube, a face, and a point on a polygon. I’ve been writing about Canvas lately, and I thought I’d review it. After reading this article, you can learn how to move a point, an edge, and the entire surface of a rectangle. This article from shallow to deep, I hope you read patiently.

The mobile

Think about mobile on canvas. The first step is to create the Canvas and add a Move event to the Canvas so that we can get the position of our mouse in real time. Then we just need to keep clearing the Canvas and redrawing the rectangle. OK, the surface of the initial implementation of the movement. I’m going to write down here a little bit of movement is going to rewrite this, but I’m going to write a quick and easy version of this.

const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); const width = 100; const height = 100; drawRect(); function drawRect(x = 10,y = 10, scale = 1) { ctx.clearRect( 0, 0, 1800, 800 ); const halfwidth = width * scale / 2; const halfheight = height * scale / 2; ctx.strokeRect(x - halfwidth, y - halfheight,width * scale, height * scale) } let isMove = true; canvas.addEventListener('mousemove',(e)=>{ if(! isMove) { return } const x = e.clientX; const y = e.clientY; drawRect(x,y) }) canvas.addEventListener('click',(e)=> { isMove = ! isMove; });

The isMove variable is a switch. You can’t move it all the time. It’s too tiring. Why X-HalfWidth, Y-HalfHeight

To explain, the Strokerect starts at the top left corner of the rectangle, but I wanted to center the rectangle, so I did a subtraction between the width and the height to show it perfectly.

The movement of the point

So the first question is what? So how do we know which point we’re going to pick? Well, a simple thing I did here is I compared the position of the mouse click with the position of each of the points in the rectangle, and I decided which one was closer to the target. Because we’re moving a point in 2D just to find the line segment associated with that point, so we just have to regenerate the line segment associated with that point, but there’s a tricky part here, right? You move a semicircle, right? If we move the break point of the semicircle, this involves a change in the arc, maybe an elliptic arc or a second or third order Bessel curve. Or is it moving one shape and cutting the other shapes on the canvas? Do you also need to cut the algorithm? In fact, you can use the Clipper to find the intersection and the difference. If you are interested in it, you can find out by yourself, but this is not the purpose of this article. All of the examples in this article (only straight lines are supported, i.e. LineSegment).

OK, so our first step is we’re going to have to re-express the rectangle, because it’s not universal enough to re-express the quadrilateral, and the rectangle and the square are just the specials. And I’ll give you the reason, right? Why? A very simple case, moving a point in a quadrilateral, might look like this:

OK. For the purposes of this illustration, let’s create a new Point2D class that represents each point on the canvas as an instance.

class Point2d {
    constructor(x,y) {
        this.x = x || 0;
        this.y = y || 0;
    }
    clone() {
        return this.constructor(this.x, this.y);
    }
    add(v) {
        this.x += v.x;
        this.y += v.y
        return this;
    }
   random() {
        this.x = Math.random() *1800;
        this.y = Math.random() * 800;
        return this
    }
}

Next, we will randomly add the length and width of the rectangle on the canvas and draw the rectangle. The code is as follows:

function drawFourPolygon(x, y ,width = 50, height = 50) {
    ctx.clearRect( 0, 0, 1800, 800 );
    ctx.beginPath();
    ctx.moveTo(x- width /2, y - height/2)
    ctx.lineTo(x+ width / 2, y -height/2 )
    ctx.lineTo(x+ width / 2, y + height/2 )
    ctx.lineTo(x - width / 2, y + height/2 )
    ctx.closePath()
    ctx.stroke()
}

To make the interaction perfect, the first mouse click determines the starting point of the movement, and then the constant mouse movement is the end point of the movement, thus determining a vector. In order to make it more obvious when moving, I added the dotted line function. The code is as follows

function drawDashLine(start, end) { if (! start || ! end) { return } ctx.strokeStyle = 'red'; ctx.setLineDash( [5, 10] ); ctx.beginPath(); ctx.moveTo( start.x, start.y ); ctx.lineTo( end.x, end.y ); ctx.closePath() ctx.stroke(); }

This is the meaning of the Canvas SetLineDash API parameter. The distance between the solid line is 5, and the blank line is 10. This is repeated to form a dotted line. Start and end is the mouse click to determine the start point, and then the mouse kept moving is the end point. A little note here is that I drew a dotted line and then I drew a rectangle as I moved around so what? The rectangle is still a solid line. We’ve changed the code for drawing rectangles here, so let’s put the dotted lines back.

The code is as follows:

 ctx.setLineDash([]); 

OK, the overall interaction is out, let me show you the effect first:

Is that feeling a little hahaha? From the perspective of the picture, this is still a whole movement, not a point movement. Since my drawing is a rectangle based on the point that the mouse clicks on, my next article will introduce the movement of irregular polygon points. In this article, we will assume that I am moving the point in the upper right corner. OK, we can get a moving vector from the starting point and the ending point of the move, so we just add the point we’re moving to this vector. So we’re not moving a little bit.

 const moveVec = end.clone().sub(start);
 const rightTop = new Point2d(x+ width / 2, y - height/2).clone().add(moveVec)

Here I changed the top right dot, but there is a problem that we click on the same function, so we need to add a switch to determine whether it is the first click or move. The code is as follows:

ctx.lineTo(isSelect ? rightTop.x : x+ width / 2, isSelect ? Righttop. y: y height/2) // Check out the click and move event switches. Canvas. AddEventListener ('mousemove',(e)=>{if(! isMove) { return } const x = e.clientX; const y = e.clientY; clearRect(); end = new Point2d(x,y); drawDashLine(start,end); DrawFourPolygon (start)}) Canvas. AddEventListener ('click',(e)=> {// This is a function that clears the canvas every time. isMove; const x = e.clientX; const y = e.clientY; start = new Point2d(x,y); drawFourPolygon(start) isSelect = true; });

The effect picture is as follows:

Ha ha ha is not very smooth and smooth, I found the drawing performance of Canvas is very good. But there’s still a problem with determining the outcome, and if we look at the code above we’re sure that the outcome is wrong. So I’m just going to end with Alt and that’s perfect, and I’m not going to show the code here.

The movement of the line

With the point movement, the line movement is shown very easily. A line moving is actually a point moving. Let’s take the right line as an example: The code is rewritten as follows:

function drawFourPolygon( point, width = 50, height = 50) { if(! point) { return } ctx.strokeStyle = 'black' ctx.setLineDash([]); ctx.beginPath(); const { x, y } = point; const moveVec = end.clone().sub(start); Const rightTop = new point2D (x+ width / 2, x+ width / 2); y - height/2).clone().add(moveVec) const rightBottom = new Point2d(x+ width / 2, y + height/2).clone().add(moveVec) ctx.moveTo(x- width /2, y - height/2) ctx.lineTo(isSelect ? rightTop.x : x+ width / 2, isSelect ? rightTop.y : y - height/2) ctx.lineTo(isSelect ? rightBottom.x : x+ width / 2, isSelect ? rightBottom.y : y + height/2) ctx.lineTo(x - width / 2, y + height/2 ) ctx.closePath() ctx.stroke() }

Let’s take a look at the effect picture:

conclusion

This article mainly introduces the most basic change movement in 2D graphics, whether the line movement or the surface movement is ultimately the movement of the point. And you can actually use a matrix as a vector for movement, or you can use a matrix change for rotation, movement, scale and so on. Finally, thank you for seeing the last, code word is not easy, if you see the help, welcome to click a like 👍 and follow. Your support is the biggest motivation for me to keep updating good articles. All the code is on my GitHub. Welcome to Star.