Senseless
Senseless

Reputation: 99

Why is the circle moving in x and y direction on the canvas?

I'm trying to make a simple paint program, and I'm slowly getting there. But the circle-tool has a small issue. The circle is moving a bit when the user click and drag. This doesn't happen with the rectangle, oval and polygon tool. How can this be fixed?

Here is the code for drawing the circle

            tools.circle = function () {
                var tool = this;
                this.started = false;
                this.mousedown = function (ev) {
                    tool.started = true;
                    tool.x0 = ev._x;
                    tool.y0 = ev._y;
                };
                this.mousemove = function (ev) {
                    if (!tool.started) {
                        return;
                    }
                    context.clearRect(0, 0, canvas.width, canvas.height);
                    var radius = Math.max(Math.abs(ev._x - tool.x0), Math.abs(ev._y - tool.y0)) / 2;
                    var x = Math.min(ev._x, tool.x0) + radius;
                    var y = Math.min(ev._y, tool.y0) + radius;
                    context.fillStyle = 'hsl(' + 360 * Math.random() + ', 85%, 50%)';
                    context.beginPath();
                    context.arc(x, y, radius, 0, Math.PI * 2, false);
                    context.stroke();
                    context.closePath();
                    context.fill();
                };
                this.mouseup = function (ev) {
                    if (tool.started) {
                        tool.mousemove(ev);
                        tool.started = false;
                        drawCanvas();
                    }
                };
            };

And here is the working code for an oval

        tools.oval = function () {
                var tool = this;
                this.started = false;
                this.mousedown = function (ev) {
                    tool.started = true;
                    tool.x0 = ev._x;
                    tool.y0 = ev._y;
                };
                this.mousemove = function (ev) {
                    if (!tool.started) {
                        return;
                    }
                    context.clearRect(0, 0, canvas.width, canvas.height);
                    var radius1 = Math.abs(ev._x - tool.x0);
                    var radius2 = Math.abs(ev._y - tool.y0);
                    var scaleX = radius1 / (Math.max(radius1, radius2));
                    var x = tool.x0 / scaleX;
                    var scaleY = radius2 / (Math.max(radius1, radius2));
                    var y = tool.y0 / scaleY;
                    context.fillStyle = 'hsl(' + 360 * Math.random() + ', 100%, 50%)';
                    context.save();
                    context.scale(scaleX, scaleY);
                    context.beginPath();
                    context.arc(x, y, Math.max(radius1, radius2), 0, 2 * Math.PI);
                    context.restore();
                    context.stroke();
                    context.closePath();
                    context.fill();
                };
                this.mouseup = function (ev) {
                    if (tool.started) {
                        tool.mousemove(ev);
                        tool.started = false;
                        drawCanvas();
                    }
                };
            };

It would be very nice if the circle didn't move with the mouse on the canvas, but instead stayed at the starting point and was dragged out from there.

Upvotes: 0

Views: 52

Answers (3)

Kurohige
Kurohige

Reputation: 1418

Based on your code you need to change these lines:

//causes pointer moving from circle these lines:
var radius = Math.max(Math.abs(ev._x - tool.x0), Math.abs(ev._y - tool.y0))/2;
//causes center moving
var x = Math.min(ev._x, tool.x0) + radius;
var y = Math.min(ev._y, tool.y0) + radius;

in

var radius = Math.max(Math.abs(ev._x - tool.x0), Math.abs(ev._y - tool.y0));
var x =  tool.x0;
var y =  tool.y0;

Upvotes: 1

obscure
obscure

Reputation: 12891

You can use the Pythagoras theorem to get the distance from the point you clicked on the canvas to the point you're dragging your mouse to - thus the radius for your circle. Now simply draw the circle from the initial 'click' position.

Here's the modified mousemove function for your circle:

        this.mousemove = function(ev) {
          if (!tool.started) {
            return;
          }
          context.clearRect(0, 0, canvas.width, canvas.height);
          var tempX = ev._x - tool.x0;
          var tempY = ev._y - tool.y0;
          var radius = Math.sqrt(tempX * tempX + tempY * tempY);
          var scale = radius / radius;
          var x = tool.x0 / scale;
          var y = tool.y0 / scale;
          context.fillStyle = 'hsl(' + 360 * Math.random() + ', 100%, 50%)';
          context.save();
          context.scale(scale, scale);
          context.beginPath();
          context.arc(x, y, radius, 0, 2 * Math.PI);
          context.restore();
          context.stroke();
          context.closePath();
          context.fill();
        };

Upvotes: 1

ruedamanuel
ruedamanuel

Reputation: 1930

You are moving your center by recalculating the min value between your initial start point and your current mouse location. If you want the center of the circle to remain still, your x and y coordinates should remain fixed:

var x = tool.x0;
var y = tool.y0;

Upvotes: 0

Related Questions