HEXA BLOG

プログラム

HEXA BLOGプログラム2012.2.6

たまには失敗のjavaScript

お久しぶりです。
前回のブログ1月以上の間が空きまして、
この間色々な事がありました。
間もなく引越し予定のgood sun晴れこと山口です。
今回もJavaScriptネタをやろうとしたのですが、
最初にお断りさせて頂きますが、一部失敗しました。ふらふら
そんな時もあります。
まずは何がしたかったのか説明させて頂きます。
以前JavaScriptでマルチタッチ手(チョキ)が取れるというお話を書かせて頂きました。
今回はいつもより少し時間があったので
このタッチについてサンプルを作ってみようとしました。
そこまでは良かったのです。
問題は音るんるんを鳴らしてみようと思った所です。
GoogleChromeでは

var audio = new Audio(音データ);
audio.play();

で音が鳴ります。
ここまでは確認しました。
まだ問題ありません。
これをAndroidで確認すると…
鳴りません。
おかしいと思い検索エンジンで調査を開始しました。
なんと現行のAndroidやiOS端末のブラウザはJavaScript単体で音を鳴らすことが出来ないようです。
完全に調査不足でした。
しかし失敗はこれだけに留まりません。
どのように失敗なのかは今回のサンプルを実行していただくのが早いと思います。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name=”viewport” content=”width=480, user-scalable=no, maximum-scale=0.6667″ />
<title>javascriptサンプル</title>
</head>
<body>
<dir style="vertical-align: middle; margin-left:auto; margin-right:auto;">
<canvas id="canvas"></canvas>
</dir>
</body>
<script type="text/javascript" charset="UTF-8">
//! ノード管理クラス
function NodeManager(){
this.nodes = new Array();
}
NodeManager.prototype.create = function(x, y){
this.nodes.push(new Node(x, y));
}
NodeManager.prototype.update = function(){
for(var i = this.nodes.length - 1; i >= 0; i--){
if(!this.nodes[i].update()){
if(i == 0){
if(this.nodes.length > 1){
this.nodes = this.nodes.slice(1, this.nodes.length);
}else{
this.nodes = new Array();
}
}else{
if(i + 1 == this.nodes.length){
this.nodes = this.nodes.slice(0, i);
}else{
var tmparray = this.nodes.slice(0, i);
this.nodes = tmparray.concat(this.nodes.slice(i + 1, this.nodes.length));
}
}
}
}
}
NodeManager.prototype.draw = function(context2d){
for(var i = 0; i < this.nodes.length; i++){
this.nodes[i].draw(context2d);
}
}
var nodeManager = new NodeManager();
//! ノードクラス
function Node(x, y){
// パラメータはランダムで決定
this.posx = x;
this.posy = y;
this.color = "#"+((Math.floor(Math.random()*255) << 16) | (Math.floor(Math.random()*255) << 8) | Math.floor(Math.random()*255)).toString(16);
this.isFill = Math.random() > 0.5 ? true : false;
this.width = Math.floor(Math.random()*10) + 3;
this.rad = 5;
this.life = Math.floor(Math.random()*10) + 30;
}
//! 更新関数
Node.prototype.update = function(){
this.rad += 10;
this.life--;
if(this.life <= 0){
return false;
}
return true;
}
//! 描画関数
Node.prototype.draw = function(context2d){
context2d.beginPath();
context2d.arc(this.posx, this.posy, this.rad, 0, 360, false);
if(this.isFill == true){
context2d.fillStyle = this.color;
context2d.fill();
}else{
context2d.strokeStyle = this.color;
context2d.lineWidth = this.width;
context2d.stroke();
}
context2d.closePath();
}
//! フレーム管理クラス
function Frame(){
var _this = this;
// クリアカラーとキャンバスサイズ
this.clearColor = "#202030";
// コンテキストの準備
this.canvas = window.document.getElementById("canvas");
this.context2d = this.canvas.getContext('2d');
this.canvas.width = document.body.scrollWidth;
this.canvas.height = document.body.scrollHeight;
// クリアカラーでクリアする
this.context2d.fillStyle = this.clearColor;
this.context2d.fillRect(0, 0, this.canvas.width, this.canvas.height);
// タッチイベントの追加
document.getElementsByTagName("body").item(0).ontouchstart = function(event){
_this.onTouchStart(event);
};
document.getElementsByTagName("body").item(0).ontouchmove = function(event) {
_this.onTouchMove(event);
};
document.getElementsByTagName("body").item(0).ontouchend = function(event) {
_this.onTouchEnd(event);
};
// もしくはクリック
this.canvas.onclick = function(event){
_this.onMouseClick(event);
}
}
Frame.prototype.onMouseClick = function(event){
nodeManager.create(event.clientX, event.clientY);
}
Frame.prototype.onTouchStart = function(event){
event.preventDefault();
event.touches.length;
for(var i = event.touches.length - 1; i >= 0; i--){
nodeManager.create(event.touches[i].pageX, event.touches[i].pageY);
}
}
Frame.prototype.onTouchMove = function(event){
event.preventDefault();
}
Frame.prototype.onTouchEnd = function(event){
event.preventDefault();
}
//! 実行
Frame.prototype.run = function(lastTime){
// クリア
this.context2d.fillStyle = this.clearColor;
this.context2d.fillRect(0, 0, this.canvas.width, this.canvas.width);
nodeManager.update();
nodeManager.draw(this.context2d);
//! 更新を行う
var nowTime = new Date();
// 20FPS
var nextTime = 50 - (nowTime.getTime() - lastTime.getTime());
if(nextTime <= 0){
nextTime = 1;
}
var _this = this;
setTimeout(function(){_this.run(nowTime);}, nextTime);
}
var frame = new Frame();
frame.run(new Date());
</script>
</html>

動くのはこちらから
(動作確認が出来ているのは、Android+OperaMobile、iOS+Safariです。
残念ながらAndroid+標準ブラウザではマルチタッチ認識しないようです。
iOS+OperaMiniはそもそもタッチ認識しませんでした。)
…画面サイズがおかしいです。
フルスクリーンをやりたいなと思ってみたのですが御覧の結果です。
何事も慌ててやってはいけないという事ですね。
反省です。
次回までの課題ですね。
今回の目玉目マルチタッチの取得に関しては

document.getElementsByTagName("body").item(0).ontouchstart = function(event){
_this.onTouchStart(event);
};

この辺が該当の箇所になります。
ちゃんとクロージャな呼び出しも健在です。
次は今回カットした音に関連してデータに関して何かやれたらなと思っています。
ではまた。手(パー)

RECRUIT

大阪・東京共にスタッフを募集しています。
特にキャリア採用のプログラマー・アーティストに興味がある方は下のボタンをクリックしてください

RECRUIT SITE 

NEWS