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すればいいのだけれども、複雑な交差あったりすると、交差する部分が抜けてしまうので、そうしたくない場合は困る。
対策。
- 大きめに描く
- fillだけでなくstrokeも使って境目を消す。これ→ http://jsdo.it/gct256/ca5S
- fillにたよらない。これ→ http://jsdo.it/gct256/cgVl
大きめに描くのは結構面倒そう。
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);
そのまえに
CSのどっかのチャンネルをみてると頻繁にCMが入るこれを再現するというのはどうだろう?
最近の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の加速度センサを検出できるようなので、試してみた。
iPhoneとかと違って、本体を傾けたりするのがいまいちやりづらいものの、動いた。手元のはEarly 2008と呼ばれているMacBook-Proだけど、他のMacBook-ProとかMacBookとか、そもそもMacBook以外でも動くのか。対応機器が少ないとあんまり使いではなさそう。
iPhoneとかで使えれば利用価値がありそうだけれども、Mobile Safariでは無理っぽい(90度刻みの回転しか検出できないっぽい)。他のプラットフォームは持ってないので調べてない。