JavaScriptでの乱数メモ

さくっと乱数が欲しい時にいつも方法を忘れるのでメモ。

  • Math.randomは0以上1未満のNumberを返す。
  • 0以上4未満の乱数を得たければMath.random() * 4とする。整数として欲しければMath.floorを使う。
    • 3以上7未満は0以上4(=7-3)未満に3を足せばOK。
  • 0以上4以下の場合は?
    • 整数でよければ5未満と同じなのでMath.floor(Math.random() * 5)でOK。
    • 整数でない場合、例えば0以上4.5以下とかは?Math.random() * 4.5では4.5にならない。
      • 4.5 * 100000 = 4500000なので、4500000以下の整数にしてから100000で割ればある程度の値が得られる。精度気にしなくていいならこの程度でOK。
// min以上max未満
function rnd1(min, max) {
  return min + Math.random() * (max - min);
}

// min以上max以下(整数)
function rnd2(min, max) {
  return min + Math.floor(Math.random() * (max - min + 1));
}

// min以上max以下(小数)
function rnd3(min, max) {
  return min + Math.floor(Math.random() * ((max - min) * 100000 + 1)) / 100000;
}

塗りつぶし図形の境目の問題

こんな描画コードを実行するとする。

CX.beginPath();
CX.moveTo(20, 20);
CX.lineTo(100, 20);
CX.lineTo(20, 100);
CX.fill();

CX.beginPath();
CX.moveTo(100,20);
CX.lineTo(100,100);
CX.lineTo(20,100);
CX.fill();

↓こんな結果を期待するのだけれども。

↓こうなる。境目がでてしまう。

ある程度単純な図形なら、いちいちパスを切らないでまとめてfillすればいいのだけれども、複雑な交差あったりすると、交差する部分が抜けてしまうので、そうしたくない場合は困る。

対策。

大きめに描くのは結構面倒そう。

canvasまとめ

基本

var CV = document.getElementById('canvas');
var CX = CV.getContext('2d');

canvasに対応しているかどうかは気にしない(気にするくらいだったら使わない)。

canvas自体のサイズを変える

CV.width = 256;
CV.height = 256;

CV.style.widthとかをいじると、canvas自体のサイズではなくて、表示サイズが変わって拡大縮小がかかる。

ビットマップをいじる

var DT = CX.getImageData(0, 0, CV.width, CV.height);
var DD = DT.data;

for (var p, y = 0; y < DT.height; ++y) {
  for (var x = 0; x < DT.width; ++x) {
    p = (x + y * DT.width) * 4;
    DD[p  ] = 255;
    DD[p+1] = 0;
    DD[p+2] = 0;
    DD[p+3] = 255;
  }
}

CX.putImageData(DT, 0, 0);

getImageDataとputImageDataを使う。ImageData.dataに画素情報が入っていてArrayっぽく操作できる。並びはR→G→B→alpha。

画像の描画

ImageとかIMG要素とかをdrawImageで描画できる。CANVAS要素も描画できるので、描画した一部分を拡大とかできる。

// (0,0)-(32,32)の範囲にいろいろ描画

// (0,0)-(32,32)を(0,0)-(256,256)に拡大して描画
CX.drawImage(CV, 0, 0, 32, 32, 0, 0, 256, 256);

座標

translate、scale、rotateで平行移動、拡大縮小、回転ができる。これらの変換は維持されるので、save→座標変換+描画→restoreとするのが無難。

setTransformやtransformで、せん断みたいな座標変換もできるけれども、3Dっぽいのは無理っぽい。

自分ルール

自分としては、左上が(0,0)になっているよりも、中央が(0,0)になっていたほうが楽。さらに、canvasのサイズが変更されても描画コードを変更しなくてもいいようになっていると楽。こういったことはtranslateとscaleで実現できる。

常に、(-300,-300)-(300,300)の範囲がcanvas内におさまるようにするにはこんな感じ。

var SIZE = 600, SIZE1_2 = SIZE >> 1;
var SCALE = 1;

function set_canvas_size() {
  var w = CV.width = window.innerWidth;
  var h = CV.height = window.innerHeight;
  SCALE = Math.min(w / SIZE, h / SIZE);
}

function my_draw() {
  CX.clearRect(0, 0, CV.width, CV.height);
  CX.save();
  CX.translate(SIZE1_2, SIZE1_2);
  CX.scale(SCALE, SCALE);

  // 描画コード

  // ↓これは常に画面の中央いっぱいに正方形の枠が描かれる
  CX.strokeRect(-SIZE1_2, -SIZE1_2, SIZE, SIZE);

  CX.restore();
}

window.addEventListener('resize', function() {
  set_canvas_size();
  my_draw();
}, false);

最近のjsdo.it

あんまりこっちを更新していなかったので最近jsdo.itに上げた分でお茶を濁す

Catmull-Romを使ってマウスで曲線を描く
http://jsdo.it/gct256/ghS9
棒人間を描くライブラリ
http://jsdo.it/gct256/Bouningen
↑を使ってダンシング
http://jsdo.it/gct256/hIZJ
マウス曲線をカリグラフィっぽく
http://jsdo.it/gct256/ca5S
↑を虹色に
http://jsdo.it/gct256/yVPb
画像を使ったブラシのテスト
http://jsdo.it/gct256/cgVl

マウスで描画とかやっていたら、キッドピクスとかTuxPaintのようなお絵かきソフトに発展させたくなってきた。高機能なペイントソフト/ドローソフトはいっぱいあるけれども、キッドピクスみたいなのはあんまりないような気がする。

Firefox + MacBook-Proで加速度センサ

http://journal.mycom.co.jp/news/2009/08/25/062/index.htmlによると、Firefoxの最近のものでは、MacBook-Proの加速度センサを検出できるようなので、試してみた。

http://jsdo.it/gct256/qfRX

iPhoneとかと違って、本体を傾けたりするのがいまいちやりづらいものの、動いた。手元のはEarly 2008と呼ばれているMacBook-Proだけど、他のMacBook-ProとかMacBookとか、そもそもMacBook以外でも動くのか。対応機器が少ないとあんまり使いではなさそう。

iPhoneとかで使えれば利用価値がありそうだけれども、Mobile Safariでは無理っぽい(90度刻みの回転しか検出できないっぽい)。他のプラットフォームは持ってないので調べてない。