简体   繁体   English

HTML5画布-从左上方绘制圆圈

[英]HTML5 Canvas - draw circle from top left

How would I alter the following code to force a HTML5 canvas to draw from the top-left of an arc, instead of from the centre. 我将如何更改以下代码,以强制HTML5画布从弧的左上角而不是从中心绘制。

I currently have: 我目前有:

function drawCircle(e) {
    var oe = e.originalEvent || e;

    ctx.beginPath();
    ctx.arc(start.x, start.y + 10, oe.pageX - start.x - offset.left, 0, 2 * Math.PI, false);
    ctx.stroke();
    ctx.closePath();
}

I have the following fiddle (code below for convenience) - if you begin drawing on that, the circle is drawn fine but it draws from the centre of where you place your mouse, outwards: http://jsfiddle.net/g4zxp/ 我有以下小提琴(为方便起见,下面的代码)-如果您开始在其上画图,则该圆画得很好,但是它是从您放置鼠标的中心向外绘制的: http : //jsfiddle.net/g4zxp/

I would like to drag the circle from the top-left down, but I cannot figure out the maths to do it! 我想从左上角向下拖动圆,但是我不知道要怎么做! I know I would need to calculate and keep changing the centre point. 我知道我需要计算并不断更改中心点。

Any ideas? 有任何想法吗?

Thanks 谢谢

Code as follows: 代码如下:

HTML : HTML

<canvas width="200" height="200"></canvas>

JavaScript/jQuery : JavaScript / jQuery

$(function () {
    var $canvas = $('canvas'),
        canvas = $canvas.get(0),
        offset = $canvas.offset(),
        ctx,
        drawing = false,
        start = {
            x: null,
            y: null
        };

    function init() {
        if (canvas.getContext) {
            ctx = canvas.getContext('2d');

            ctx.lineJoin = 'round';
            ctx.lineCap = 'round';
            ctx.strokeStyle = '#000000';
            ctx.lineWidth = 5;
        }
    }

    function startDrawing(e) {
        var oe = e.originalEvent || e;

        e.preventDefault();

        drawing = true;

        start.x = Math.floor(oe.pageX - offset.left);
        start.y = Math.floor(oe.pageX - offset.left);
    }

    function continueDrawing(e) {
        e.preventDefault();

        if (!drawing) {
            return;
        }

        clearCanvas();
        drawCircle(e);
    }

    function endDrawing(e) {
        e.preventDefault();
        drawing = false;
    }

    function clearCanvas() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
    }

    function drawCircle(e) {
        var oe = e.originalEvent || e;

        ctx.beginPath();
        ctx.arc(start.x, start.y + 10, oe.pageX - start.x - offset.left, 0, 2 * Math.PI, false);
        ctx.stroke();
        ctx.closePath();
    }

    $canvas.on('touchstart mousedown', function (e) {
        startDrawing(e);
    });

    $canvas.on('touchmove mousemove', function (e) {
        continueDrawing(e);
    });

    $canvas.on('touchend mouseup', function (e) {
        endDrawing(e);
    });

    init();
});

I am assuming the "top left of an arc" to be the intersection of the lines in the diagram below. 我假设“圆弧的左上角”是下图中线的交点。 In that case, the distance from the center of the circle is a distance of sqrt(2 * r^2) away from the "top left" 在这种情况下,距圆心的距离为距“左上角”的距离为sqrt(2 * r^2)

But, since circles in canvas are positioned using x and y anyway, we can use that instead. 但是,由于画布中的圆圈无论如何都使用x和y定位,因此我们可以改用它。 The distance from the center to the closest point on the vertical line is r, as is the distance from the center to the nearest point on the horizontal line 从中心到垂直线上最近点的距离为r,从中心到水平线上最近点的距离也为r

This means that (since (0,0) is in the top left) the "top left's" x position is center's x position - r and the "top left's" y position is center's y position - r or (cX - r, cY - r) for short 这意味着(因为(0,0)在左上角),“左上角”的x位置是center's x position - r ,“左上角”的y位置是center's y position - r(cX - r, cY - r)简称

You can manually calculate this in canvas using your code like (since oe.pageX - start.x - offset.left = r ) so: 您可以使用代码(因为oe.pageX - start.x - offset.left = r )在画布中手动计算此值,因此:

var r = oe.pageX - start.x - offset.left;
ctx.arc(start.x + r, start.y + 10 + r, r, 0, 2 * Math.PI, false);

Demo . 演示 This works just fine. 这样很好。

However you could make a function if you want to use the same format on the front end. 但是,如果您想在前端使用相同的格式,则可以创建函数。 It'd look something like this 看起来像这样

function arcTopLeft(x, y, r, a1, a2) {
    ctx.arc(x + r, y + r, r, a1, a2, false);
}
// Called using the same inputs as your original call
arcTopLeft(start.x, start.y + 10, oe.pageX - start.x - offset.left, 0, 2 * Math.PI, false);

Hope it helped! 希望能有所帮助!

Ok, so there is an insanely simple way to do this, and you only had an error in your ctx.arc() call, thats all: 好的,所以有一种非常简单的方法来执行此操作,并且您在ctx.arc()调用中仅出现错误,仅此而已:

ctx.arc(oe.layerX, oe.layerY, Math.abs(oe.pageX - start.x - offset.left), 0, 2 * Math.PI, false);

I also set your radius to an absolute value so that you can draw the circle in the negative direction without crashing your app. 我还将您的半径设置为绝对值,以便您可以沿负方向绘制圆,而不会导致应用崩溃。 Wish I would've gotten to you sooner, I figured you would have wanted this very simple answer before. 希望我早点找到您,我想您以前会想要这个非常简单的答案。

By the way, here is your fiddle all fixed up and doing exactly what you wanted it to do. 顺便说一句, 这是您的小提琴全部都固定好了,并按照您想要的去做。 Sorry I didn't get to you sooner! 抱歉,我没早联系您!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM