HTML5 CANVAS 6-7

videoタグじゃなくてcanvas経由で動画を表示する。

HTML5 6-7

videoElement = document.createElement('video')
videoDiv = document.createElement('div')
document.body.appendChild(videoDiv)
videoDiv.appendChild(videoElement)
videoDiv.setAttribute("style","display:none;")
videoType = supportedVideoFormat(videoElement)

console.log(videoType)
videoElement.setAttribute("src","/videos/sample." + videoType)
videoElement.addEventListener("canplaythrough", videoLoaded, false)

theCanvas = document.getElementById("canvasOne")
context = theCanvas.getContext("2d")

videoElement.play()
setInterval(drawScreen, 33)

なんでvideoElementにイベントリスナー設定しているのに、最後の方でplayメソッドを呼び出しているのかわからん。6-5のサンプルに倣うんだったらvideoLoadedで呼び出すべきなんじゃないのかね?

ProductName HTML5 Canvas: Native Interactivity and Animation for the Web
Steve Fulton
Oreilly & Associates Inc / 2922円 ( 2011-05-13 )


HTML5のビデオ変換がめんどくさすぎる

HTML5 Canvasも6章になってvideoを扱う。この本の欠点はサンプルコードがないことかなぁ。

コードはなくてもいいけど本書でつかった画像とか、動画とかはダウンロードできるようにしてもらいたかった。しょうがないので、必要な画像とか動画は都度用意しているが、やはり手間だ。

そして、初めてvideoタグを使う時がやってきたので、動画のコンバーターをインストールしたり、サンプルの動画を用意したりしている。

現状のブラウザの対応状況の関係で、動画関連はメインの規格が3つくらいあって、面倒だとは聞いていたけど、用意するのは本当に面倒だった。WebMなんて特に面倒くさい。ogg(theora+vorbis)はffmpeg2theoraがあるので楽だった。MP4(H.264+AAC)は特許に縛られてるからどうだろうねぇ、現状iPhoneとandroidで動くので必要だろうけど。

入門HTML5のvideoの章が、「サルでもわかるHTML5ビデオ」みたいなスクリーンショット多めのチャプターでソフトウェアの使用方法にページを割いててなんだこれ?と思っていたんだけど、実際に動画を変換してみて、

あーこの章は必要だわ

と思ったのであった。

ProductName 入門 HTML5
Mark Pilgrim
オライリージャパン / 2415円 ( 2011-04-23 )


各ブラウザのサポート対応表を改めて見直していたら、別にWebMに対応しなくてもいい気もしてきた。

ところで著者のMark Pilgrimは今月の頭にinfosuicideしちゃったみたいなんだよね。

HTML5 CANVAS 5-8

衝突をHTML5で。

html5 canvas 5-8

ProductName HTML5 Canvas: Native Interactivity and Animation for the Web
Steve Fulton
Oreilly & Associates Inc / 2922円 ( 2011-05-13 )


本書は10章がPhoneGapの使い方なんだけど、まだそこまで到達してない(今5章)。

600ページ超えでサンプルも豊富な割に3000円を切る値段と安いのでコストパフォーマンスは高いと思う。 英語も難しくないし。

HTML5 CANVAS chapter 4

3章は画像の扱い方。アイコンをタイル型に並べた画像ファイルを用意しておいて、任意の部分を切り出してCanavasに貼り付けたりアニメーションさせたりと、動くものをができるのは結構楽しい。

が、この本のサンプル画像が用意されていないのでちょっと困った。

text

ProductName HTML5 Canvas: Native Interactivity and Animation for the Web
Steve Fulton
Oreilly & Associates Inc / 2922円 ( 2011-05-13 )


Express+jade+coffeeで書いたのはGitHubにあげている。

ドット絵ブームが来る予感がしてきた。

HTML5 CANVAS chapter 3

3章はテキストの扱い方。プロパティをインタラクティブにいじれるものを作りながらText属性に関して学んでいく感じ。これといって難しい所はなくて、さくっとこなした。

text

ProductName HTML5 Canvas: Native Interactivity and Animation for the Web
Steve Fulton
Oreilly & Associates Inc / 2922円 ( 2011-05-13 )


Express+jade+coffeeで書いたのはGitHubにあげている。

HTML5 CANVAS chapter 2

Shapeの扱い方全般。グラデーションのかけかたや、影の落とし方を覚えた。それからsaveとリストアが何をしているのかとか。

ProductName HTML5 Canvas: Native Interactivity and Animation for the Web
Steve Fulton
Oreilly & Associates Inc / 2922円 ( 2011-05-13 )


Express+jade+coffeeで書いたのはGitHubにあげている。

HTML5 CANVAS chapter 1

文字当てクイズをCanvasで。コードはGitHubにおいた。

1-4

ProductName HTML5 Canvas: Native Interactivity and Animation for the Web
Steve Fulton
Oreilly & Associates Inc / 2922円 ( 2011-05-13 )


入門HTML5

「HTML5が何を目指しているか」の入門書。初心者向けではないし、tips集とかコード例が載っている本ではない。文書の構造と意味付けに始まり、HTML5で登場した新しい機能をサクサクと説明してある。

特に10章はセマンティクスとか知らないと難しいかもしれないが、未来を感じさせられる内容だ。というかbioinformaticsなんかでは10年以上前からRDFとかセマンティックwebとかずっと言われ続けてきてると思うが、なかなか普及してないような気がする。けど本書を読んでpubmedとか出版社とか化合物のマイクロデータとか整備すればかなり面白いんじゃないかなぁとおもうんだけどねぇ。

9章のwebフォームも読んだら早速使いたくなる内容だった。一方8章のオフラインウェブアプリはちょっと身近な具体例が思い浮かばなかった。

ProductName 入門 HTML5
Mark Pilgrim
オライリージャパン / 2415円 ( 2011-04-23 )


Html5 Graphics With Svg & Css3

夏の出版ラッシュか?

ProductName Html5 Graphics With Svg & Css3
Kurt Cagle
Oreilly & Associates Inc / 2081円 ( 2011-08-05 )


Want to create exciting HTML5 graphics without spending eternity in JavaScript? You can! This provides a basic overview of the two declarative languages bound to HTML5 - CSS 3.0 and Scalable Vector Graphics (SVG).

ほしい物リストが大きくなっていく

FlaskでDrag and Drop APIとXHR2で画像をポストする

HTMLガイドブックはphpなのでFlaskでやってみた。この本は良書ですね、オススメです(最後のほうにNode.jsのサンプルも載ってるし)。

ProductName 徹底解説 HTML5 APIガイドブック コミュニケーション系API編
小松 健作
秀和システム / 2730円 ( 2010-12 )


青い囲みの中にドラッグドロップするとアップロードされるが、ドラッグドロップAPIのためにスペースを用意するっていうのはなんかいまいちだなぁ。もうちょっと洗練されたドラッグドロップのインターフェースはないものかね。

file_upload

ディレクトリ構成

$ tree
.
├── static
│   └── uploads
├── templates
│   └── index.html
└── uploader.py

サーバー側

from flask import Flask, request, url_for, render_template, make_response
import os

DEBUG = True
SECRET_KEY = 'development key'
UPLOAD_FOLDER = 'static/uploads'
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'])

app = Flask(__name__)
app.config.from_object(__name__)

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS

@app.route('/')
def show_index():
    return render_template('index.html')

@app.route('/upload', methods=['POST'])
def do_upload():
    file = request.files['xhr2upload']
    if file and allowed_file(file.filename):
        filename = file.filename
        file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
    response = make_response(url_for('static', filename='uploads/'+filename, _external=True))
    response.headers['Access-Control-Allow-Origin'] = '*'
    return response

if __name__ == '__main__':
    app.run()

クライアント側(templates/index.html)

<!doctype html>
<html>
  <head>
  <meta charset="utf-8">
  <title>File Uploader</title>
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.js"></script>
  <style>
  #dropbox {
    width: 500px;
    height: 200px;
    border: 1px solid blue;
    background: #eee;
  }
  #urllists {
    margin-top: 30px;
    width: 400px;
    height: 300px;
    overflow: auto;
    floar: left;
    boader: 1px solid blue;
  }
  #currentimage {
    margin-left: 420px;
    margin-top: 30px;
  }
  </style>
  </head>
<body>
<h1>File Uploader</h1>
<div id=dropbox></div>
<div id=urllists></div>
<div id=currentimage></div>
<script>
var DnDUploader = function (base_id) {
  if(typeof(base_id) != "string" || base_id.length == 0 || document.getElementById(base_id) == null)
    return false;

  var __body = document.getElementsByTagName('body')[0];
  var parent = document.getElementById(base_id);
  __body.addEventListener("drop", function(e){e.stopPropagation();e.preventDefault();}, false);
  __body.addEventListener("dragenter", function(e){e.stopPropagation();e.preventDefault();}, false);
  __body.addEventListener("dragover", function(e){e.stopPropagation();e.preventDefault();}, false);
  parent.addEventListener("drop", function(e){e.stopPropagation();e.preventDefault();_handleDrop(e);}, false);
  parent.addEventListener("dragenter", function(e){e.stopPropagation();e.preventDefault();}, false);
  parent.addEventListener("dragover", function(e){e.stopPropagation();e.preventDefault();}, false);

  var _handleDrop = function(e) {
    var x = e.layerX, y = e.layerY;
    var dt = e.dataTransfer, files = dt.files, count = files.length;

    var types = [
            'image/png',
            'image/gif',
            'image/jpeg'
    ];

    for (var i=0; i < count; i++) {
    if (files[i].fileSize < 1048576) {
        var file = files[i];
        var type = file.type;
        var filename = file.fileName;

        if($.inArray(file.type, types) == -1) {
        alert(file.type + 'はサポート外です。');
        continue;
        }

        var reader = new FileReader();
        reader.readAsDataURL(file);
        _upload(file);

        reader.onload = function(e) {
        var fileData = e.target.result;
        _drawImage(x, y, fileData);
        }
    } else {
        alert('ファイルが大きすぎます');
    }
    }
  };

    var _drawImage = function(x, y, file) {
    var imgElement = document.createElement('img');
    imgElement.src = file;
    imgElement.style.position = 'absolute';
    imgElement.style.display = 'none';
    parent.appendChild(imgElement);

    setTimeout(function(e) {
        var o_w = imgElement.width;
        var o_h = imgElement.height;
        imgElement.width = o_w > 100 ? 100 : o_w;
        imgElement.height = parseInt( o_h * imgElement.width / o_w);

        var w = imgElement.width;
        var h = imgElement.height;
        imgElement.style.left = (x-w / 2)+'px';
        imgElement.style.top = (y-h / 2)+'px';
        imgElement.style.display = 'block';
    },1);
    };

    var _upload = function(file) {
    var fd = new FormData();
    fd.append("xhr2upload", file);
    var xhr = new XMLHttpRequest()
    xhr.open("POST", "http://www.kzfmix.com:5000/upload");
    xhr.send(fd);

    xhr.onload = function(e) {
        var url = e.target.responseText;
        $('#urllists').prepend('<p><a href="' + url + '">'+url+'</a></p>');
        $('#currentimage').html('<img src="' +url+ '">');
    }
    }
}

DnDUploader('dropbox');
</script>
</body>
</html>