LoginSignup
39
29

More than 5 years have passed since last update.

SVGでフリーハンドお絵描き

Last updated at Posted at 2017-01-12

svgでお絵描きサンプルを作ってみました。
線を滑らかにしたかったので色々と思考錯誤してみました。

やりたいこと

  • svg上でドラッグしたらpathを追加したい
  • pathをベジェにして滑らかにしたい
  • 頂点を間引いて滑らかにしたい

svg上でドラッグしたらpathを追加したい

これは、単純にマウスイベントとフラグ管理でドラッグしている時にsvg要素にpath要素を追加していきました。

pathをベジェにして滑らかにしたい

これがけっこう大変でした。

通過点のみで曲線を描くのはcatmull曲線があるのですが、まだpath要素には実装されていないようでした。
ここによると下記のようです。

R,r1 Catmull-Romスプライン曲線を引く
SVG2での新機能.詳細仕様は策定中であり,動作する環境はまだない.

したがって、ベジェ曲線を使うことになるのですが、通過点の他に制御点が必要です。
イラレでよく見かけるアンカーポイントのことです。

svgでベジェ曲線サンプル

通過点から制御点を求める関数を上げている人がいたので、これを拝借しました。

ソースコードのみ抜粋

catmullRom2bezier
function catmullRom2bezier(pts){
    var cubics = [];
    for ( var i = 0, iLen = pts.length; i < iLen ; i++ ){
        var p = [
            pts[i - 1],
            pts[i],
            pts[i + 1],
            pts[i + 2]
        ];
        if( i === 0 ){
            p[0] = {
                x: pts[ 0 ].x,
                y: pts[ 0 ].y
            }
        }
        if( i === iLen - 2 ){
            p[3] = {
                x: pts[iLen - 2].x,
                y: pts[iLen - 2].y
            };
        }
        if ( i === iLen - 1 ) {
            p[2] = {
                x: pts[iLen - 1].x, 
                y: pts[iLen - 1].y
            };
            p[3] = {
                x: pts[iLen - 1].x, 
                y: pts[iLen - 1].y
            };
        }
      const val = 6;
        cubics.push([
            (-p[0].x + val * p[1].x + p[2].x) / val,
            (-p[0].y + val * p[1].y + p[2].y) / val,
            (p[1].x + val * p[2].x - p[3].x) / val,
            (p[1].y + val * p[2].y - p[3].y) / val,
            p[2].x,
            p[2].y
        ]);
    }
    return cubics;
}

引数に通過点の座標配列を入れれば、制御点を含んだベジェ曲線用の座標配列を返してくれます。

他にも、npmで公開している人もいました。
実際に使う時はこれをインストールしても良いさそうです。

頂点を間引いて滑らかにしたい

最初、単純に距離が近すぎる点を間引いていたのですが、あまりうまく機能しませんでした。
そこでポリゴンの線を単純化してくれるSimplify.jsを使うことにしました。
(CDNで公開されているものが見つからなかったので、成果物ではコードをコピペして使っています。)

成果物

http://codepen.io/kwst/pen/vgGgqN
上が滑らかにした線、下がフリーハンドで描いた線
スクリーンショット 2017-01-12 14.40.30.png
割りとなめらかになったかなと思います。
単純なお絵描きですが、線をなめらかにするだけでも結構骨が折れました。

Githubに公開してみました。
SVGCatmullRomSpline

39
29
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
39
29