第一引数 文字列又は関数オブジェクト
function test() { alert('test'); }; setTimeout(test, 1000);//1ms後実行 setTimeout(test(), 1000);//評価時に即実行 setTimeout('test()', 1000);//1ms後実行 setTimeout('test', 1000);//単なる文字列なので何も起こらない
第一引数が文字列の時evalされる。
引数を渡したいとき、
var str = 'str'; function test(arg) { alert(arg); }; setTimeout('test("' + str + '")', 1000); //一応可能 setTimeout(function(){test(str)}, 1000); //無名関数を渡せば問題無い
var arr = [1,2,3]; for(var i=0,len=arr.length;i<len;i++){ setTimeout(function() { console.log(arr[i]);//undefined×3 }, i * 1000); };
setTimeout内でarrにアクセスできていないのかと一見思った。 がiがブロックスコープの為このコンソールは全てarr[3]にアクセスし undefinedが返っている。
var arr = [1,2,3]; console.log(i);//undefined>条件式で定義されてるからエラーではない for(var i=0,len=arr.length;i<len;i++){ console.log(i);//0,1,2 setTimeout(function() { console.log(i);//3,3,3>ブロックスコープでは無い為 }, i * 1000); }; }; console.log(i);//3>条件式で3回インクリされた状態で残る var arr = [1,2,3]; for(var i=0,len=arr.length;i<len;i++){ (function(arg) { setTimeout(function() { console.log(arr[arg]);//1,2,3 }, arg * 1000); })(i); }; //クロージャにてスコープをキープ
forで回してDOM要素にアクセスしてイベントハンドリング。 参考までに画像を見込んだ順にフェードインするスクリプト。
<style type="text/css"> h1 { font-family: Helvetica, Arial; text-align: center; } #gallery { width: 95%; margin: 0 auto; padding: 5px; border: solid 1px #ccc; border-radius: 5px; } #gallery li { list-style-type: none; width: 200px; height: 200px; display: inline-block; background: url('load.gif') no-repeat center; } #gallery img { width: 200px; height: 200px; opacity: 0; } </style>
<h1>- gallery -</h1> <ul id="gallery"> <li><img src="1.png" /></li> <li><img src="2.png" /></li> <li><img src="3.png" /></li> <li><img src="4.png" /></li> <li><img src="5.png" /></li> <li><img src="6.png" /></li> <li><img src="7.png" /></li> <li><img src="8.png" /></li> <li><img src="9.png" /></li> <li><img src="10.png" /></li> <li><img src="11.png" /></li> <li><img src="12.png" /></li> </ul>
とりあえず、変数iをクロージャでキープ
onloadイベントの前に無名関数でスコープを作らないと
onloadが実行される時にはみんな同じiを参照してしまう、、、。
setTinerval内も無名関数のスコープで実行できる。
<script type="text/javascript"> var gallery = document.getElementById('gallery'); var elem = gallery.getElementsByTagName('img'); var timerId = []; var count = []; for(var i=0,len=elem.length;i<len;i++) { count[i] = 0; (function(arg) { elem[arg].onload = function() { timerId[arg] = setInterval(function(){fade(arg)}, 50); }; })(i); }; function fade(tar) { if(elem[tar].style.opacity >= 1) { clearInterval(timerId[tar]); } else { count[tar] += 0.1; elem[tar].style.opacity = count[tar]; }; }; </script>
こん度は頑張ってthisとか使ってみる。
そんで、ついでにmouseoverとかも追加してみる。
<script type="text/javascript"> function ImgObj(img) { var that = this; this.img = img; this.duration = 0.1; this.img.addEventListener('load', function() { that.fadeIn() }, false); this.img.addEventListener('mouseover', function() { that.fadeOut() }, false); this.img.addEventListener('mouseout', function() { that.fadeIn() }, false); }; ImgObj.prototype.fadeIn = function() { var that = this; if(this.fadeTimer) { clearInterval(this.fadeTimer); } else { this.opacity = this.img.style.opacity = 0; }; this.fadeTimer = setInterval(function() { that.chgOpacity(1) }, 50); }; ImgObj.prototype.fadeOut = function() { var that = this; if(this.fadeTimer) { clearInterval(this.fadeTimer); } else { this.opacity = this.img.style.opacity = 1; }; this.fadeTimer = setInterval(function() { that.chgOpacity(0) }, 50); }; ImgObj.prototype.chgOpacity = function(limit) { this.opacity = Math.round(this.opacity * 100) / 100; if(this.opacity == limit) { clearInterval(this.fadeTimer); } else { this.opacity += limit ? this.duration : -this.duration; this.img.style.opacity = this.opacity; }; }; var gallery = document.getElementById('gallery'); var elem = gallery.getElementsByTagName('img'); var imgObj = []; for(var i = 0, len = elem.length; i < len; i++) imgObj[i] = new ImgObj(elem[i]); </script>
クロージャなしでいけるのか?
しかしイベントリスナ部でthisを
使用するとそこはやはりそのイベント発生元のDOMを参照する。
setInterval内でのthisはwindowを参照する。
それでこのthisの参照が違うって聞くと、いよいよかっこよさげなapplyとか callが使えるの??って思って考えたけどよく理解していませんので 使い道が思いつきませんでした。
基本的にthisをローカル変数に代入してクロージャで参照するって感じでしょうか。
前から思ってたけどこういうイベントハンドリングみたいなのを クラスとか使う書き方が全くもってわからん。
なので我ながら
意味不明なコードになってます。
結局クロージャです。正直クロージャってのもあまり理解できていません。
なんか検索しようとするとメモリリークとかサジェストで出てくるし。
しっかり理解した方が良さそうさな。
]]>以下fileReaderに関するメモです。。
iPhoneってinput type="file"が使えなかったんですよね。
これ結構残念な仕様だなぁとずっと思ってました。
それがついに開放!
そしてこのブログでも長いことひっぱてますお絵かきアプリ、
以前作ってみた時、撮った写真にお絵かきできたらいいな、
と思ったのですが、
まぁ、まずファイルにアクセスできないし、ブラウザだけで
完結できないし、とか考えつつあきらめていたのですが、
iOS6にて両方いけるようになったのでとりあえず試してみました。
ちなみに1点残念な事がありまして、どーやらwindows版safariの
提供が終了してしまったようで、win safariはfileReaderが使えないまま
最後を迎えてしまったようです。。。
input type="file"ってそーいえばデザインどーする?!
とちょっとググってみたら、透明にして重ねる!みたいな記事が
結構ヒット。やっぱり同じ悩みを持つ方は結構いるんだなと。
html
<ul> <li>写真にお絵かき<input type="file" id="fake" /></li> <li>・・・・</li> <li>・・・・</li> <li>・・・・</li> </ul>
css
li { line-height: 75px; position: relative; margin: 0 auto; width: 320px; } #fake { position: absolute; top: 0; left: 0; width: 100%; height: 100%; opacity: 0; }一応webkit系であればli全体がクリックできた
var tar = $("#illustMenu li"); //input type file、fileReader使える?? if(!window.FileReader || $('#fake').get(0).disabled) $(tar[0]).css('display', 'none'); $("#illustMenu li").bind("click", function() { scrollTo(0, 0); var index = $("#illustMenu li").index(this); var myImg = new Image(); if(!index) { var $fake = $('#fake').get(0); $fake.onchange = function() { var file = $fake.files[0]; if(!file.type.match('image.*')) { alert('画像以外は読込めません'); return; }; var fr = new FileReader(); fr.onload = function() { myImg.src = fr.result; callback(); }; fr.onerror = function() { alert('読込めませんでした'); }; fr.readAsDataURL(file); }; } else { myImg.src = "img/illust/" + index + ".png"; callback(); }; function callback() { myImg.onload = function() { var iw = myImg.width; var ih = myImg.height; if(!index) { ・・・・・ ・・・・・ }; if(W > 600 && !retina) { ctx.drawImage(myImg, 0, 0, iw, ih); } else { ctx.drawImage(myImg, 0, 0, iw/2, ih/2); }; }; }; });とりあえずfileReaderが使えるか?input type fileが使えるか?
ではiPhoneで確認。
問題なくファイル選択画面登場。
適当な写真を選択。
まったくもってきちんと描画されない、、、、。
縦、横もおかしい。
ググってググってまたググって。
そこでふと思い出したMobileSafariのリソース制限。
これかぁ。
canvasにリサイズして書き出したくても
どーにもきちんと読み込まれない。
これはやっぱりimageオブジェクトで読み込んだ時
おかしくなってるのか??
上限35メガピクセル。
iPhone4sのカメラは800万画素で8メガピクセル。
ただ2メガピクセル以上はうんたらかんたら。
よくわからん。
さらにcanvasの上限は2メガバイト。
よくわからん。
まず4sで撮影したデフォルト画像はcanvasに書き出した際
おかしなことになる。さらに縦・横認識していない。
しかしフォトストリームから読み込むと問題なく書き出され
縦・横も認識される。
iPad2で撮影したデフォルト画像はcanvasに書き出した際
きちんと書き出されるが縦・横が認識されていない?
ただiPad2で4sで撮影したフォトストリームの画像は
問題なく書き出され縦・横も認識された。
3GSではフォトストリームの画像もおかしなことに、、、。
うーんよくわからん。
おそらくそのRAMとリソース制限の関係でしょうか??
描きだし時にバグるのはしょうがないとして
なぜ縦・横を認識しない?
ググってみると画像にはExifという画像の様々なデータ
が書き込まれたものがあると。なるほど。
そんでそれはバイナリデータで抽出可能。
なんともめんどくさそう。
fileapiに出会った時これは一体何に使うんだ?
と思っていったreadAsArrayBuffer。
バイナリデータを読み込めます。
まさか早速お世話になるとは。
JPEG画像からExif情報を抽出する
未知な世界のバイナリ。
ということでとりあえず上のコードをお借りして
いったんExifデータを確認させていただくと、
しっかりorientation6又は1となってる。
これで分岐すればとりあえず対応はできそう。
そのうちバイナリの勉強でもしよう。
まともには使えませんがとりあえず実装してみました。
それとあまり関係ありませんがgetImageDataで取得した
imageDataオブジェクトをputImageDataで描き出す際
変換マトリックスを適用する方法ご存知の方いませんでしょうか??
回転させたいだけなんですが、、、。ご存知の方コメントいただけたら
うれしいです。
いつもいつも簡単に終わるかなと思って取り掛かるんですが、
予想外の時間がかかってしまいます。
いい加減他の勉強を始めなければ、、、
.navi li { width: 100%; border-bottom: solid 1px #ccc; } .navi li a { text-decoration: none; display: block; padding: 10px 20px 10px 10px; margin-right: 5px; background: url('../images/arrow.png') no-repeat right center; -webkit-background-size: 20px 20px; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; }
(function() { // セッションストレージに対応してるか? if(typeof sessionStorage === 'undefined') return; var spFlag = false; var n = navigator.userAgent; var uap = new RegExp('iPhone|Android.+Mobile|iPod'); //ユーザーエージェントにてスマホ判別 if(n.match(uap)) { spFlag = true; //対応しててもプライベートブラウズだとエラーになってしまうので。 try { //セッションスタートかどうかチェック //confirmはお好みで //if(sessionStorage['SPorPC'] == undefined) sessionStorage['SPorPC'] = confirm('スマートフォン用サイトを表示しますか?') ? 'sp' : 'pc'; if(sessionStorage['SPorPC'] == undefined) sessionStorage['SPorPC'] = 'sp'; } catch(e) { //プライベートブラウズ時、他ストレージエラー時はスマホフラグをfalseに spFlag = false; }; }; //PC、スマホ切り替えボタンにclickイベントをliveで紐付け $('#pc, #sp').live('click', function() { sessionStorage['SPorPC'] = this.id; scrollTo(0,0); //changeView();// no load location.reload();// reload }); function changeView() { //スマホの時のみ呼ばれsessionStorageがPCかSPかを //判別してフラグを書き換えます。 spFlag = !(sessionStorage['SPorPC'] == 'pc'); //既存(PC用)のスタイルシートをデフォルトのままかスマホ用に書き換えてます。 //全てのスタイルシートを書き換えてるので変更の無いCSSもスマホ用が必要になってしまいますが、、、。 //下はスマホ用は頭に「sp_」を付けて正規表現でパスを書き換えています。 var $path = $('link[rel="stylesheet"]'); for(var i = 0,len = $path.length; i < len; i++) { $path[i].href = changePath($path[i].href); }; function changePath(path) { //コピペするとこの正規表現のバックスラッシュがエラーになりますのでご注意を。 var trim = path.match(/sp_[0-9a-z]+¥.css|[0-9a-z]+¥.css/); trim[1] = (spFlag) ? 'sp_' + trim[0] : trim[0].replace('sp_', ''); var changedPath = path.replace(trim[0], trim[1]); return changedPath; }; //viewportをheadに挿入 if(spFlag) { var meta = '<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0" />'; $('head').append(meta); } else if(!spFlag && n.indexOf('Android') != -1) { //AndroidはPCサイトに切り替えた際PC用のwidthをviewportに設定しないとdivice-widthのままになっているような気がします。 var meta = '<meta name="viewport" content="width=980" />'; $('head').append(meta); }; $(function() { //スクロールしてURLバーを隠します scrollTo(0,1); //PCからスマホ、スマホからPCへの切り替えボタンを挿入。 if(spFlag) { var btn = '<div id="spbtn"><a href="javascript:void(0);" class="btn" id="pc">PC</a></div>'; $('h1').after(btn); var $switch = $('#switch'); if($switch) $switch.remove(); } else { var swt = '<div id="switch">表示切替 : <a href="javascript:void(0);" id="sp">スマートフォン</a></div>'; $('#footer').after(swt); var $spbtn = $('#spbtn'); if($spbtn) $spbtn.remove(); }; }); }; //スマホだったらchangeViewを実行 if(spFlag) changeView(); })();
div.css-testbox { margin: 10px auto; width: 300px; height: 300px; border: solid 1px #cdcdcd; } div.box-prefix { -webkit-border-radius: 10px; -moz-border-radius: 10px; -o-border-radius: 10px; -ms-border-radius: 10px; -webkit-box-shadow: 0px 0px 5px 3px rgba(0,0,0,.2); -moz-box-shadow: 0px 0px 5px 3px rgba(0,0,0,.2); -o-box-shadow: 0px 0px 5px 3px rgba(0,0,0,.2); -ms-box-shadow: 0px 0px 5px 3px rgba(0,0,0,.2); } div.box-without-prefix { border-radius: 10px; box-shadow: 0px 0px 5px 3px rgba(0,0,0,.2); } @-webkit-keyframes rotate { 0% { -webkit-transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg) } } @-moz-keyframes rotate { 0% { -moz-transform: rotate(0deg); } 100% { -moz-transform: rotate(360deg) } } @-o-keyframes rotate { 0% { -o-transform: rotate(0deg); } 100% { -o-transform: rotate(360deg) } } @-ms-keyframes rotate { 0% { -ms-transform: rotate(0deg); } 100% { -ms-transform: rotate(360deg) } } @keyframes rotate { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg) } } /* animation-name: ;keyframeの名前 animation-duration: ;実行時間(1000sm>1s>1秒) animation-timing-function: ;easing animation-delay: ;開始時間(1000sm>1s>1秒) animation-iteration-count: ;実行回数(infinite>無限) aniamation-direction: ;反転再生(normal,alternate) */ .animation-prefix { -webkit-animation: rotate 5s ease-in-out infinite; -moz-aniamation: rotate 5s ease-in-out infinite; -o-animation: rotate 5s ease-in-out infinite; -ms-animation: rotate 5s ease-in-out infinite; } .animation-without-prefix { animation: rotate 5s ease-in-out infinite; } /* transition-property: ;cssプロパティ名(all,none,プロパティ名) transition-duration: ;実行時間(1000sm>1s>1秒) transition-timing-function: ;easing transition-delay: ;開始時間(1000sm>1s>1秒) */ .transition-prefix { width: 100%; height: 100%; -webkit-transition: width 500ms ease-in-out 0, height 1s ease-in-out 0; -moz-transition: width 500ms ease-in-out 0, height 1s ease-in-out 0; -o-transition: width 500ms ease-in-out 0, height 1s ease-in-out 0; -ms-transition: width 500ms ease-in-out 0, height 1s ease-in-out 0; } .transition-without-prefix { transition: width 500ms ease-in-out 0, height 1s ease-in-out 0; }いつも思い出せないcss3 animationとtransitionとプレフィックスのメモ。
.transition-prefix:hover { width: 80%; height: 80%; } .transition-without-prefix:hover { width: 80%; height: 80%; }
<div id="scratchBox"> <div id="cover"> <span id="back" class="btn"><<back</span> <span id="next" class="btn">Loading....</span> </div> <canvas id="can"></canvas> <canvas id="can_bg"></canvas> <canvas id="can_is"></canvas> </div>scratch.js、scratch.cssがまぁベースになりまして、
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<title>test</title>
<script type="text/javascript">
window.onload = function() {
console.log('test' in window);
test.addEventListener('click', function() { alert('click') }, false);
};
</script>
</head>
<body>
<div id="test">test</div>
</body>
</html>
はい。jquery mobileを試しに使ってみたいな、と前々から思っていて、
とりあえず何かサクッと作れそうな物を、、、と考えて、
GoogleMaps APIを使った場所メモアプリを作ってみました。
★主な機能★
・現在地の住所とメモを保存。
・住所で地図を検索してメモと保存。
・移動ルートをメモと保存。
・重要度を付けて保存データを並び替え。
・メモと場所のURLをメールで送信。
・データのエクスポート・インポート。
★対応機種★
・iPhone、iPad
・Androidも使えるとおもうのですが、、、。
・一応最近のブラウザでしたらPCでもデータの読み書きは可能です。
データは端末に保存されるのみで、サーバにあげてみなんで共有!
みたいなことはありません!見れるのはこの端末からのみ。
個人的にはそのほうがいいような、、、ウソです。スキルがありません。
バグなど修正できるかわかりませんがお気軽にご指摘下さい。
※住所・場所など精密なものではありませんのでご注意下さい。
safariのプライベートブラウズだとデータの読み書きができませんので
ご注意下さい!!
またもありふれた地図アプリ+メモアプリです。いいんです。次に繋げます。
そして案の定サクッとは作れませんでした。
謎のキャラが気持ち悪い仕上がりになってしまいました。
すごいです。簡単にスマホサイトが作れます。
しかしやっぱり凝ったデザインにするには知識が要りそう。。。
アプリケーションキャッシュなど使えばかなり快適になる!と思いましたが、
あまり勝手にデータを保存するのもなぁ、
それにオフラインでは機能しないアプリだし。というこでキャッシュは止め。
スクリプトから動かした要素をリフレッシュするのに手間取りました。
なんか一度そのページを故意にロードしないとどうもうまくいきませんでした。
それと<input type="range">のスライダーを設定すると左に数値のボックスと
右にスライダーが設置されるはずなのですが、ダイアログ内に設置すると
なぜかsafariだけ両方スライダーになってしまいました。
<input type="number" data-type="range" name=〜 />
と設定することで回避できました。これはそういう仕様なのでしょうか??
それとテーマローラーでICONをBlackのW/Odiscに設定したら、
/* HD/"retina" spriteの部分だけwhiteのアイコンが設定されていて
retinaディスプレーのみアイコンが表示されず悩んでしまいました。
とりあえず使ってみた感じはサクッと作るのには大変便利だけど
オリジナリティを出すにはやはりそれなりの労力が要りそうだなぁ。
これまた素晴らしい。ゼロからスタートして使ってみたんですが、
動作は軽いし一通りマニュアル目を通せばなんとかなっちゃう感じが素晴らしい。
これに関してもサクッと簡単にできちゃう部分と、奥がそうな部分と
ただただ感心してしまいました。
ただjquery mobileみたいなので使用するとき、
ページを移動(page divを入れ替え)したときdisplay: noneに設定されると、
マップのページに戻り再度表示した際
ページを表示した後にresizeイベントをトリガしないと
マップがずれてしまうことがありました。
というかマップを表示するdivを表示してからマップを表示しないと
マップの位置がずれてしまうようです。
ま、正直細かいことは良くわかりません!
jquery mobileのフレームワークに、GooleMapsAPIのスクリプトを
お借りして一体自分はなにを作ったんだ???
こういう素晴らしいものを作る技術、それを使ってビックリするようなものを
作るアイデア、それ以上に見てるだけでも楽しめるデザイン力などなど、
プロフェッショナルな方々は凄いなぁ。
まぁ何をやっても無駄なことはない!はずなのでこつこついろいろがんばろう。
得意のスパゲッティーコードに仕上がりました。
初めてコンストラクターを使用!
これ別にHTML5じゃなくてもいいんじゃないか??
Rethinaディスプレーに振り回されました。
イラストが苦手。。。
タイマー関数が不安。
スタイルの切り替えとかjavascriptでやるのと、CSSのメディアクエリでやるの
どっちがいいんでしょう?
などなど。
フォトショップの勉強しよ。