LoginSignup
4
4

More than 5 years have passed since last update.

canvas で円を描画

Posted at

日経ソフトウェア2013年7月号のコードを若干アレンジ

3点を使って円を描画.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>3点を使って円を描画</title>
    <style>canvas { background-color: #d0d0d0; }</style>
</head>
<body onload="draw()">
    <canvas id="canvas" width="600" height="600"></canvas>
<script>

    xx = new Array(3);
    yy = new Array(3);
    var cx, cy;     // 円の中心
    var n = 0;      // クリック回数のカウンタ

    function draw() {
        var canvas = document.getElementById("canvas"); // 描画対象の canvas を選択
        var context = canvas.getContext("2d");          // 描画コンテキストを取得

        // マウスダウンイベント処理
        canvas.onmousedown = function(e) {
            // canvas 内でのマウス座標を計算
            var rect = e.target.getBoundingClientRect();
            var mouseX = e.clientX - rect.left;
            var mouseY = e.clientY - rect.top;

            context.beginPath();
            context.strokeStyle = "rgb(128, 128, 128)";

            xx[n] = mouseX;
            yy[n] = mouseY;
            context.rect(xx[n], yy[n], 2, 2);   // 点を描画
            if( n >= 2 ) {
                drawLine();     // 3点を結ぶ直線を描画
                calcCenter();   // 垂直二等分線の交点を計算
                drawCircle();   // 3点を通る円を描画
                n = 0;
            } else {
                n++;
            }
            context.stroke();
        }

        // 3点を結ぶ直線を描画
        function drawLine() {
            context.beginPath();
            context.strokeStyle = "rgb(128, 128, 128)";
            context.moveTo(xx[0], yy[0]);
            context.lineTo(xx[1], yy[1]);
            context.lineTo(xx[2], yy[2]);
            context.closePath();
            context.stroke();
        }

        // 垂直二等分線の交点を求める
        function calcCenter() {
            // 2点間の垂直2等分線を求める
            f = function (x1, y1, x2, y2) {
                // 直線の係数を求める
                var a = (y2 - y1) / (x2 - x1);
                var b = y1 - (a * x1);
                // 直線の中点を求める
                var mx = x1 + ((x2 - x1) / 2);
                var my = y1 + ((y2 - y1) / 2);
                // 直線の垂直二等分線の係数を求める
                var aa = -1 / a;
                var bb = my - (aa * mx);
                return [mx, my, aa, bb];
            }
            ret = f(xx[0], yy[0], xx[1], yy[1]);
            m1 = [ret[0], ret[1]];              // 中点座標
            ab = [ret[2], ret[3]];              // 垂直二等分線の係数
            ret = f(xx[1], yy[1], xx[2], yy[2]);
            m2 = [ret[0], ret[1]];
            cd = [ret[2], ret[3]];

            // 二つの垂直二等分線の交点を求める
            // 解法)x = (-1/(-a+c) * -b) + (1/(-a+c) * -d)
            //       y = (-c/(-a+c) * -b) + (a/(-a+c) * -d)
            var z = 1 / (-ab[0] + cd[0]);                   // z = 1/(-a+c)
            cx = z * (-1     * -ab[1] + 1     * -cd[1]);    // x = z * (-1 * -b + 1 * -d)
            cy = z * (-cd[0] * -ab[1] + ab[0] * -cd[1]);    // y = z * (-c * -b + a * -d)

            // 垂直二等分線を描画
            context.strokeStyle = "rgb(0, 255, 0)"
            context.beginPath();
            context.moveTo(cx, cy);
            context.lineTo(m1[0], m1[1]);
            context.stroke();
            //
            context.beginPath();
            context.moveTo(cx, cy);
            context.lineTo(m2[0], m2[1]);
            context.stroke();
        }

        // 3点を通る円を描画
        function drawCircle() {
            // 円の半径を求める
            var r = Math.sqrt(Math.pow(cx - xx[0], 2) + Math.pow(cy - yy[0], 2));

            // 円を描画
            context.beginPath();
            context.strokeStyle = "rgb(255, 0, 0)";
            context.arc(cx, cy, r, 0, 2 * Math.PI, true);
            context.stroke();
        }
    }
</script>
</html>
4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4