【Canvas】mousemoveのタイミングで円を描くときに円が離れてしまう問題

こんにちはー。

前回、arc を使って描いた時、円が散らばらないようにする方法を紹介すると書いたので書きます。

【JS】Canvasで丸や四角で「消す」方法
こんにちはー。題名のとおり、Canvas の「消す」機能で、丸などに形を変える方法を紹介します。「消す」機能についてまずはじめに、消す方法としてのルールを書いておき...

まず、下の例を見てください。

うまくいかない例

See the Pen Canvas Mousemove 円で描いてうまくいかない例 by shundroid (@shundroid) on CodePen.dark

よくありがちなコンテンツです。
mousemove のイベントが発生した時に円を描いているわけですが、
めっちゃ速く動かして書くと、円と円の間が空いてしまいます。

今回は意外と初歩的なことかもしれませんが、
この、間が空かないようにする方法を描きます。

moveToとlineToを使う

実際に moveTo と lineTo でやった例は、こちらです。

See the Pen Canvas mousemove lineToとmoveTo by shundroid (@shundroid) on CodePen.dark

この方法は、円で描くのではなく、線で描いています。
そのため、円と円の間が描けるわけです。

では、使っている関数を紹介したいと思います。

moveTo 関数

線の始点を指定します。
ここでは、ひとつ前の mousemove での座標、もしくは mousedown での座標を指定しています。

lineTo 関数

lineTo で指定した始点から、
線を引くときの終点を指定します。
ここでは、現在の座標を指定しています。

色を変えるには

CanvasRenderingContext2D.strokeStyle で取得・変更できます。

var ctx = canvas.getContext("2d");
ctx.strokeStyle = "red"; // 赤
ctx.strokeStyle = "green"; // 緑

参考: https://developer.mozilla.org/ja/docs/Web/API/CanvasRenderingContext2D/strokeStyle

太さを変えるには

CanvasRenderingContext2D.lineWidth で取得・変更できます。
円で描いた時は、arc メソッドの第3引数で指定していたので、それの代わりです。

var ctx = canvas.getContext("2d");
ctx.lineWidth = 100;

詳しいサイト

Canvasで使える関数が紹介されています。
「こんな機能あったんだ~」という新発見もあるので、一度見てみてください!

【JS】Canvasで丸や四角で「消す」方法

こんにちはー。
題名のとおり、Canvas の「消す」機能で、丸などに形を変える方法を紹介します。

「消す」機能について

まずはじめに、消す方法としてのルールを書いておきます。

  • 白く塗る はダメ!(背景が白でない場合があるため)
  • 消した部分は透明になるようにする。

実装のポイント

context の globalCompositeOperation を、destination-out に変更すると、
fill や stroke で指定した領域を 切り取る ことができます。

また、このプロパティは、その他いろいろな値に変更できます。

サンプル:円形で消す

globalCompositeOperationを変更した状態で、arc メソッドを呼ぶことでできます。

var ctx = document.getElementById("xxx").getContext("2d");
function eraseArc() {
  ctx.globalCompositeOperation = "destination-out";
  ctx.beginPath();
  ctx.arc(100, 100, 50, 0, Math.PI*2, false);
  ctx.fill();
}

arc() の引数

arc(中心x, 中心y, 半径, 開始角度(ラジアン), 終了角度(ラジアン), どっち回りか(true→反時計回り))

応用例

See the Pen Canvas Erase By Arc by shundroid (@shundroid) on CodePen.dark

  • チェックボックス ON:描く、OFF:消す(globalCompositeOperation で切り替えています)
  • 背景色を変更で、消した部分が透明になっていることを確認できます

掲載したサンプルコードでは、ctx.arc で描画していますが、
このサンプルは mousemove で動いた時に描いているので、arc で描くと円が散らばってしまい、うまく描けません。
そのため、moveTo と、lineTo を使って描いています。

この方法については、次回ブログで書きたいと思います。

「消す」モードを戻したい

このままでは、常に stroke や fill した部分が切り取られてしまうため、
元の値に戻しておきましょう。
デフォルトの値は、source-over です。

var ctx = document.getElementById("xxx").getContext("2d");
ctx.globalCompositeOperation = "source-over";

【Rx.js】画像を非同期に読み込むサンプルコード

こんにちはー。

非同期の処理をいい感じに使える js のライブラリないかなーと探していたら、
Rx.js というのを見つけたので、それを使ったサンプル?を紹介します。

Rx.js とは?

.NET 向けの Reactive Extensions を js 用に移植したもの。
ぼくは、最初 .NET の方を使っていて、
「それの js 版があったらいいな~」と思っていたらピンポイントであったという感じですー。

コードの概要

では、今回書いてみるコードの概要を紹介します。

  1. 3つの画像が配列になっている
  2. それらを非同期で読むが、1つ読み終わったら次を読むという条件。
  3. 1つ読み終わった後と全部読み終わった後にコールバックする

全部いっぺんに非同期で読めばいいと思うかもしれませんが、
画像がウエーブみたいになって読み込まれていくようにしたかったんです。

【Before】Rx.js を使わない場合のコード

var images = ["1.png", "2.png", "3.png"];
function loadImages(oneByOne, finished) {
  var index = 0;
  var loadImage = (name) => {
    var elem = document.createElement("image");
    elem.src = name;
    elem.onload = function() {
      oneByOne(index);
      if (index >= images.length - 1) {
        finished();
      } else {
        loadImage(images[++index]);
      }
    }
  };
  loadImage(images[index]);
}
function main() {
  loadImages((index) => {
    console.log(index + "個目を読み込みました");
  }, () => {
    console.log("読み込み完了");
  });
}

このコードを、Rx.js を使って、シンプルにしてみます。

【After】Rx.js の降臨

// 読み込むとき、ES6 ( + browserify) だと便利
import Rx from "rx"; // ES6 modules

var images = ["1.png", "2.png", "3.png"];
function loadImages() {
  return Rx.Observable.create(loadImagesObservable);
}
function loadImagesObservable(observer) {
  var index = 0;
  var loadImage = (name) => {
    var elem = document.createElement("image");
    elem.src = name;
    elem.onload = function() {
      observer.onNext(index);
      if (index >= images.length - 1) {
        observer.onCompleted();
      } else {
        loadImage(images[++index]);
      }
    }
  };
  loadImage(images[index]);
  return function() { };
}
function main() {
  var subscription = loadImages().subscribe((index) => {
    console.log(index + "個目を読み込みました");
  }, err => {
    console.log("Observe Error: " + err);
  }, () => {
    console.log("読み込み完了");
  });
}
  • 1つ読み終わった時 -> observer.onNext
  • 全部読み終わった時 -> observer.onCompleted

に当てはめました。

Rx.js を使うメリット

キャンセル時の処理を追加できる

上のコードでは書いていませんが、
subscription.dispose でキャンセルでき、
loadImagesObservable の返り値の関数で、dispose された時の処理を追加できるので、
そこで読み込みの処理を停止するように書けば、簡単にできます!

キャンセル時の処理を書いた例: Gist

filter ができる

loadImages().subscribe(...) を、loadImages().filter(...).subscribe(...) にすれば、
フィルターを通すことも簡単にできます。

フィルターを使った例として、「5回に1回、○個目を読み込みましたと表示」するようにしてみます。

// function main() 内を変更
function main() {
  var subscription = loadImages().filter(index => index % 5 === 0).subscribe((index) => {
    console.log(index + "個目を読み込みました");
  }, err => {
    console.log("Observe Error: " + err);
  }, () => {
    console.log("読み込み完了");
  });
}

フィルターを利用した例の全コード: Gist

参考

「RxJS」初心者入門 - JavaScriptの非同期処理の常識を変えるライブラリ | 株式会社LIG
こんにちは、王です。 みなさん、「RxJS」をご存知でしょうか? すごく大雑把に言うと、RxJSとは非同期処理(マウスクリックなどのイベントベースの処理も含める)をす...

追記

2016-04-07 : Rx.js を使ったメリットを中心とするように記事の内容を全面改訂。

【WordPress】MarkdownでSyntaxHighlighter Evolvedを使うとき、「<」などと変換されてしまう

WordPress - MarkdownとSyntaxHighlighterを併用する。 - Qiita
WordPressでMarkdownを利用している間にソースコードを記述しようとすると、 **<code><</code>**や<strong><code>></code></s...

まさにドンピシャでした!ありがとうございます!!


このようになっているコード。

() => { の、>の部分が見事に&gt;になってしまうんです。

そんなときは、次のように書きましょう。

ポイントは、‘‘‘と書いていたところを、divタグとショートコードで書くところです。

これで解決!budougumiさんありがとうございます。