2011/08/04

SVGでアニメーションさせる

SVGでアニメーションをさせるには、SVGタグ内でアニメーションを指定します。






<svg height="200" width="400">
<polygon fill="#FFFF00" points="153,184 100.271,158.186 49.113,186.988 57.37,128.863
    14.168,89.109 72,79 96.458,25.628 123.943,77.506 182.261,84.274 141.416,126.445 " stroke-miterlimit="10" stroke="#000000">
 <animatetransform attributename="transform" begin="0s" dur="3s" from="360 50 50" repeatcount="indefinite" to="0 50 50" type="rotate">
 </animatetransform>
 <animatemotion begin="0s" dur="5s" path="M 0 100 L 400 100" repeatcount="indefinite" rotate="auto"></animatemotion>
</polygon>
</svg>


2011/08/03

データをローカルに保存する

データをローカルに保存するには、Web Storageを使います。
従来はクッキーを使って最大4KBまでは保存できましたが、HTML5はWeb Storageを使って5MB程度の保存ができるようになりました。
AmazonやTwitter等のサイトは既にWeb Storageを使ったデータの保存が活用されているそうです。

Web Storageには、sessionStorageとlocalStorageの2種類があります。

sessionStorageはその名の通り、セッション毎に使用されるストレージです。
ウィンドウやタブ毎に保存場所が異なり、sessionStorageに保存されたデータは他のウィンドウやタブからは参照することができません。また、セッション終了時(ウィンドウやタブを閉じる)には同時にsessionStorageに保存されたデータも削除されます。

localStorageはプロトコル・ドメイン・ポート番号が同じであれば全てのセッションでデータが共有され、セッションが終了してもデータは永続されます。


Web Storageのメソッド・プロパティ一覧
メソッド・プロパティ内容
length保存データの個数
key(index)指定インデックスに格納されているキー
getItem(key)指定キーに格納されている値
setItem(key, value)指定キーに指定値を格納
removeItem(key)指定キーと値の組を削除
clear()全データを削除


Web Storageにはイベントはstorageイベント1つしかありません。
以下に使用上のプロパティ値を載せますが、本項執筆時点ではまだ未実装の物が多いようです。


storageイベントで渡されるオブジェクト
プロパティ内容
keyイベント発生対象のキー
oldValueキーに対する旧いvalue
newValueキーに対する新しいvalue
urlイベントが発生したURL
storageArea変更データのストレージへの参照


以下はsessionStorageの例です。
KeyとValueに適当な値を入力して「保存」ボタンを押すとsessionStorageに保存されていく様子が分かります。また、一旦ウィンドウを閉じた後で再度開いても、データが残っていないことが分かると思います。


Key : Value:





Key : <input type="text" name="key" id="key" size="20">
  Value:<input type="text" name="value" id="value" size="20">
<input type="button" value="保存" onClick="save()">
<input type="button" value="全クリア" onClick="allClear()">
<div id="list"></div>
<script type="text/javascript">
window.onload = function() {
    list();
}
var storage = window.sessionStorage;
function save() {
    var keyValue = document.getElementById("key").value;
    var valValue = document.getElementById("value").value;

    if ( keyValue && valValue ) {
        storage.setItem(keyValue, valValue);
    }
    keyValue = "";
    valValue = "";
    list();
}
function list() {
    var list = "";
    for ( var i = 0 ; i < storage.length ; i++ ) {
        var _key = storage.key(i);
        list += "sessionStorage[" + i + "] = Key:" + _key + "  Value:" + storage.getItem(_key) + "      <a href=\"#\" onClick=\"remove(" + i + "); return false;\">削除</a><br />";
    }
    document.getElementById("list").innerHTML = list;
}
function remove(index) {
    var _key = storage.key(index);
    storage.removeItem(_key);
    list();
}
function allClear() {
    storage.clear();
    list();
}
</script>


以下はlocalStorageを使った例です。
sessionStorageをlocalStorageに変更しただけで同じです。
sessionStorageとlocalStorageは同じメソッド、プロパティが使えます。
また、localStorageはセッションが終了しても残るため、前のセッションで保存したものをページのロード時に表示させるためにonloadイベントを追加しています。




Key : Value:





Key : <input type="text" name="key" id="key" size="20">
  Value:<input type="text" name="value" id="value" size="20">
<input type="button" value="保存" onClick="save()">
<input type="button" value="全クリア" onClick="allClear()">
<div id="list"></div>
<script type="text/javascript">
window.onload = function() {
    list();
}
var storage = window.localStorage;
function save() {
    var keyValue = document.getElementById("key").value;
    var valValue = document.getElementById("value").value;

    if ( keyValue && valValue ) {
        storage.setItem(keyValue, valValue);
    }
    keyValue = "";
    valValue = "";
    list();
}
function list() {
    var list = "";
    for ( var i = 0 ; i < storage.length ; i++ ) {
        var _key = storage.key(i);
        list += "sessionStorage[" + i + "] = Key:" + _key + "  Value:" + storage.getItem(_key) + "      <a href=\"#\" onClick=\"remove(" + i + "); return false;\">削除</a><br />";
    }
    document.getElementById("list").innerHTML = list;
}
function remove(index) {
    var _key = storage.key(index);
    storage.removeItem(_key);
    list();
}
function allClear() {
    storage.clear();
    list();
}
</script>



2011/08/02

オフラインでも見られるようにする

Webサーバーにアクセスした時に必要なファイルをローカルに保存しておけば、ネットに接続していない時でも接続しているのと同じようにサービスを受けることができるようになります。
このHTML5の仕組みを「アプリケーションキャッシュ」と言います。

キャッシュするファイルを指定するためにhtml要素に「manifest=”ファイル名.manifest”」属性を付けます。
そして、Webサーバー側の設定ファイルである、.htaccessファイルに以下の1行を追加します。


AddType text/cache-manifest              manifest


これで、manifest拡張子のファイルはMIME/TYPE「text/cache-manifest」でクライアントに送信されるようになります。マニフェストファイルは「text/cache-manifest」で送信しないとクライアント側で認識されません。

manifestファイルの中身は以下の様にします。


CACHE MANIFEST
#  #はコメントです。
# 下のCACHEから、キャッシュするファイル名を指定します。
# 何もラベルが無い場合は、このCACHEを指定したのと同じになります。
CACHE
index.html

# 下のNETWORKからはキャッシュしないファイル名を指定します。
NETWORK
・・・・.cgi
http://maps.google.com/

# ここに*(アスタリスク)を置くと、全てのファイルという
# 意味になります。この場合、全てのファイルをキャッシュ
# しない設定になります。

# 下のFALLBACKから、キャッシュしていないリソースにアクセスした
# 時に表示する代替リソースを指定します。
FALLBACK
# abc.htmlがキャッシュされていない場合、error.htmlを表示します。
abc.html  error.html




上のようにマニフェストを設定すると、例えば「index.html」ファイルはクライアントのローカルにキャッシュされるようになります。

例えばここで、サーバー側でindex.htmlファイルが更新された場合、index.htmlファイルはキャッシュ指定されているのでクライアント側には旧いindex.htmlファイルが表示され続けることになります。

このような場合は、サーバー側でindex.htmlファイルの更新と同時にマニフェストファイルの更新も行えば、キャッシュ内のファイルも更新されるようになります。
マニフェストファイルの日付が更新されていると、キャッシュされたファイルも新しい物に更新されます。

また、javascriptから明示的にキャッシュを更新したい場合、「window.applicationCache.update()」を呼べば、マニフェストファイルを再ダウンロードしてキャッシュも更新してくれるようになります。


FirefoxでURL入力欄に「about:cache」と指定すれば、キャッシュ情報が表示されます。
ChromeでURL入力欄に「chrome://appcache-internals/」と指定すれば、キャッシュ情報が表示されます。

経度・緯度から住所を取得する

Google Map APIを利用して、経度、緯度情報から住所を取得するには、Geocoderオブジェクトを使用します。








<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0, maximum-scale=3.0" />
<div id="map" style="border:1px solid #0000FF; width:400px; height:300px;"></div>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true"></script>
<script type="text/javascript">
var map, infoWindow;
if (!navigator.geolocation) {
    var map = document.getElementById("map");
    map.innerHTML = "このブラウザは位置情報をサポートしていません。";
} else {
    navigator.geolocation.getCurrentPosition(showMap2, showError2,
                {
                    enableHighAccuracy:true,
                    maximumAge:0,
                    timeout:10000
                });
}
function showMap2(position) {
    var latitude = position.coords.latitude;
    var longitude = position.coords.longitude;

    // 取得して現在位置をGoogle Maps APIに渡す
    var mapCenter = new google.maps.LatLng(latitude, longitude);
    var mapDiv = document.getElementById("map");
    var op = {
        zoom:16,            // 表示倍率を指定
        center:mapCenter,    // 中央位置を指定
        mapTypeId:google.maps.MapTypeId.ROADMAP,
        scaleControl:true    // 倍率変更を指定
    };
    // 地図を表示
    map = new google.maps.Map(mapDiv, op);

    // マーカーを表示
    var marker = new google.maps.Marker({
        position:mapCenter,
        map:map,
        title:"現在地"});
    map.setCenter(mapCenter);

    var geocoder = new google.maps.Geocoder();
    geocoder.geocode({'latLng': mapCenter}, getGoogleMapAddress);
    infoWindow = new google.maps.InfoWindow();
}
function showError2(error) {
    var l = document.getElementById("map");
    switch(error.code) {
        case error.UNKNOWN_ERROR:
            l.innerHTML = "UNKNOWN_ERROR:" + error.message;
            break;
        case error.PERMISSION_DENIED:
            l.innerHTML = "PERMISSION_DENIED:";
            break;
        case error.POSITION_UNAVAILABLE:
            l.innerHTML = "POSITION_UNAVAILABLE:";
            break;
        case error.TIMEOUT:
            l.innerHTML = "TIMEOUT:";
            break;
    }
}
function getGoogleMapAddress(results, status){
    var address;
    if (status == google.maps.GeocoderStatus.OK) {
        address = results[0].formatted_address;
        infoWindow.setPosition(results[0].geometry.location);
        infoWindow.setContent(address);
        infoWindow.open(map);
    } else {
    m = document.getElementById("map");
    m.innerHTML = "エラーが発生しました。" + status;
    }
}
</script>


Google Mapに現在位置を表示する

Google Mapに位置情報を表示するには、「現在位置を取得する」と同様に現在位置を取得し、その後Google Map APIに位置を指定して表示させます。








<div id="map" style="border: 1px solid #0000FF; width:400px; height:300px;"></div>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true"></script>
<script type="text/javascript">
if (!navigator.geolocation) {
    var map = document.getElementById("map");
    map.innerHTML = "このブラウザは位置情報をサポートしていません。";
} else {
    navigator.geolocation.getCurrentPosition(showMap, showError,
                {
                    enableHighAccuracy:true,
                    maximumAge:0,
                    timeout:10000
                });
}
function showMap(position) {
    var lat = position.coords.latitude;
    var long = position.coords.longitude;

    // 取得して現在位置をGoogle Maps APIに渡す
    var mapCenter = new google.maps.LatLng(lat, long);
    var mapDiv = document.getElementById("map");
    var options = {
        zoom:16,            // 表示倍率を指定
        center:mapCenter,    // 中央位置を指定
        mapTypeId:google.maps.MapTypeId.ROADMAP,
        scaleControl:true    // 倍率変更を指定
    };
    // 地図を表示
    var map = new google.maps.Map(mapDiv, options);

    // マーカーを表示
    var marker = new google.maps.Marker({
        position:mapCenter,
        map:map,
        title:"現在地"});
    map.setCenter(mapCenter);
}
function showError(error) {
    var l = document.getElementById("map");
    switch(error.code) {
        case error.UNKNOWN_ERROR:
            l.innerHTML = "UNKNOWN_ERROR:" + error.message;
            break;
        case error.PERMISSION_DENIED:
            l.innerHTML = "PERMISSION_DENIED:";
            break;
        case error.POSITION_UNAVAILABLE:
            l.innerHTML = "POSITION_UNAVAILABLE:";
            break;
        case error.TIMEOUT:
            l.innerHTML = "TIMEOUT:";
            break;
    }
}
</script>


定期的に位置情報を取得する

定期的に位置情報を取得するには、Geolocation APIのwatchPositionメソッドを使用します。

watchPosition(
位置情報取得成功Callback関数,
位置情報取得失敗Callback関数(省略可),
位置情報取得オプション(省略可)
);

watchPositionメソッドは、getCurrentPositionと基本的に同じですが、getCurrentPositionが1回だけ位置情報を通知するのに対し、watchPositionは位置が変更される度に通知されるというのが違います。また、戻り値に位置情報の継続取得を中止するためのIDが返却されるのも異なる点です。
各オブジェクト、プロパティ等の意味は「現在位置を取得する」を参照して下さい。








<div id="location2"></div>
<input type="button" onclick="stopWatchPosition();" value="ボタンを押すと位置情報の継続取得を中止します"></input>
<script language="javascript" type="text/javascript">
var stopID;
if (!navigator.geolocation) {
    var l = document.getElementById("location2");
    l.innerHTML = "このブラウザは位置情報をサポートしていません。";
} else {
    stopID = navigator.geolocation.watchPosition(locationGetSuccess2
        , locationGetError2,
        {
            enableHighAccuracy:true,
            maximumAge:0,
            timeout:1000
        });
}
function locationGetSuccess2(position) {
    var l = document.getElementById("location2");
    var now = new Date();
    l.innerHTML = "緯度:" + position.coords.latitude + "<br />"
            + "経度:" + position.coords.longitude + "<br />"
            + "Time:" + now.getHours() + ":" + now.getMinutes() + ":"
            +  now.getSeconds() + "<br />";
}
function locationGetError2(error) {
    var l = document.getElementById("location2");
    switch(error.code) {
        case error.UNKNOWN_ERROR:
            l.innerHTML = "UNKNOWN_ERROR:" + error.message;
            break;
        case error.PERMISSION_DENIED:
            l.innerHTML = "PERMISSION_DENIED:";
            break;
        case error.POSITION_UNAVAILABLE:
            l.innerHTML = "POSITION_UNAVAILABLE:";
            break;
        case error.TIMEOUT:
            l.innerHTML = "TIMEOUT:";
            break;
    }
}
function stopWatchPosition() {
    navigator.geolocation.clearWatch(stopID);
}
</script>


現在位置を取得する

現在位置を取得するには、Geolocation APIのgetCurrentPositionメソッドを使います。
お使いのPCやスマートフォンがGPSやWIFI等を利用した位置情報の取得に対応していれば、ブラウザで位置情報を使用することが可能になります。

navigator.geolocation.getCurrentPosition(位置情報取得成功Callback関数
, 位置情報取得失敗Callback関数(省略可)
, 位置情報取得オプション(省略可)
)

位置情報取得オプションには、以下のPositionOptionsオブジェクトを指定できます。


位置情報取得オプション指定PositionOptionsオブジェクト
プロパティ内容
enableHighAccuracy高い精度で位置情報を取得(true/false)
timeoutタイムアウト時間(ミリ秒)
maximumAge有効期間(ミリ秒)


位置情報取得成功Callback関数には、Positionオブジェクトが引数として渡され、Javascriptからそれらの情報にアクセスすることができます。


位置情報取得成功Callbackに渡されるPositionオブジェクト
プロパティ内容
latitude緯度
longitude経度
altitude高度
accuracy緯度、経度の誤差
altitudeAccuracy高度の誤差
heading方角
speed速度(m/秒)
timestampタイムスタンプ型の時刻情報


位置情報取得失敗Callback関数には、PositionErrorオブジェクトが引数として渡されます。

PositionErrorオブジェクト
プロパティ内容
codeエラーコード
messageエラーメッセージ

エラーコード
エラーコード意味
UNKNOWN_ERROR(0)不明なエラー
PERMISSION_DENIED(1)位置情報の利用が許可されていない
POSITION_UNAVAILABLE(2)位置情報が取得できない
TIMEOUT(3)位置情報取得タイムアウト


以下は、現在の位置情報を取得して表示する例です。







<div id="location"></div>
<script type="text/javascript">
if (!navigator.geolocation){
    window.alert("このブラウザはGeolocation APIを利用できません");
}else{
    navigator.geolocation.getCurrentPosition(
                    getLocationSuccessCallback,
                    getLocationErrorCallback,
            {
                enableHighAccuracy:true,
                maximumAge:0,
                timeout:10000
            }
                    );
}

function getLocationSuccessCallback(position){
    var l = document.getElementById("location")
    l.innerHTML = "緯度:" + position.coords.latitude + "<br />"
    +  "経度:" + position.coords.longitude + "<br />";
}
function getLocationErrorCallback(error){
    var message = "";
    switch(error.code)
    {
        case error.TIMEOUT:
            message = "タイムアウトが発生しました";
            break;
        case error.POSITION_UNAVAILABLE:
            message = "位置情報が利用できませんでした";
            break;
        case error.PERMISSION_DENIED:
            message = "Geolocation APIの利用権限がありません";
            break;
        case error.UNKNOWN_ERROR:
            message = "UNKNOWN_ERROR:" + error.message;
            break;
    }
    document.getElementById("location").innerHTML = message;
}
</script>


他ブラウザからドロップする

ブラウザ外の別アプリケーションからドラッグ&ドロップを受け入れるには、ドロップイベントを補足してdataTransferでドロップされた情報を読み取ります。
他アプリケーション(ブラウザ)からドロップすることができるMIME/TYPEは、「text/plain」「text/html」「text/xml」「text/uri-list」です。

下の例は、他ブラウザで適当なサイトを表示して適当な文字を選択し、そのまま四角の中にドロップすると、ドロップされた情報を表示する例です。
テキストにはHTMLタグがある可能性があるので、タグが処理されないように一旦HTMLのDiv要素に入れることでタグが処理されないようにエスケープ処理をかけています。
FireFoxで実行すると自動的にリンク読み込み処理が走ってエラーが表示されるようです。



ここにドロップして下さい。





<div id="dropSample" ondragover="onDragOver2(event)" onDrop="onDrop2(event)" style="border:1px solid #0000FF;border-radius:4px; width:300px; height:200px">
ここにドロップして下さい。
</div>
<div id="dropItemInfo"></div>
<script type="text/javascript">
var di = document.getElementById("dropItemInfo");
function onDrop2(event) {
    var text = event.dataTransfer.getData("text/plain");
    di.innerHTML = escapeHTML(text);
}
function onDragOver2(event) {
    event.preventDefault();
}
function escapeHTML(str) {
    var div = document.createElement("div");
    var text = document.createTextNode("");
    div.appendChild(text);
    text.data = str;
    return div.innerHTML;
}
</script>


2011/07/31

ファイルをブラウザにドロップして読み込む

ブラウザにドラッグしたファイルを読み込むには、「ドラッグ&ドロップを検出する」と同じように、dropイベントを補足し、「ローカルファイルを読み込む」と同じようにFileReaderでドロップされたデータを読み込むようにします。


下の四角にエクスプローラ/ファインダー等からファイルをドラッグすると、ブラウザにファイルを読み込みます。

ここにドロップして下さい。







<div id="dragAndDropSample" style="border: 1px solid #0000FF;border-radius:4px; width:300px; height:200px;" onDragOver="onDragOver2(event)" onDrop="onDrop2(event)">
ここにドロップして下さい。
</div>
<div id="info"></div>
<div id="view"></div>
<script type="text/javascript">
var info = document.getElementById("info");
var v = document.getElementById("view");
var fr = new FileReader();
function onDragOver2(event) {
    event.preventDefault();
}
function onDrop2(event) {
    var fs = event.dataTransfer.files;
    for ( var i = 0 ; i < fs.length ; i++) {
        var f = fs[i];
        info.innerHTML = "name:" + f.name + "  type:" + f.type + "  size:" + f.size / 1000 + " KB";
        if(/^image/.test(f.type)) {
            var img = document.createElement("img");
            fr.onload = function() {
                img.src = fr.result;
                v.appendChild(img);
            }
            fr.readAsDataURL(f);
        }
        if (/^text/.test(f.type)) {
            fr.onload = function() {
                v.innerHTML = fr.result;
            }
            fr.readAsText(f, "utf-8");
        }
    }
    event.preventDefault();
}
</script>

ローカルファイルを読み込む

ファイルを読み込むには、File APIのFileReaderを使用します。




0%





<input type="file" name="files[]" id="file" multiple onchange="readFile()">
<div id="progress">0%</div>
<div id="view"></div>
<script type="text/javascript">
function readFile() {
    var fs = document.getElementById("file").files;
    var v = document.getElementById("view");
    v.innerHTML = "";
    for ( var i = 0 ; i < fs.length ; i++ ) {
        var f = fs[i];
        var fr = new FileReader();
        var p = document.getElementById("progress");
        if (f.type == "image/jpeg" || f.type == "image/gif" || f.type == "image/png") {
            var img = document.createElement("img");
            fr.onload = function(event) {
                img.src = fr.result;
                v.appendChild(img);
            }
            fr.onerror = function() {
                v.innerHTML = "エラーが発生しました。";
            }
            fr.onprogress = function(event) {
                p.innerHTML = Math.floor(event.loaded / event.total) * 100 + "%";
            }
            fr.readAsDataURL(f);
        } else {
            fr.onload = function(event) {
                v.innerHTML = fr.result;
            }
            fr.onerror = function() {
                v.innerHTML = "エラーが発生しました。";
            }
            fr.onprogress = function(event) {
                p.innerHTML = Math.floor(event.loaded / event.total) * 100 + "%";
            }
            fr.readAsText(f, "utf-8");
        }
    }
}
</script>



上の例は、input要素でファイルを選択させ、選択後にファイルを読み込んでImageファイルの場合はimg要素を追加し、Image以外の場合はテキストとして読み込んで表示するようにしています。また読み込みの際、progressイベントを補足して進行度をパーセント表示させています。
FileReaderのメソッドは以下の物があります。


メソッド・プロパティ内容
readAsBinaryString(ファイル)バイナリとして読み込みます。
readAsText(ファイル, エンコーディング)テキストファイルを指定エンコーディングで読み込みます。
readAsDataURL(ファイル)ファイルをDataURL形式で読み込みます。
abort()ファイル読み込みを中断します。
resultメソッドの実行結果を参照します。


イベント一覧は以下の物があります。
イベント内容
loadstart読み込みが開始された
load読み込みが正常終了
loadend読み込みが終了(成功 or 失敗)
abort読み込みが中断された
error読み込みエラーが発生
progress読み込み中

ファイル情報を取得する

File APIを使用すれば、filesでファイル情報を取得してローカルにあるファイルにアクセスすることができます。
filesで取得できる情報には以下の物があります。


プロパティ内容
nameファイル名
typeファイルのMIME/TYPE
sizeファイルのバイトサイズ
urnファイルのURN










<input type="file" name="files[]" id="file" multiple onchange="getFiles()"><br>
<span id="disp"></span>
<script type="text/javascript">
function getFiles() {
    var files = document.getElementById("file").files;
    var disp = document.getElementById("disp");
    disp.innerHTML = "";
    for(var i=0 ; i < files.length; i++) {
        var file = files[i];
        disp.innerHTML += file.name + " : " + file.size/1000 + " KB type:" + file.type + " URN:" + file.urn + "<br>";
    }
}
</script>

ドラッグ&ドロップを検出する

ドラッグ&ドロップを検出するには、onDragStartのイベントを補足して、dataTransferのメソッドでデータを受け渡します。 draggable属性がデフォルトで有効なのはimg要素とa要素だけなので、その他はドラッグ&ドロップを行わせる場合は明示的にdraggable=”true”に指定する必要があります。

5つの花を四角の中にドロップして移動させるサンプルです。


ここにドロップして下さい。





<img draggable="true" id="flower" ondragstart="onDragStart1(event)" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrN7GoVUmc8GWwlCrypw4f2ZMFCMZCQJvAKGxFIa9wOqK_ECXHs-Zo2sI5otcUc07B6PTudt60HymlNn6UJeHVh9M1wyagAzFO3fjpphPCDWsapTAxssPY5rBUuYHNwIV2fVcAlmcCTAQR/s1600/_Sunflower.gif" />
<img draggable="true" id="dandellion" ondragstart="onDragStart1(event)" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUFRjLRFcgpbOK4Wsu1Vxn1JpTFdsudqjftA7aLis-DL6kfxPC1yVoZRtAos4VoZ4DP58387QcGMox9i6gCdFPzKH8XtVCBVszxWRlxALs8vSjzyVARrBhr5HduOB-9oVVl03CYs9x2dX9/s1600/Dandelion.gif" />
<img draggable="true" id="African Daisy" ondragstart="onDragStart1(event)" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-8DlPX2EtuZTqgNwmhVVe790bdl6-SjcPKssqbovYxDjigJnvbGl2H5w9M_cR27vCHUQZvWJpSlw_c4bkXhwBospATjzSqyfVtKZHleRSaAUp3DCs_sZl-z2fIlt1N6dWlJz-cXJqkWEd/s1600/African+Daisy.gif" />
<img draggable="true" id="Ixia" ondragstart="onDragStart1(event)" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1oL5S3SeWlU3KXi5FAVaKNkZmUbwPQwKxJhnLKxXkXev-IrCLET55LGMH9SZhxHxFktkwXmmdiBrSXE18-iETdWJ13MuOGplhjxGG7kBA7tu7H-zDKt9Hx2uWLT2gVTYna5a_dMp_LEYE/s1600/Ixia.gif" />
<img draggable="true" id="Spiked" ondragstart="onDragStart1(event)" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg15pYaJtscUa0JI3AnlUte5n4Ado14vWIyegi5RVaqYlvhw1DAfTgaBte3nLJIAT0udeKO6hkrEfktIP6Hv4jAUk8dKjaF6Srf-742mTLfGlzNIMnlo_veE8pJcPQ86PPpDdR0nqjeaET7/s1600/Spiked.gif" />
<br />
<div id="drop1" ondragenter="onDragEnter1(event)" ondragleave="onDragLeave1(event)" ondragover="onDragOver1(event)" ondrop="onDrop1(event)" style="border-radius: 4px; border: 1px solid #0000FF; height: 100px; width: 400px;">
ここにドロップして下さい。
</div>
<div id="debug">
</div>
<script type="text/javascript">
var debug = document.getElementById("debug");
function onDragStart1(event) {
 debug.innerHTML = "Drag Start";
 event.dataTransfer.setData("text", event.target.id);
}
function onDrop1(event) {
 debug.innerHTML = "On Drop";
 var id = event.dataTransfer.getData("text");
 var elm = document.getElementById(id);
 event.currentTarget.appendChild(elm);
 event.preventDefault();
}
function onDragOver1(event) {
 debug.innerHTML = "On Drag Over";
 event.preventDefault();
}
function onDragEnter1(event) {
 debug.innerHTML = "On Drag Enter";
}
function onDragLeave1(event) {
 debug.innerHTML = "On Drag Leave";
}
</script>



onDrop1 / onDragOver1にある、「preventDefault()」は、デフォルトではDropイベントが無効化されているので、このメソッド呼び出しでDropイベントを有効化しています。

メソッド・プロパティ内容
setData(key , value)ドラッグ&ドロップされるデータをセットする
keyには"text"か"url"のみ指定できる。
getData(key)ドラッグ&ドロップされたデータを取得する
keyには"text"か"url"のみ指定できる。
clearDataドラッグ&ドロップされたデータをクリアする
typessetDataメソッドでセットされた情報のtype(text/plain等)を取得する
files他アプリケーションからドラッグされたファイル情報を取得する
setDragImage(image, X, Y)ドラッグ中に表示されるイメージを指定する
addElement(element)ドラッグ中に表示されるイメージに要素を追加する

2011/07/30

SVGを描画する

SVGとは、Scalable Vector Graphicsの略です。
HTML5では、外部ファイルにある拡張子がSVGのファイルを読み込んで表示させることができます。
SVGファイルはその名の通りベクターベースなので拡大してもピクセルがカクカクになったりしないという利点があります。また、XMLベースなのでグラフィックツールなどを利用して簡単にデータが作成できるという利点もあります。

以下は四角形を描画する例です。





<svg height="150" width="300" xmlns="http://www.w3.org/2000/svg">
 <rect height="100" style="fill: orange;" width="100" x="30" y="30"></rect>
 <rect height="100" ry="8" style="fill: black;" width="100" x="150" y="30"></rect>
</svg>



円の例です。





<svg height="100" width="100" xmlns="http://www.w3.org/2000/svg">
    <circle cx="50" cy="50" r="50" style="fill: blue;" width="100" />
</svg>



楕円形です。





<svg height="100" width="100" xmlns="http://www.w3.org/2000/svg">
 <ellipse cx="50" cy="50" rx="50" ry="20" style="fill: skyblue;">
</ellipse></svg>




線の例です。





<svg height="200" width="200" xmlns="http://www.w3.org/2000/svg">
 <polyline fill="none" points="20,20 100,100 180,30" stroke-width="3" stroke="black"></polyline>
</svg>



ポリゴンの例です。





<svg height="200" width="200" xmlns="http://www.w3.org/2000/svg">
 <polygon fill="blue" points="20,20 100,100 180,30" stroke-width="3" stroke="black"></polygon>
</svg>



グラフィックツールを使えば、パスやグラデーションを使った以下の様な絵もSVGで描画可能です。





<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
     y="0px" width="300px" height="300px" viewBox="0 0 300 300" enable-background="new 0 0 300 300" xml:space="preserve">
<polygon fill="#FFFF00" stroke="#000000" stroke-miterlimit="10" points="153,184 100.271,158.186 49.113,186.988 57.37,128.863
    14.168,89.109 72,79 96.458,25.628 123.943,77.506 182.261,84.274 141.416,126.445 "/>
<path fill="#C7B299" stroke="#000000" stroke-miterlimit="10" d="M239.192,113.619c4.675,4.697,4.657,12.296-0.04,16.971L119,231
    c-4.697,4.675-14.052,25.583-18.727,20.886l-8.465-8.505C87.133,238.684,109.303,228.675,114,224l99.757-118.926
    c4.696-4.675,12.295-4.657,16.97,0.04L239.192,113.619z"/>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="207.1367" y1="233.4961" x2="281.1367" y2="233.4961" gradientTransform="matrix(-0.9478 0.3187 -0.3187 -0.9478 540.8281 359.5)">
    <stop  offset="0" style="stop-color:#FFFFFF"/>
    <stop  offset="0.1832" style="stop-color:#FAFAFA"/>
    <stop  offset="0.3909" style="stop-color:#EDEDED"/>
    <stop  offset="0.6108" style="stop-color:#D6D6D6"/>
    <stop  offset="0.8375" style="stop-color:#B6B6B6"/>
    <stop  offset="1" style="stop-color:#9B9B9B"/>
</linearGradient>
<circle fill="url(#SVGID_1_)" stroke="#000000" stroke-miterlimit="10" cx="235" cy="216.001" r="37"/>
<path fill="none" stroke="#000000" stroke-miterlimit="10" d="M211.001,187.823C220.17,191.074,227,203.575,227,218.5
    c0,13.298-5.423,24.673-13.091,29.294"/>
<path fill="none" stroke="#000000" stroke-miterlimit="10" d="M263.954,239.872c-6.184-2.017-12.876-13.377-15.964-27.979
    c-2.752-13.01-1.847-24.828,1.807-30.323"/>
</svg>




文字を描く例です。

テキストです。 パスに沿ったテキストです。



<svg height="200" width="400" xmlns="http://www.w3.org/2000/svg">
 <text fill="skyblue" font-family="sans-serif" font-size="30" stroke-width="1" stroke="blue" x="30" y="30">
テキストです。
 </text>
 <defs>
  <path d="M30,100 C100,100 150,200 200,100 C250,200 300,150 400,150" id="textPath1"></path>
 </defs>
 <text fill="skyblue" font-family="sans-serif" font-size="30" stroke-width="1" stroke="blue" x="30" y="100">
  <textpath xlink:href="#textPath1">パスに沿ったテキストです。</textpath>
 </text>
</svg>



以下は、外部にあるsvgファイルを表示する例です。ファイルは存在しないので以下ではエラーメッセージが表示されます。






<object data="svgファイルのURL" type="image/svg+xml" width="400" height="300"></object>


2011/07/29

canvas上でアニメーションする

canvas上でアニメーションをさせるには、javascriptで繰り返し描画を行います。


マウスを乗せると描画します。






<canvas id="drawAnimationOnCanvas1Canvas" style="border: 1px solid;" onmouseover="drawAnimationOnCanvas1();" width="400" height="300">
</canvas>
<script language="javascript" type="text/javascript">
function drawAnimationOnCanvas1() {
    var c = document.getElementById("drawAnimationOnCanvas1Canvas");
    var context = c.getContext("2d");
    var width = c.width;
    var height = c.height;
    var cx = 150;
    var cy = 150;
    var r = 150;
    var d = 0;
    var fontSize = 1;
    var fontAdd = 0.02;
    setInterval(fire, 50);
    function fire() {
        context.clearRect(0, 0, c.width, c.height);
        context.fillStyle = "#FFFFFF";
        context.fillRect(0, 0, c.width, c.height);
        var x = Math.cos(d * 360) * r + cx;
        var y = Math.sin(d * 360) * r / 2 + cy;
        context.fillStyle = "#000000";
        context.font = fontSize + "em 'Georgia'";
        context.fillText("This is not a Flash", x, y);
        d += 0.07;
        fontSize += fontAdd;
        if (3 < fontSize) fontAdd = -0.02;
        if (fontSize <= 0.25) fontAdd = 0.02;
    }
}
</script>

canvasにグラフを描画する

グラフを描画するには、canvas要素に「四角形を描く」や「線を描く」等で紹介したメソッドを使って地道に書いていくか、ライブラリを使います。
ライブラリの説明はそれぞれのサイトをご覧下さい。
RGraph
html5.jp


マウスを乗せるとグラフを描画します。






<canvas id="drawGraphCanvas1" onmouseover="drawGraph1();" style="border: 1px solid;" width="400" height="300">
</canvas>
<script language="Javascript" type="text/javascript">
function drawGraph1() {
    var c = document.getElementById("drawGraphCanvas1");
    var context = c.getContext("2d");
   
    // プロットデータ
    var month = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
    var attendance = [3, 5, 4, 7, 9, 5, 11, 13, 15, 20, 19, 22];
    var attendanceMax = 22;    // attendanceの最大値
   
    var originalPoint = 50;    // 原点座標
    var barInterval = 20;        // 棒グラフの間隔

    var graphHeight = c.height - originalPoint;    // グラフの高さ取得
    var graphWidth = c.width - originalPoint;        // グラフの幅取得
    // 1メモリの高さ
    var memHeight = Math.floor(graphHeight / attendanceMax);
    // 棒グラフの幅
    var barWidth = (graphWidth - barInterval * month.length) / month.length;
   
    // X軸を描画
    context.moveTo(originalPoint, graphHeight);
    context.lineTo(graphWidth + originalPoint, graphHeight);
    context.strokeStyle = "#121212";
    context.stroke();
    // Y軸を描画
    context.moveTo(originalPoint, 0);
    context.lineTo(originalPoint, graphHeight);
    context.stroke();

    // 棒グラフを描画
    var x = originalPoint + barInterval;
    var i = 0;
    for( i = 0 ; i < month.length ; i++) {
        context.fillStyle = "#FF1212";
        context.fillRect(x, graphHeight - (memHeight * attendance[i])
            , barWidth, memHeight * attendance[i]);
       
        context.fillStyle = "#000000";
        context.fillText(attendance[i], x, graphHeight - (memHeight * attendance[i]) - 3);
       
        context.strokeStyle = "#FF0000";
        context.stroke();
        context.fillStyle = "#121212";
        context.fillText(month[i] + "月", x, graphHeight + 15);
        x += barInterval + barWidth;
    }

    // メモリを描画
    var y = graphHeight - memHeight;
    for( i = 0 ; 0 < y ; i++) {
        context.strokeStyle = "#696969";
        context.moveTo(originalPoint, y);
        context.lineTo(graphWidth + originalPoint, y);
        context.stroke();
       
        if ( (i + 1) % 5 == 0 ) {
            context.fillStyle = "#000000";
            context.fillText(i + 1, originalPoint - 20, y);
        }
        y -= memHeight;
    }
}
</script>

canvasに文字を描画する

canvasにテキストを描画するには、以下のプロパティ、メソッドを使います。

メソッド・プロパティ内容
fontフォントを指定
textAlign表示位置の指定
left/center/right
textBaselineテキストのベースラインを指定
位置は上からtop/hanging/middle/alphabetic/ideographic/bottomの順。
fillText(text, X, Y)塗りつぶしテキストを描画
fillText(text, X, Y, Width)塗りつぶしテキストを描画
strokeText(text, X, Y)線でテキストを描画
strokeText(text, X, Y, Width)線でテキストを描画

マウスを乗せると文字を描画します。







<canvas id="drawTextCanvas1" onmouseover="drawText1();" width="400" height="400">
</canvas>
<script language="javascript" type="text/javascript">
function drawText1() {
    var c = document.getElementById("drawTextCanvas1");
    var context = c.getContext("2d");
    var text = "Baseline=top";
    context.font = "1em 'Georgia'";
    context.lineWidth = 1;
    context.fillStyle = "#1212FF";
    context.strokeStyle = "#0000FF";
    context.textBaseline = "top";
    context.fillText (text, 80, 50);
    context.beginPath();
    context.moveTo(80, 50);
    context.lineTo(320, 50);
    context.stroke();

    text = "Baseline=hanging";
    context.textBaseline = "hanging";
    context.fillText(text, 80, 100);
    context.beginPath();
    context.moveTo(80, 100);
    context.lineTo(320, 100);
    context.stroke();

    text = "Baseline=middle";
    context.textBaseline = "middle";
    context.fillText(text, 80, 150);
    context.beginPath();
    context.moveTo(80, 150);
    context.lineTo(320, 150);
    context.stroke();

    text = "Baseline=alphabetic";
    context.textBaseline = "alphabetic";
    context.fillText(text, 80, 200);
    context.beginPath();
    context.moveTo(80, 200);
    context.lineTo(320, 200);
    context.stroke();

    text = "Baseline=ideographic";
    context.textBaseline = "ideographic";
    context.fillText(text, 80, 250);
    context.beginPath();
    context.moveTo(80, 250);
    context.lineTo(320, 250);
    context.stroke();

    text = "Baseline=bottom";
    context.textBaseline = "bottom";
    context.fillText(text, 80, 300);
    context.beginPath();
    context.moveTo(80, 300);
    context.lineTo(320, 300);
    context.stroke();

    text = "縁取り文字";
    context.font = "2em 'Georgia'";
    context.strokeText(text, 80, 350);
    context.beginPath();
    context.moveTo(80, 350);
    context.lineTo(320, 350);
    context.stroke();
}
</script>


2011/07/28

イメージを描画する

イメージをcanvasに描画するには、drawImageメソッドを使います。

描画メソッド内容
drawImage(image, X, Y)(X, Y)にimageを描画
drawImage(image, X, Y, W, H)(X, Y)にimageを指定の大きさ(Width, Height)で描画
drawImage(image, X1, Y1, W1, H1, X2, Y2, W2, H2)image画像から座標(X1, Y1)から大きさ(W1, H1)で切り取った後、(X2, Y2)から指定の大きさ(W2, H2)にコピーして描画

マウスを乗せると描画します。








<canvas id="drawImage1Canvas" style="border: 1px solid;" onmouseover="drawImage1();" width="400" height="300">
</canvas>
<script language="javascript" type="text/javascript">
function drawImage1() {
    var c = document.getElementById("drawImage1Canvas");
    var context = c.getContext("2d");
    var image = new Image();
    image.src = "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrN7GoVUmc8GWwlCrypw4f2ZMFCMZCQJvAKGxFIa9wOqK_ECXHs-Zo2sI5otcUc07B6PTudt60HymlNn6UJeHVh9M1wyagAzFO3fjpphPCDWsapTAxssPY5rBUuYHNwIV2fVcAlmcCTAQR/s1600/_Sunflower.gif";
    image.onload = function() {
        context.drawImage(image, 10, 10, 400, 300);
    }
}
</script>


マウスを乗せると描画します。







<canvas id="drawImage2Canvas" style="border: 1px solid;" onmouseover="drawImage2();" width="400" height="300">
</canvas>
<script language="javascript" type="text/javascript">
function drawImage2() {
    var c = document.getElementById("drawImage2Canvas");
    var context = c.getContext("2d");
    var image = new Image();
    image.src = "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrN7GoVUmc8GWwlCrypw4f2ZMFCMZCQJvAKGxFIa9wOqK_ECXHs-Zo2sI5otcUc07B6PTudt60HymlNn6UJeHVh9M1wyagAzFO3fjpphPCDWsapTAxssPY5rBUuYHNwIV2fVcAlmcCTAQR/s1600/_Sunflower.gif";
    image.onload = function() {
        context.drawImage(image, 10, 10, 20, 30, 10, 10, 300, 400);
    }
}
</script>

ベジェ曲線を描画する

ベジエ曲線を描画するには、以下のメソッドを使います。

描画メソッド内容
quadraticCurveTo(X1, Y1, X2, Y2)現在位置から(X2, Y2)までのベジェ曲線を描画。その際、(X1, Y1)を使って2次ベジェ曲線カーブをかけます。
bezierCurveTo(X1, Y1, X2, Y2, X3, Y3)現在位置から(X3, Y3)までのベジェ曲線を描画。その際、(X1, Y1), (X2, Y2)を使って3次ベジェ曲線カーブをかけます。

下の例は、赤線がquadraticCurveToを使った描画で、青線がbezierCurveToを使った描画です。

マウスを乗せると描画します。








<canvas id="drawBezierCurveCanvas" style="border: 1px solid;" onmouseover="drawBezierCurve();" width="400" height="300">
</canvas>
<script language="javascript" type="text/javascript">
function drawBezierCurve() {
    var c = document.getElementById("drawBezierCurveCanvas");    var context = c.getContext("2d");
    context.beginPath();
    context.moveTo(100, 50);
    context.quadraticCurveTo(300, 0, 300, 250);
    context.strokeStyle = "#FF0000";
    context.stroke();

    context.beginPath();
    context.moveTo(100, 50);
    context.bezierCurveTo(300, 0, 300, 250, 350, 50);
    context.strokeStyle = "#0000FF";
    context.stroke();
}
</script>

円を描く

円を描画するには、arcメソッドを使います。

arc(X, Y, 開始角度, 終了角度, 反時計回り);

角度はラジアンで指定します。また、時計回りに増加していきます。

マウスを乗せると描画します。







<canvas id="drawArcCanvas1" style="border: 1px solid;" onmouseover="drawArc1();width="400" height="300">
</canvas>
<script language="javascript" type="text/javascript">
function drawArc1() {
    var c = document.getElementById("drawArcCanvas1");
    var context = c.getContext("2d");
    context.arc(200, 150, 100, 0 , 2 * Math.PI, false);
    context.strokeStyle = "#FFCCCC";
    context.lineWidth = 6;
    context.fillStyle = "#CCCCFF";
    context.fill();
    context.stroke();
}
</script>




マウスを乗せると描画します。







<canvas id="drawArcCanvas2" style="border: 1px solid;" onmouseover="drawArc2();" width="400" height="300">
</canvas>
<script language="javascript" type="text/javascript">
function drawArc2() {
    var c = document.getElementById("drawArcCanvas2");
    var context = c.getContext("2d");
    context.arc(200, 150, 100, 0, Math.PI / 2, false);
    context.strokeStyle = "#FFCCCC";
    context.lineWidth = 6;
    context.fillStyle = "#CCCCFF";
    context.fill();
    context.stroke();
}
</script>

パスにグラデーションで色を塗る

パスにグラデーションで色を塗るには、pathStyleにグラデーションを指定します。

描画メソッド/プロパティ内容
createLinearGradient(x1, y1, x2, y2)線形グラデーションの生成
createRadialGradient(x1, y1, r1, x2, y2, r2)円形グラデーションの生成
addColorStop(オフセット, 色)グラデーションの色を指定








<canvas id="drawGradientPathCanvas1" onmouseover="drawGradientPath1();" style="border: 1px solid;" width="400" height="300"></canvas>
<script language="javascript" type="text/javascript">
function drawGradientPath1() {
    var c = document.getElementById("drawGradientPathCanvas1");
    var context = c.getContext("2d");
    context.beginPath();
    context.moveTo(50, 100);
    context.lineTo(350, 100);
    context.lineTo(80, 250);
    context.lineTo(200, 50);
    context.lineTo(320, 250);
    context.closePath();
    var g = context.createLinearGradient(0, 0, 300, 300);
    g.addColorStop(0.3, "#FF0000");
    g.addColorStop(1, "#00FF00");
    context.fillStyle = g;
    context.fill();
    context.stroke();
}
</script>


以下の例は、上の「createLinearGradient」を「createRadialGradient」に変えただけの例になります。







<canvas id="drawGradientPathCanvas2" style="border: 1px solid;" onmouseover="drawGradientPath2();" width="400" height="300"></canvas>
<script language="javascript" type="text/javascript">
function drawGradientPath2() {
    var c = document.getElementById("drawGradientPathCanvas2");
    var context = c.getContext("2d");
    context.beginPath();
    context.moveTo(50, 100);
    context.lineTo(350, 100);
    context.lineTo(80, 250);
    context.lineTo(200, 50);
    context.lineTo(320, 250);
    context.closePath();
    var g = context.createRadialGradient(200, 150, 50, 200, 150, 100);
    g.addColorStop(0.3, "#FF0000");
    g.addColorStop(1, "#00FF00");
    context.fillStyle = g;
    context.fill();
    context.stroke();
}
</script>

パスに色を塗る

canvas要素にパスを描画したら、それに色を塗ることもできます。

描画メソッド/プロパティ内容
strokeStyle線の色を指定
lineWidth線の太さを指定
fillStyle塗りつぶしの色を指定
fill()塗りつぶしの実行









<canvas id="drawFillPathCanvas" onmouseover="drawFillPath();" style="border: 1px solid;" width="400" height="300">
</canvas>
<script language="javascript" type="text/javascript">
function drawFillPath() {
    var c = document.getElementById("drawFillPathCanvas");
    var context = c.getContext("2d");
    context.beginPath();
    context.moveTo(50, 100);
    context.lineTo(350, 100);
    context.lineTo(80, 250);
    context.lineTo(200, 50);
    context.lineTo(320, 250);
    context.closePath();
    context.strokeStyle = "#CACAFF";
    context.lineWidth = 8;
    context.fillStyle = "#FFCACA";
    context.fill();
    context.stroke();
}
</script>

線を描く

絵を描けるようにするには、canvas要素を追加します。
canvas要素内で以下のメソッドで描画します。

描画メソッド内容
beginPathパスの開始
moveToX, Yに移動
lineToX, Yに向けて線を描画
closePathパスを閉じて描画(最後に始点に向かってパスが引かれます)
strokeパスを線として表示









<canvas id="drawPathCanvas" onmouseover="drawPath();" style="border: 1px solid;" width="400" height="300">
</canvas>
<script language="javascript" type="text/javascript">
function drawPath() {
    var c = document.getElementById("drawPathCanvas");
    var context = c.getContext("2d");
    context.beginPath();
    context.moveTo(100, 100);
    context.lineTo(300, 200);
    context.stroke();
}
</script>

四角形を描画する

絵を描けるようにするには、canvas要素を追加します。
canvas要素内で以下のメソッドで描画します。

パラメータは全て(x, y, 幅, 高さ)です。
描画メソッド内容
fillRect塗りつぶし四角形を描画
clearRect四角形をクリア
strokeRect四角形の専を描画



マウスを乗せると描画します。

このブラウザではcanvasは非対応です。





<canvas id="drawCanvas" onmouseover="drawRect();" style="border:1px solid;" width="400" height="300">このブラウザではcanvasは非対応です。</canvas>
<script language="javascript" type="text/javascript">
function drawRect() {
 var c = document.getElementById("drawCanvas");
 var context = c.getContext("2d");
 context.fillRect(40, 40, 200, 200);
 context.clearRect(50, 50, 150, 150);
 context.strokeRect(60, 60, 100, 100);
}
</script>

音声ファイルを再生する

音声ファイルを再生するには、audio要素を使います。
プロパティや操作などは基本的にビデオの再生と同じ物が使用できます。(poster(ロード中の画像表示)以外)
詳細は「ビデオを再生する」「Javascriptからビデオにアクセスする」を参照して下さい。

2011/07/27

Javascriptからビデオ要素にアクセスする

video要素にJavascriptからアクセスするには、「getElementById」を使用します。
getElementByIdで得られたvideo要素に対し、以下のものを使ってアクセスすることが可能です。


メソッド一覧
メソッド意味
load()ファイルの読み込みを行う
play()ファイルの再生を行う
pause()ファイルの再生の一時停止を行う
canPlayType(MIMEタイプ)指定MIMEタイプが再生可能か判断する
maybe:再生可能



プロパティ一覧
プロパティ意味
currentSrc現在再生しているファイルのURL。参照のみ
duration再生時間の長さ(秒)。参照のみ
ended再生が終了したかどうか
true:再生終了。参照のみ
errorエラー時のエラーコード。参照のみ
played再生済みの時間範囲(TimeRanges型)。参照のみ
seekableシーク可能な時間範囲(TimeRanges型)。参照のみ
seeking指定された再生位置に移動中
true:シーク中。参照のみ
startTime再生開始位置(秒数)。参照のみ
src動画ファイルのURL
readyStateメディアのダウンロード状態
currentTime現在の再生位置(秒)
defaultPlaybackRateデフォルトの再生速度。デフォルトは1.0
playbackRate再生速度。デフォルトは1.0。巻き戻しはマイナス値
preloadpreload属性。
auto:自動読み込み有効
metadata:メタデータのみ
none:自動読み込み無し
loop繰り返し再生をするか
controlsコントロールを表示するか
volume音声のボリューム。0.0〜1.0
mutedミュートするか。
true:ミュート



イベント一覧
イベント発生条件
loadstartメディアデータのロード開始
progressメディアデータの読み込み中
suspendサスペンドした
abort中断された
errorエラーが発生した
emptiedメディアデータが空
stalled中断した
play再生開始
pause再生停止
loadメディアのダウンロード完了
loadedmetadataメタデータのダウンロード完了
loadeddataデータの読み込みが完了
waiting待機中
playing再生中
canplay再生可能
canplaythrough最後まで再生可能
seekingシーク中
seekedシーク終了
timeupdate再生中は1秒間隔で発生
ended再生終了
ratechange再生速度が変更された
durationchange再生時間が変更された
volumechange音量が変更された


下の例は、ビデオを再生中にtimeupdateイベントを補足して時間と再生率を表示する例です。










<video height="300" id="playMovie" poster="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrN7GoVUmc8GWwlCrypw4f2ZMFCMZCQJvAKGxFIa9wOqK_ECXHs-Zo2sI5otcUc07B6PTudt60HymlNn6UJeHVh9M1wyagAzFO3fjpphPCDWsapTAxssPY5rBUuYHNwIV2fVcAlmcCTAQR/s1600/_Sunflower.gif" preload="auto" width="400">
<source src="https://docs.google.com/uc?id=0B_-pW_pm0gmnOTQxMDlkYzUtNjk0OS00OGM3LWI4ODAtZWM3Y2Y5YzZkMTYx&amp;export=download&amp;hl=en_US" type="video/mp4; codecs='avc1.42E01E,mp4a.40.2'"></source>
<source src="OGG用ファイルのURL.ogg" type="video/ogg; codecs='theora, vorbis'"></source>
<object data="player.swf" type="application/x-shockwave-flash"> <param name="movie" value="フラッシュ用ファイルのURL.swf">
</object>
</video>

<input onclick="startVideo()" type="button" value="再生" />
<span id="progress" name="progress"></span>
<script type="text/javascript">
var v = document.getElementById("playMovie");
function startVideo() {
 v.play();
 v.addEventListener("timeupdate", fire, false);
}
function fire() {
 var prg = document.getElementById("progress");
 var rate = Math.floor(v.currentTime) / Math.floor(v.duration) * 100;
 rate = Math.round(rate);
 prg.innerHTML = Math.floor(v.currentTime) + "/" + Math.floor(v.duration) + "  " + rate + "%";
}
</script>

動画を再生する

HTML5は標準で動画の再生をサポートしていますが、以下のようにブラウザごとに再生できるフォーマットに制限があります。
また、本項執筆時点ではHTML5は残念ながらストリーミング再生には対応していないようです。


コーデック概要ChromeFire
Fox
OperaSafariiPhone
/iPad
IE
Ogg Theora
Ogg Vorbis
Xiph.org Foundationが開発したオープンソースのビデオ・音声コーデック。×××
MP4(H.264, AAC)携帯電話からHDTV等の高品質再生まで対応した共通規格。×××


下にビデオ要素を使った例を示します。動画ファイルをGoogle Docに置いてるので、ビデオが見られない場合があるかもしれません。(Google Docはアクセスが集中するとアクセス制限がかかるようです。)




以下に、HTMLを示します。
poster属性とsrc属性は下の例では長くなっていますが(Googleのサービスを利用するため、長いURLになっています。)、サーバー等に配置する場合は、もっと短いURLで記述できるはずです。

<video controls="controls" height="300" poster="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrN7GoVUmc8GWwlCrypw4f2ZMFCMZCQJvAKGxFIa9wOqK_ECXHs-Zo2sI5otcUc07B6PTudt60HymlNn6UJeHVh9M1wyagAzFO3fjpphPCDWsapTAxssPY5rBUuYHNwIV2fVcAlmcCTAQR/s1600/_Sunflower.gif" preload="auto" src="https://docs.google.com/uc?id=0B_-pW_pm0gmnOTQxMDlkYzUtNjk0OS00OGM3LWI4ODAtZWM3Y2Y5YzZkMTYx&amp;export=download&amp;hl=en_US" width="400">再生できません。
&nbsp;</video>



それぞれのパラメータは以下の意味になります。
属性内容
src動画ファイル名
autoplay自動で再生を行うか指定。
controls再生・停止などのコントローラを表示する指定。
preload自動読み込みを行うか指定。
auto:自動読み込み有効
metadata:メタデータのみ
none:自動読み込み無効
loop繰り返し再生を指定。
poster動画が再生されるまでの間に表示される画像を指定

どのブラウザでも再生できるようにするには、以下のようにsource属性でブラウザに対応したファイルの指定を行います。
<object>〜</object>まではHTML5に対応していないブラウザでもFlashを使って再生できるようにするタグです。
sourceの「type」は基本的に不要ですが、動画データによっては複数のタイプを含んでいてブラウザがどのタイプを選べば良いか判断できない場合があるようなので、その場合に備えて一応指定しておきます。
当然ですが、動画ファイルはそれぞれ用意する必要があります。

type内容
video/mp4; codecs='avc1.42E01E,mp4a.40.2'MP4コンテナ。シンプルベースラインH.264動画とAAC音声
video/mp4; codecs='mp4v.20.8,mp4a.40.2'MP4コンテナ。シンプルプロファイルレベル0動画とAAC音声
audio/ogg; codecs='vorbis'OGGコンテナ。vorbis音声コーデック


下の例では、sourceに「OGG用ファイルのURL.ogg」「フラッシュ用ファイルのURL.swf」と指定していますが、この例では実在しないファイルなので再生されません。動画ファイルの変換が面倒くさいのでしてないだけです。(汗)





<video controls="controls" height="300" poster="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrN7GoVUmc8GWwlCrypw4f2ZMFCMZCQJvAKGxFIa9wOqK_ECXHs-Zo2sI5otcUc07B6PTudt60HymlNn6UJeHVh9M1wyagAzFO3fjpphPCDWsapTAxssPY5rBUuYHNwIV2fVcAlmcCTAQR/s1600/_Sunflower.gif" preload="auto" width="400">再生できません。
<source src="https://docs.google.com/uc?id=0B_-pW_pm0gmnOTQxMDlkYzUtNjk0OS00OGM3LWI4ODAtZWM3Y2Y5YzZkMTYx&amp;export=download&amp;hl=en_US" type="video/mp4; codecs='avc1.42E01E,mp4a.40.2'"></source>
<source src="OGG用ファイルのURL.ogg" type="video/ogg; codecs='theora, vorbis'"></source>
</video>
<object data="player.swf" type="application/x-shockwave-flash">         <param name="movie" value="フラッシュ用ファイルのURL.swf">
    </object>