2017년 1월 3일 화요일

Timing Control For script based Animations

描画のアニメーションは、setInterval, setTimeoutを使っていたが
requestAnimationFrameを使うと
ブラウザの負荷状況によって最も適したタイミングでアニメーションを開始し、
バックグラウンドにある場合は、速度が低くなるため、メモリ消費を抑えることができる
アニメーションを終了したい場合は requestCanselAnimationFrameを呼び出す


https://liginc.co.jp/web/js/130758

requestAnimationFrameの特徴
  • ブラウザの描画更新単位と同じ単位で呼び出される
  • 次の再描画が行われる前に次のアニメーションをする関数を呼び出す
  • タブが非アクティブの時はFPSを落とす
setInteval、setTimeoutの特徴
  • ブラウザで準備ができていなくても必ず実行
  • タブが非アクティブの状態でも常に実行
------------------------------------------
loop();
function loop() {
    console.log('requestAnimationFrame直前');
    requestId = window.requestAnimationFrame(loop);
    var currentTime = new Date().getTime();
    var now = window.performance.now();
    console.log('now() :' + (now));
    //経過時刻を取得
    var status = currentTime - startTime // 描画開始時刻から経過時刻を引く
    // 経過時間が2000ミリ秒すぎたらアニメーション終了
    if (status > 2000) {
        console.log('END!! ');
        console.log('requestId : ' + requestId);
        // loopを終了させる
        window.cancelAnimationFrame(requestId);
    }
    console.log(status);
}
---------------------------------------------------------------
canvasとrequestAnimationFrameを使いサンプル作成
---------------------------------------------------------------

        <div id="info"></div>
        <canvas id="sample" width="500" height="500"></canvas>
        <button id="move">move</button>
        <button id="stop">stop</button>      
        <script type="text/javascript">
            var startTime = new Date().getTime();
            console.log(startTime);
            (function () {
                var sample = document.getElementById('sample');
                sample.width = 500;
                sample.height = 500;
                var ctx = sample.getContext('2d');
                var sizeX = 50;
                var sizeY = 50;
                var _amount = 5;
                var _x = 0;
                var _y = 0;
                var _w = sample.width;
                var _h = sample.height;
                var requestId;

                render(_x, _y);
                document.getElementById('move').addEventListener('click', loop);
                document.getElementById('stop').addEventListener('click', stop);

                var dirX = _amount;
                var dirY = _amount * 5;

                function render(_x, _y) {
                    ctx.clearRect(0, 0, _w, _h);
                    ctx.beginPath();
                    ctx.fillRect(_x, _y, sizeX, sizeY);
                    ctx.closePath();
                }
                var start;
                function loop() {

                    if (!start) {
                        start = window.performance.now();
                    }

                    requestId = window.requestAnimationFrame(loop);

                    if (_x > _w || _x < 0) {
                        dirX *= -1;
                        _y += dirY;
                    }

                    if (_y > _h || _y < 0) {
                        dirY *= -1;
                    }
                    _x += dirX;

                    render(_x, _y);
                }

                function stop() {
                    var end = window.performance.now();
                    document.getElementById('info').innerHTML = floatFormat((end - start) / 1000, 2);
                    start = null;
                    window.cancelAnimationFrame(requestId);
                }
               
                // 小数点n位までを残す関数
                // number=対象の数値
                // n=残したい小数点以下の桁数
                function floatFormat( number, n ) {
                        var _pow = Math.pow( 10 , n ) ;
                        return Math.round( number * _pow ) / _pow ;
                }

            })();
        </script>
--------------------------------------------------------------


performance

http://ohgyun.com/335
http://html5.ohtsu.org/html5advent2011/
http://d.hatena.ne.jp/jovi0608/20111209/1323428049
http://qiita.com/mamo/items/ff336b5cc0a1a95e03a7

1. performance.timing 




여기서는 performance.timing 객체와 관련된 PerformanceTiming 인터페이스의 속성에 대해 정리해보려고 한다.
(스펙에 기재된 내용을 이해하기 쉽게 번역한 정리본이다. 원문 링크


navigationStart     
    이전 페이지에서 도큐먼트가 unload를 시작한 시점('prompt to unload a document'를 끝낸 시점)(1).
    이전 페이지가 없을 경우 fetchStart와 동일하다.

unloadEventStart
    
이전 페이지와 현재 페이지가 동일 근원(same origin)일 때, unload 이벤트를 시작하는 시점.
    이전 페이지가 없거나 동일 근원이 아닐 경우 0.
unloadEventEnd     unload 이벤트가 끝나는 시점.

redirectStart  
    HTTP 리다이렉트나 동일 근원 상의 리다이렉트가 수행되는 경우, 그 시작 시점을 의미하며 fetchStart와 동일하다.
    없을 경우 0.
redirectEnd  
    위와 같은 조건에서 마지막으로 리다이렉트된 응답의 첫 번째 바이트를 받은 시점. 없을 경우 0.

fetchStart  
    HTTP 요청으로 새로운 리소르를 불러오기 시작하는 시점.
    애플리케이션 캐시가 있을 경우 캐시 존재 여부를 체크하기 시작하는 시점.
    캐시가 없는 경우, 리소스를 받아오기 시작하는 시점.

domainLookupStart     
    
도메인에 해당하는 IP를 검색(DNS Lookup)하기 시작하는 시점.
    이미 연결되어 있거나(2), 캐시되어 있거나, 로컬 리소스일 경우, fetchStart와 동일한 값.
domainLookupEnd     
    
DNS Lookup이 종료되는 시점. 조건에 해당하지 않을 경우, fetchStart와 동일.


connectStart     
    
브라우저(3)가 문서를 받기 위해 서버와 연결을 시도하는 시점.
    이미 연결되어 있거나, 캐시되어 있거나, 로컬 리소스일 경우, domainLookupEnd와 동일한 값.
connectEnd     
    
브라우저가 서버와 연결을 맺은 시점.
    조건에 해당하지 않을 경우, domainLookupEnd와 동일.

requestStart     
    
브라우저가 서버, 애플리케이션 캐시 또는 로컬 리소스에 현재 문서에 대한 요청을 시작하는 시점(4).

responseStart     
    
브라우저가 서버로부터 응답 데이터의 첫 번째 바이트를 받은 시점.
responseEnd     
    
브라우저가 응답 데이터의 마지막 바이트를 받은 시점 또는 연결이 끊기 시점 중 빠른 값.

domLoading     
    브
라우저가 문서를 만들기 시작하는 시점. 문서 준비 상태(5)가 "loading"이 되었을 때. (6)
domInteractive     
    브라우저가 문서 준비 상태를 "interactive"로 변경하는 시점.
domContentLoadedEventStart     
    문서에서 DOMContentLoaded 이벤트가 호출되는 시점.
domComplete     
    브라우저가 문서 준비 상태를 "complete"로 변경하는 시점.


loadEventStart     
    
문서의 "load" 이벤트가 발생하는 시점. 이벤트가 호출되지 않았다면 0이다.
loadEventEnd     
    문서의 load 이벤트가 완료된 시점.

----------------------------------------------------------------------------------------------------------
(1) prompt to unload a document : http://dev.w3.org/html5/spec/history.html#prompt-to-unload-a-document
(2) persistent connection : '영구적인 접속' 또는 '지속적인 접속'이지만 문맥상 '이미 연결되어 있다'고이라고 번역
(3) User Agent 이지만 여기서는 이해를 위해 브라우저라고 번역
(4) requestEnd는 스펙에 포함되어 있지 않다. request 완료 시점이 네트워크 완료 시점과 정확히 일치하지 않는 경우가 있고,  몇몇 User Agent는 HTTP Layer 캡슐화 때문에 request 종료 시점을 파악하는데 비용이 들기 때문이다.
(5) 문서 준비 상태(current document readiness). 문서 상태가 변경될 때마다 readystatechange 이벤트가 호출되며, document.readyState 속성에서 확인할 수 있다.
     "loading": 문서를 생성하고 파싱하는 단계.

     "interactive": 파싱이 종료되고, 남은 리소스를 가져오는 단계.
     "complete": 로드가 완료된 상태. 

2.performance.navigation.type
アクセスの状態を表す(どうやってアクセスしたかがわかる)

0  urlを打ち込んだかクリックでアクセスした場合
1  リロードでアクセス
2 history.back(), history.forward()でアクセス
3. 将来のための予約


3.hight solution Time
performance.now()メソッドを使い、ページを開いた時からnow()メソッドを実行するまでの時刻を
DOMHighResTimeStamp 型で取得できる
(ミリ秒の整数値.浮動小数点は1/1000 ex.2025.6950000000002)

DOMHighResTimeStamp 型
従来、Web アプリケーションの時間を計測しようとする場合は、DOMTimeStamp を返す Date.now() のようなものを使っていました。DOMTimeStamp は値としてミリ秒の整数値を返します。高精度計時に必要とされる、より高い精度を提供するために、DOMHighResTimeStamp と呼ばれる新しい型が導入されました。この型は浮動小数点の値であり、ミリ秒で時間を返します。しかし、その値は浮動小数点なので、ミリ秒より小さい値を表現できるため、1/1000 ミリ秒の精度を生成できます。



2017년 1월 2일 월요일

HTTPリクエスト、レスポンス色々


ウェブブラウザは、HTTPリクエストメッセージを作成
・URLを解析し、ウェブサーバとファイル名(URI)が判断できたら、それを元でHTTPリクエストメッセージを作成
http: + // + www.google.co.jp  +  /  + dir  + / + file.html

http:  データソースにアクセスする構造(プロトコル)を記述
//    後ろの続きはサーバ名を表す
www.google.co.jp ウェブサーバ名
/dir/file.html データ元のパス名 ※ 最初の/:ルートディレクトリを意味

httpプロ処を使用する(httpサーバ)www.google.co.jpというウェブサーバから/dir/file.htmlのパスのファイルにアクセスするという意味(ファイルをリクエスト)

・HTTPプロトコルは、クライアントとサーバーが通信するメッセージの内容、順番を定めた規約
・クライアント --> サーバにリクエストメッセージを送信する。リクエストのメッセージには
「何を」、「どうするか」が含まれる。
「何を」 : リクエストするファイル名 または CGI名などが該当(URI --> ex. /dir/file.html)
「どうするか」:メソッド(代表的なメソッドは、GET, POST)
GET --> URIで指定したリソースをリクエスト
POST --> サーバ側にデータを送信

・サーバ --> クライアントにレスポンスメッセージを送信する。
レスポンスのメッセージには、状態コードとデータが含まれる

・サーバからレスポンスメッセージを表示するとページが文章だけだと表示することでいいだが、
写真とか図などを含む場合は、イメージ以外のテキストのみ表示してから、
もう一度、ウェブサーバにイメージファイルをURIに指定し、リクエストメッセージを送信
リクエストメッセージを記載するURIは一つで決まっているため、複数のイメージファイルが
ある場合、イメージ数分のリクエストが必要になる

・ウェブサーバは、HTTPリクエスト作成はできるが、ウェブサーバーにメッセージを送信するのは、
できない

・ウェブサーバは(アプリケーション)、ソケットライブラリにDNSサーバからウェブサーバのIPアドレスを参照するようにリクエスト

・OS(TCP/IP)にデータ送信をリクエスト

・TCP/IP(softwear)はデータ送信・受信を制御(通信の準備作業など)
 ※インターネットではデータを送信時に細かく分けた形(パケット)で転送するが
   そのパケットの送信・受信を制御するのがIPの主な役割

・LANカードが実際の送信、受信処理を行う

Geolocation

http://mikaduki.info/api/1823/
http://help.opera.com/Windows/10.61/ja/geolocation.html#details

Geolocation機能は、ユーザが現在地球上のどの位置にいるかを特定する機能
Geolocationは、ユーザの位置情報を教えてくれるAPI


Geolocation仕組み

無線LAN、携帯電話基地局、GPS、IPアドレスなどから送信されたデータを取得


Geolocationオブジェクト取得
navigator.geolocaion --> Andoroid端末では対応してない場合がるので、googleのWEB拡張設定を使って値を取得

◆Andoroid用option設定は、

・GPSを使用して正確さを増やす
・データ取得を待つミリ秒
・キャッシュを保持するミリ秒

var option = {enableHighAcuuracy:true, timeout:10000, maximumAge:0};

◆データ取得については、
現在の位置を一度きりのデータを取得する方法と
一定間隔おきにデータを取得する方法がある

・geolocation.getCurrentPosition($成功時コールバック関数、$失敗時コールバック関数、$オプション)
・geolocation.watchPosition($成功時コールバック関数、$失敗時コールバック関数、$オプション)

※clearWatch --> watchPositionでの定期的な取得をクリア

◆positionのcoordsプロパティ
緯度
経度
高度
方向
スピード
緯度経度の精度
高度の精度

・position.coords.latitude
position.coords.longitude
position.coords.altitude
position.coords.heading
position.coords.speed
position.coords.accuracy
position.coords.altitudeAccuracy

◆errorプロパティ
geolocation情報取得に失敗した場合のエラーコード、メッセージ
・error.code
・error.message


------------------------------------------------------------------

        <div id="latitude"></div>
        <div id="longitude"></div>
        <div id="altitude"></div>
        <div id="speed"></div>
        <div id="accuracy"></div>
        <div id="heading"></div>      
        <div id="altitudeAccuracy"></div>        
        <script type="text/javascript">
            (function (){
                debugger;
                var geo = window.navigator.geolocation;
                // geolocationオブジェクトが使えない場合、
                // googleのWEB拡張設定を使って値を取得
                if(geo === undefined){
                    geo = google.gears.factory.create('beta.geolocation');
                }
             
                // Android用option設定
                // GPSを利用して制度を増やすか、データの取得を待つミリ秒、キャッシュ保持時間(ミリ秒)、
                var option = {enableHighAccuracy:true, timeout:10000, maximumAge:0};
             
                // ユーザの位置を一度きりで取得
                geo.getCurrentPosition(success, fail, option);
             
                // 一定間隔おきに位置情報データ取得
                geo.watchPosition(success, fail, option);
             
                function success(position){
                    alert('geolocation情報取得成功');
                    $('latitude').innerHTML = "緯度:" + position.coords.latitude;
                    $('longitude').innerHTML = "経度:" + position.coords.longitude;
                    $('heading').innerHTML = "方向:" + position.coords.heading;
                    $('altitude').innerHTML = "高度:" + position.coords.altitude;
                    $('speed').innerHTML = "速度:" + position.coords.speed;
                    $('accuracy').innerHTML = "緯度緯度の精度:" + position.coords.accuracy;
                    $('altitudeAccuracy').innerHTML = "高度の精度:" + position.coords.altitudeAccuracy;                  
                }
             
                function $(id){
                    return document.getElementById(id);
                }
             
                function fail(err){
                    alert('geolocation情報取得失敗 ' + err.code + " : " + err.message);
                }
             
            })();
         

        </script>


2017년 1월 1일 일요일

file






     
        <input type="file" multiple name="file[]" id="file">
        <div id="info"></div>
        <div id="result"></div>  

 <script type="text/javascript">
            (function () {
                if (window.file) {
                    debugger;
                    var fileEl = document.getElementById('file');
                    fileEl.addEventListener("change", display);

                    function display() {
                        var files = fileEl.files;
                        debugger
                        console.log(typeof filesArray);
                        var info = "";
                        var result = "";
                        var fileReader;

                        for (var idx = 0; idx < files.length; idx++) {
                            debugger
                            var file = files[idx];
                            var fileName = file.name;
                            var fileSize = file.size;
                            var fileType = file.type;
                            var fileUpdate = file.lastModifiedDate;
                            var fileUrn = file.urn;
                            info += '--------------------------------------------------------';
                            info += '<li>' + 'fileName: ' + fileName + '</li>';
                            info += '--------------------------------------------------------';
                            info += '<li>' + 'fileSize: ' + fileSize + '</li>';
                            info += '<li>' + 'fileType ' + fileType + '</li>';
                            info += '<li>' + 'fileUpdate ' + fileUpdate + '</li>';
                            info += '<li>' + 'fileUrn ' + fileUrn + '</li>';
                           
                            fileReader = new FileReader();
                            fileReader.readAsText(file, "utf-8");
                            fileReader.addEventListener('load', function () {
                                debugger;
                                result += document.getElementById('result').innerHTML;
                                result += '-------------------------------------------------------';
                                result += '<li>' + "内容:" + fileReader.result + '</li>';
                                document.getElementById('result').innerHTML = result;
                            });

                            fileReader.addEventListener('error', error);
                            function error() {
                                return function () {
                                    alert(event.target.error.code);
                                };
                            }
                        }

                        document.getElementById('info').innerHTML = info;
                    }

                } else {
                    alert('fileをサポートしません');
                }

            })();
        </script>

worker


http://m.mkexdev.net/52

http://d.hatena.ne.jp/ushiboy/20101021/1287667594

javascriptはもともとシングルスレッドといい、時間がかかる処理の場合
その間、他のUI作業をスクリプト作業が完了するまで待機しないといけなかったが
Webworkerを使えば、複数のプログラムを平行して実行できる(マルチスレッド)

WebworkerはjsコードをUIスレッドと別途でバックグラウンドで実行できるため、
worker処理が行われる間ウェブページが固まることなく、UI作業を行うことができる

ワーカをサポートしないブラウザかを確認する必要がある
if(!!window.Worker){
      alert("ブラウザがワーカをサポートしません")
}

terminate()  ワーカを終了
onmessage メッセージ受信イベント
postMessage メッセージ送信イベント
onerror         エラー発生時感知イベント
 errプロパティ
 ・message
 ・filename
 ・lineno エラーが発生した時、エラー発生行を知ることができる
-----------------------------------------------
worker.html
-----------------------------------------------
...
<body>
<button onclick="callWorker()">callWorker</button>
<button onclick="stopWorker()">stopWorker</button>
<br>
<input type="text" id="toworker">
<div id="result"></div>
<script type="text/javascript">
var worker;
function callWorker() {
if (!!window.Worker) {

// workerがすでに存在した場合終了
if (worker){
worker.terminate();
}

// worker処理を定義したjsをパラメータでworker生成
worker = new Worker("./worker.js");

// workerからメッセージ受信
worker.onmessage = function(event) {
document.getElementById('result').innerHTML = event.data;
};

// ワーカーにパラメータ送信
worker.postMessage(document.getElementById('toworker').value);
} else {
alert("ブラウザがワーカをサポートしません")
}
}

function stopWorker() {
if (worker) {
worker.terminate();
}
}
</script>
</body>


-----------------------------------------------
worker.js
-----------------------------------------------
var total = 0;
onmessage = function(event){
for(var val=0; val < 50000000000000000000; val++){
total = total + val;

// workerから
postMessage(event.data + ' 中間結果:' + total);

}

postMessage(event.data + '結果' + total);
}

Storage

Storageオブジェクトには、LocalStorageとSessionStorageの2種類がある。

1.SessinStorage
  ブラウザを閉じるとデータが消えてしまう。

2.LocalStorage
 ・ブラウザを閉じてもデータは残る
 ・ブラウザにKey-Value型で保存される。
 ・デベロッパツールのResourcesタグのLocalStorage項目で確認できる
 ・重要な情報を保存するのは望ましくない(個人情報。。)
 ・メソッド
 getItem(key)
  setItem(key, 値)
  removeItem(key)
  clear() LocalStorageにあるデータをすべて削除

 ・キー:値  --> 1:n 可能
  キー一つに対して複数の値を保存できる
  複数の値は、JSONというデータのフォーマットで設定する
  LocalStorageに設定:JSON.stringify({'key1':value, "key2:value"}) --> Objectを文字列
    LocalStorageから取得:JSON.parse("{'key1:value,''key2:value'}");--> 文字列をObject







        <script type="text/javascript">
            var keyEl = $("key");
            var valEl = $('val');
            $('save').addEventListener('click', save(keyEl,valEl));
            $('display').addEventListener('click', display(keyEl));
            $('remove').addEventListener('click', remove(keyEl));
            $('clear').addEventListener('click', clear());
            function save(keyEl,valEl){
                return function (){                  
                    var arrayOfValue = valEl.value.split(",");
                    var objOfValue = {};
                    arrayOfValue.forEach(function (item, index){
                        debugger;
                        objOfValue[index] = item;
                    });
                 
                    window.localStorage.setItem(keyEl.value, JSON.stringify(objOfValue));
                    window.sessionStorage.setItem(keyEl.value, JSON.stringify(objOfValue));
                };
            }
         
            function display(){
                return function (){ // {key1:{0:val1,1:val2}, key2:{0:val1,1:val2}} key1 : val1,val2
                    var storage = window.localStorage;
                    var print = "";
                    for(keyOfStorage in storage){
                        var arrayValue = storage[keyOfStorage];
                        var objVal = JSON.parse(arrayValue);                      
                        var displayVal = "";
                        var keys = Object.keys(objVal); // {0:val1,1:val2} --> [0,1]
                        for(var idx = 0; idx < keys.length; idx++){
                            displayVal = displayVal + objVal[idx];
                            if(idx < keys.length -1){
                                displayVal = displayVal + ',';
                            }
                        }
                        var line = keyOfStorage + ":" + displayVal + '<br>';
                        var print = print + line;
                    }

                  $('content').innerHTML = print;
                };
            }
         
            function remove(keyEl){
                return function(){
                  window.localStorage.removeItem(keyEl.value);
                };
            }
         
            function clear(){
                return function(){
                  window.localStorage.clear();
                };
            }
         
            function $(id){
                return document.getElementById(id);
            }
        </script>


    


page Visibility


・下記のイベントが発生した場合、visibilitychangeイベント発生
ページが最小化
ページ遷移
ページが隠れる
※window クローズの場合は、発生しない

・visibilitychangeイベントが発生したら、document.hiddenの状態はtrue

document.hidden --> true

Audio

1.audio 再生時間が変わった時に発生するイベント
timeUpdate --> chromeの場合、0.25秒ごとイベント発生


2.audioメソッド

audio.play()
audio.pause()
audio.load()          



3.audioプロパティ

audio.duration
audio.currentTime
audio.volume           ---> 0以下、1以上の場合エラー
audio.playbackRate
audio.paused
audio.ended
audio.error
audio.readyState
audio.networkState


-----------------------------------------------------------

audioメソッド

audio.play()     再生
audio.pause()   停止
audio.load()     再ロード



audioプロパティ

audio.duration      メディアの長さ
audio.currentTime  再生位置
audio.volume         音量(0 ~ 1 --> +0.1, -0.1)
audio.playbackRate スピード(+0.5, -0,5)
audio.paused          停止状態判定
audio.ended     終了状態判定
audio.error            エラーの状態(何もなければnull)
audio.readyState  メディアの準備状態 
audio.networkState ネットワーク状態


play開始前
-----------------------
readState :null  
readyState :0             何も準備できてない
networkState :3         リソースがみつからない


play後(play後停止、終了しても状態は同じ)
-------------------------
error :null
readyState :4          HAVE_ENOUGH_DATA 充分に完了
networkState :1   NETWORK_IDLE 利用停止状態
                            最初は 2 (データダウンロード中)--> 1






        <button id="play">play</button>
        <button id="pause">pause</button>
        <button id="load">load</button>
        <button id="end">終了</button>        
        <button id="currenTime">currentTime最初から</button>
        <button id="volumeDown">volume-</button>
        <button id="volumeUp">volume+</button>      
        <button id="playbackRateUp">playbackRate+</button>
        <button id="playbackRateDown">playbackRate-</button>      
        <div id="info"></div>
        <div id="infoVolume"></div>
        <div id="infoCurrentTime"></div>      
        <div id="infoDuration"></div>
        <div id="infoPlaybackRate"></div>
        <div id="infoError">エラーなし</div>    
        <div id="infoReadyState">準備状態</div>
        <div id="infoNetworkState">ネットワーク状態</div>  


        <script type="text/javascript">
            var audio = new Audio();
            audio.src = "http://www.noiseaddicts.com/samples_1w72b820/2558.mp3";

            // 再生時間が変わった時にtimeupdateイベント発生:chromeの場合0.25秒ごとに呼ばれる
            audio.addEventListener("timeupdate", displayInfo);

            $('play').addEventListener("click", play);
            $('pause').addEventListener("click", pause);
            $('currenTime').addEventListener("click", currentTime(0));
            $('volumeUp').addEventListener("click", volume(true));
            $('volumeDown').addEventListener("click", volume(false));
            $('playbackRateUp').addEventListener("click", playbackRate(true));
            $('playbackRateDown').addEventListener("click", playbackRate(false));
            $('load').addEventListener("click", load);
            $('end').addEventListener("click", end);
            $('infoError').innerHTML = "readState :" + audio.error;
            $('infoReadyState').innerHTML = "readyState :" + audio.readyState;
            $('infoNetworkState').innerHTML = "networkState :" + audio.networkState;

            function displayInfo() {
                $('infoVolume').innerHTML = "infoVolume :" + audio.volume;
                $('infoCurrentTime').innerHTML = "infoCurrentTime :" + audio.currentTime;
                $('infoDuration').innerHTML = "infoDurationvolume :" + audio.duration;
                $('infoPlaybackRate').innerHTML = "infoPlaybackRate :" + audio.playbackRate;
                $('infoError').innerHTML = "error :" + audio.error;
                $('infoReadyState').innerHTML = "readyState :" + audio.readyState;
                $('infoNetworkState').innerHTML = "networkState :" + audio.networkState;

                // 終了状態の場合
                if (audio.ended) {
                    return $('info').innerHTML = '終了';
                }
                // 停止状態の場合
                else if (audio.paused) {
                    return $('info').innerHTML = '停止';
                } else {
                    return $('info').innerHTML = '';
                }
            }

            function play() {
                audio.play();
            }

            function pause() {
                audio.pause();
            }

            function load() {
                $('info').innerHTML = "再読み込み!(audio.load())";
                audio.load();
            }

            function end() {
                debugger;
                audio.currentTime = audio.duration;
            }

            function volume(upFlg) {
                return function () {
                    if ((upFlg && audio.volume === 1) || (!upFlg && audio.volume === 0)) {
                        return;
                    }

                    if (upFlg) {
                        audio.volume += 0.1;
                    } else {
                        audio.volume -= 0.1;
                    }
                };
            }

            function currentTime(time) {
                return function () {
                    audio.currentTime = time;
                };
            }

            function playbackRate(upFlg) {
                return function () {
                    if (upFlg) {
                        audio.playbackRate += 0.5;
                    } else {
                        audio.playbackRate -= 0.5;
                    }
                };
            }

            function $(id) {
                return document.getElementById(id);
            }

        </script>