[69-3] Canvasに曲線を描こう(線のスタイルも)

最終更新日:2019年02月06日  (初回投稿日:2014年04月15日)

前回は、<canvas>に四角形、多角形、円弧を描いてみました。
[69-2] Canvasに基本的な図形を描こう
多角形は直線で描きましたね。

今回はいろいろな曲線を描いてみます。
Illustrator などで描く「コントロールポイント」がある曲線です。
その応用で、直線と組み合わせて「角丸四角形」も作ってみました。
Canvas でも Illustrator と同じように「線の太さ」「先端の形状」なども指定できます。

今回のサンプルはこちら。
クリックで別ウィンドウで開きます。

本日のINDEX
  1. 二次ベジェ曲線の基本
    1. 二次ベジェ曲線は quadraticCurveTo(cpx, cpy, x, y);
    2. 角丸四角形を作ろう(二次ベジェ曲線の応用)
    3. ちなみに、円弧と直線でも角丸四角形を作れます(arcTo)
  2. 三次ベジェ曲線の基本
    1. 三次ベジェ曲線は bezierCurveTo(cpx1, cpy1, cpx2, cpy2, x, y);
    2. 花びらを描いてみた(三次ベジェ曲線の応用)
  3. 線の幅(太さ)の指定(lineWidth)
  4. 線の先端のスタイル(lineCap)
  5. 線の接合部分のスタイル(lineJoin)
  6. 接合部分が miter の場合、尖る部分を無効にする miterLimit

二次ベジェ曲線の基本

二次ベジェ曲線は quadraticCurveTo(cpx, cpy, x, y);

二次ベジェ曲線は「quadraticCurveTo(cpx, cpy, x, y);」で表します。
quadratic は数学用語で「二次の...」という意味だそうです。

  1. beginPath(); で、描画の開始を宣言
  2. moveTo(x,y); で、サブパスの開始点をx,y座標(ピクセル)を指定
    ここまで前回の「多角形」と同じですね。
  3. quadraticCurveTo(cpx, cpy, x, y); で、二次ベジェ曲線を指定
    cpx, cpy は、コントロールポイント(cp)の x, y 座標。
    その後のx, y は終点の座標です。
  4. strokeStyle または fillStyle で、線 or 塗りの色指定をする
    *ここを省略すると、デフォルトの黒い線、または塗りになります。
  5. stroke(); または fill(); で、線 or 塗りで描画します

サンプルの二次ベジェ曲線のソースを見てみましょう。
(クリックでサンプルが別ウィンドウで開きます)

図のように、コントロールポイントが1点なのが、二次ベジェ曲線です。

/* 二次ベジェ曲線_1本目 */
    ctx.beginPath();
    /* 始点の座標 */
    ctx.moveTo(30, 30);
    /* 二次ベジェ曲線(quadraticCurveTo(cpx, cpy, x, y)) */
    ctx.quadraticCurveTo(80, 130, 130, 30);
    /* 色指定無しで書き出すとデフォルトの黒になる */
    ctx.stroke();
     
/* 二次ベジェ曲線_2本目 */
    ctx.beginPath();
    ctx.moveTo(30, 100);
    ctx.quadraticCurveTo(130, 180, 130, 100);
    ctx.stroke();

角丸四角形を作ろう(二次ベジェ曲線の応用)

二次ベジェ曲線を使うと便利なのは「角丸四角形」です。
角丸の二次ベジェ曲線と、直線とを、交互に描いていきます。
クリックでサンプルが別ウィンドウで開きます。

サンプル
では、図のように x=150, y=40 の地点から「時計回り」で描いています。

/* 二次ベジェ曲線と直線で、角丸四角形を描く */
    ctx.beginPath();
    ctx.moveTo(150, 40);
    /* 多角形の各頂点を二次ベジェ曲線の制御点に指定する */
    ctx.quadraticCurveTo(150, 30, 160, 30);
    ctx.lineTo(240, 30);
    ctx.quadraticCurveTo(250, 30, 250, 40);
    ctx.lineTo(250, 120);
    ctx.quadraticCurveTo(250, 130, 240, 130);
    ctx.lineTo(160, 130);
    ctx.quadraticCurveTo(150, 130, 150, 120);
    /* closePath で始点まで直線を引く */
    ctx.closePath();
    ctx.strokeStyle = '#FF7373';
    ctx.stroke();

ちなみに、円弧と直線でも角丸四角形を作れます(arcTo)

二次ベジェ曲線の話の途中ですが、円弧(正円)のサブパスを描くには、もう1つ「arcTo」というのがあって、こっちのほうがラクかも。自動で円を描いてくれるので。

arcTo(x1, y1, x2, y2, radius) で表します。
「beginPath();」「moveTo(x,y);」で開始点を作ってから、
x1, y1 は1本目の補助線の終点。
x2, y2 は2本目の補助線の終点。
radius は正円の半径です。

arcToは、1本目の補助線に接する点から、2本目の補助線に接する点までの円弧を描き、
1本目の補助線の、円弧が始まるまでの直線も描かれるので、これを連続して使うと角丸の多角形ができる、という理屈です。

「arcTo」を使って「角丸四角」を描いてみました。

クリックでサンプルが別ウィンドウで開きます。

サンプル
では、図のように、x=280, y=30 の地点から、時計回りに描いています。
直線と円弧を4回繰り返して、角丸四角を作っています。

この場合、2本目の補助線の終点(x2, y2)は、角丸四角の「辺」のどの場所でもいいんですが、
円弧の終わる地点にしています。(半径を足すだけで計算しやすかったので)

/* 円弧と直線で、角丸四角形を描く */
    ctx.beginPath();
    ctx.moveTo(280, 30);
    /* 直線に接する円弧を描く(arcTo(x1, y1, x2, y2, radius)) */
    ctx.arcTo(370, 30, 370, 40, 10);
    ctx.arcTo(370, 130, 360, 130, 10);
    ctx.arcTo(270, 130, 270, 120, 10);
    ctx.arcTo(270, 30, 280, 30, 10);
    ctx.fillStyle = '#ff9';
    ctx.globalAlpha = 0.5;/*塗りだけ透明度50%にする*/
    ctx.fill();
    ctx.globalAlpha = 1;/*透明度を100%に戻す*/
    ctx.strokeStyle = '#FFBF00';
    ctx.lineWidth = 5;
    ctx.stroke();

三次ベジェ曲線の基本

三次ベジェ曲線は bezierCurveTo(cpx1, cpy1, cpx2, cpy2, x, y);

三次ベジェ曲線は「bezierCurveTo(cpx1, cpy1, cpx2, cpy2, x, y);」で表します。
Bezier curve はそのまま三次ベジェ曲線の意味です。

  1. beginPath(); で、描画の開始を宣言
  2. moveTo(x,y); で、サブパスの開始点をx,y座標(ピクセル)を指定
  3. bezierCurveTo(cpx1, cpy1, cpx2, cpy2, x, y); で、三次ベジェ曲線を指定
    cpx1, cpy1 は、1つ目のコントロールポイント(cp)の x, y 座標。
    cpx2, cpy2 は、2つ目のコントロールポイント(cp)の x, y 座標。
    x, y は終点の座標です。
  4. strokeStyle または fillStyle で、線 or 塗りの色指定をする
    *ここを省略すると、デフォルトの黒(#000)い線、または塗りになります。
  5. stroke(); または fill(); で、線 or 塗りで描画します

コントロールポイントが2点あるのが、三次ベジェ曲線です。

クリックでサンプルが別ウィンドウで開きます。

サンプル
の三次ベジェ曲線のソースを見てみましょう。

/* 三次ベジェ曲線_1本目 */
    ctx.beginPath();
    ctx.moveTo(400, 30);
    ctx.bezierCurveTo(415, 100, 485, 100, 500, 30);
    ctx.lineWidth = 1;
    ctx.strokeStyle = '#00D900';
    ctx.stroke();
 
/* 三次ベジェ曲線_2本目 */
    ctx.beginPath();
    ctx.moveTo(400, 110);
    ctx.bezierCurveTo(450, 160, 450, 60, 500, 110);
    ctx.strokeStyle = '#4DD2FF';
    ctx.stroke();

花びらを描いてみた(三次ベジェ曲線の応用)

三次ベジェ曲線を2回連続して描いて、花びらのようなパスを作ってみました。
(画像のクリックでサンプルが別ウィンドウで開きます)

Illustrator のように、けっこう自由に描くことができます。

ただし、Illustrator のようなハンドルが出るわけじゃないので大変ですけど(笑)
私はまず Illustratorでカタチを作って、コントロールポイントの座標を調べながら JavaScriptを書きました。

/* 三次ベジェ曲線_応用_花びらを描く */
    ctx.beginPath();
    ctx.moveTo(539, 128);
    ctx.bezierCurveTo(536, 62, 593, 13, 658, 71);
    ctx.bezierCurveTo(624, 128, 568, 67, 539, 128);

サンプルファイルのほうに、指定の全文があります。
ここでは、線形グラデーションで塗っています。(グラデーションの詳細は後日)

線の幅(太さ)の指定(lineWidth)

線の太さのデフォルトは 1pxです。
太さを変更したい場合は lineWidth を使います。

クリックでサンプルが別ウィンドウで開きます。

図のように、太さを10px にしたければ lineWidth = 10;
20px にしたければ lineWidth = 20; と、ピクセルで単位なしで指定します。

/* 線幅10ピクセルの指定 */
    ctx2.lineWidth = 10;
    ctx2.beginPath();
    ctx2.moveTo(30, 40);
    ctx2.lineTo(190, 40);
    ctx2.stroke();

線の先端のスタイル(lineCap)

線の先端のスタイルのデフォルトは、「butt」です。
「butt」は、線の先端に何も付けません。(ぶった切った先端って雰囲気の butt です)
「round」は、先端を中心点にした正円で丸めます。
「square」は、先端を中心点にした正方形で四角くします。
先端のスタイルを変更したい場合は lineCap」を使います。

クリックでサンプルが別ウィンドウで開きます。

図のように、先端のスタイルを丸くしたければ lineCap = round;
四角くしたければ lineCap = square; と指定します。

    ctx2.lineWidth = 20;
    /* ↑ 1度線幅を指定すると、以降全部この幅になります */
    
/* 3本目 'butt'(初期値。始点、終点でぶつ切り) */
    ctx2.beginPath();
    ctx2.moveTo(30, 80);
    ctx2.lineTo(190, 80);
    ctx2.lineCap = 'butt';
    ctx2.stroke();
/* 4本目 'round'(始点、終点を中心点にした円でまとめる) */
    ctx2.beginPath();
    ctx2.moveTo(30, 110);
    ctx2.lineTo(190, 110);
    ctx2.lineCap = 'round';
    ctx2.stroke();
/* 53本目 'square'(始点、終点を中心点にした正方形でまとめる) */
    ctx2.beginPath();
    ctx2.moveTo(30, 140);
    ctx2.lineTo(190, 140);
    ctx2.lineCap = 'square';
    ctx2.stroke();

線の接合部分のスタイル(lineJoin)

線と線の接合部分(角)のデフォルトスタイルは「miter」です。
「miter」は、線の外側のラインをそのまま延長させて尖らせます
「round」は、角を正円で丸くします。
「bevel」は、角に線幅が1辺の正方形を置くかんじで、直線で面取りします。
接合部分のスタイルを変更したい場合は「lineJoin」を使います。

クリックで サンプルが開きます。

図のように、角を丸くしたければ lineJoin = 'round';
角を斜めに面取りしたければ lineJoin = 'bevel'; と指定します。

/* 線の接合部分のスタイル(lineJoin) */
    /* 'miter'(初期値。角が尖っている) */
    ctx2.beginPath();
    ctx2.moveTo(305, 25);
    ctx2.lineTo(245, 25);
    ctx2.lineTo(245, 85);
    ctx2.lineJoin = 'miter'; /* この指定省略しても同じ */
    ctx2.stroke();
    /* 'round'(丸く面取りする) */
    ctx2.beginPath();
    ctx2.moveTo(340, 55);
    ctx2.lineTo(280, 55);
    ctx2.lineTo(280, 115);
    ctx2.lineJoin = 'round';
    ctx2.stroke();
    /* 'bevel'(直線で面取りする) */
    ctx2.beginPath();
    ctx2.moveTo(375, 85);
    ctx2.lineTo(315, 85);
    ctx2.lineTo(315, 145);
    ctx2.lineJoin = 'bevel';
    ctx2.stroke();
}

接合部分が miter の場合、尖る部分を無効にする miterLimit

接合部分が miter の場合、角が鋭角であるほど、生成される三角形が長くなります。
あまりにも長くなりすぎるのを防ぐために、miterLimit という設定があります。

miterLimit はデフォルトが 10.0 です。
マイター限界は「 lineWidth ÷ 2 × miterLimit」
線幅 (lineWidth) が 20pxなら、デフォルトのマイター限界は 100pxになり、 それを越えなければ尖った三角形は生成されます。

クリックでサンプルが別ウィンドウで開きます。

サンプルの一番下のパスでは、miterLimit を2.0に指定したので、miter 限界長は 20pxになり、それを越えるため三角形は生成されません。(bevel と同じ角になります。)

/* miterLimit を指定 */
    ctx3.beginPath();
    ctx3.moveTo(0, 170);
    ctx3.lineTo(200, 195);
    ctx3.lineTo(0, 220);
    ctx3.lineJoin = 'miter';
    ctx3.miterLimit = 2.0;
    ctx3.stroke();
}

次回予告

今回やった内容は、Illustrator などで描けばメッチャ速い。
ちょっと飽きてきました。でも基礎ですからね、やっとかないと…。

次回は画像を Canvas に描画してみます。(これはオモシロイよ(笑)
画像をロードして drawImage() で書き出します。
画像のトリミングや、図形によるクリッピングもできます。

関連記事
このエントリーをはてなブックマークに追加

やる気を保つためにランキングに参加しています。
応援してくださると すっごいやる気を出します! (笑)

初心者にも使いやすい(と思う)レンタルサーバー

「初心者ですがレンタルサーバーはどこがいい?」というご質問をよくいただきます。
自由にファイルをアップロードできる自分のサーバがあると便利ですよね。ローカル環境じゃなくサーバ上で試してみたい時がありますからね。
私が使っているのは、 スターサーバーロリポップ!です。どちらも管理画面がわかりやすく、マニュアルも充実していて、料金も安い。どちらもライトプラン以上で WordPress が使えます。
初心者が始めやすいサーバだと思います。

ちょっと料金は高いけど、さくらのレンタルサーバや、エックスサーバー は、やはり老舗なのでおすすめです。
両方とも高スペックでコスパが良く、老舗でユーザーが多いので、質問する場がたくさんあります。初心者だけど仕事でサーバが欲しい場合は、安心なのではないかと思います。

スポンサーリンク

コメントの投稿

ご注意:メールアドレスは書かないで
「コメントを送信する」ボタンを押した後の「確認画面」で、メールアドレス・URL などを入力できるようになっており、メールアドレス・URL は、そのままオートリンクになる仕様です。
当方でメールアドレスだけ削除することも、メールアドレスを非公開にすることもできません
メールアドレスは書かないでください。詳しくはこちらにまとめましたのでご覧ください。

スポンサーリンク
最新記事
Category
オススメの本
Links
Calendar
08 | 2023/09 | 10
- - - - - 1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Archive
Profile

yuki★hata

Author : yuki★hata
せめて月1回の更新をめざします~。

メールフォームはこちら

スポンサーリンク
スポンサーリンク
Copyright © ほんっとにはじめてのHTML5とCSS3 All Rights Reserved.