2015/01/28
通常inputタグで「autocomplete="off"」とすると、自動入力が阻止できる。 ただChromeでは(バージョン 40.0.2214.93現在)この設定が反映されず自動入力されてしまい、思わぬトラブルになってしまう。 クライアント側のChrome設定で阻止するのも何だか。 力技ですが、HTMLにダミーのパスワードタグを記述しておくと回避できる模様。

<input id="user_password" name="user[new_password]" type="password" value="" autocomplete="off" >
<input id="user_password_dummy" type="password" value="" style="display:none" >

  2014/06/19
HTML5のグラフライブラリ「Flotr2」を使ってみる。 JavaScriptは「flotr2.min.js」を読み込み、表示する要素のあとにグラフ実行スクリプトを記述する。 ※データはあらかじめスクリプト等で、多次元配列を生成 ※getElementById()にidを指定 ※canvasを利用するので、グラフ表示幅、高さを指定

(function function_name(container, horizontal) { var graph = Flotr.draw(container, graph_data, {options}); })(document.getElementById(id));

HTML


<head>	
	<script type="text/javascript" src="jquery/jquery-1.7.2.min.js"></script>
	<script type="text/javascript" src="flotr2.min.js"></script>
	<style>
		.graph {
			margin: 5px;
			width: 400px;
			height: 200px;
		}
	</style>

	<script>
		var pie_values = [
		{data : [[0, 64800]], label : 'データ1'},
		{data : [[0, 712800]], label : 'データ2'},
		{data : [[0, 447120]], label : 'データ3'},
		{data : [[0, 231594]], label : 'データ4'},
		{data : [[0, 108000]], label : 'データ5'}
		];

		var bars_values = [
		{data : [[5, 32400],[4, 32400]], label : 'データ1'},
		{data : [[6, 237600],[5, 237600],[4, 237600]], label : 'データ2'},
		{data : [[6, 149040],[5, 149040],[4, 149040]], label : 'データ3'},
		{data : [[6, 77198],[5, 77198],[4, 77198]], label : 'データ4'},
		{data : [[5, 54000],[4, 54000]], label : 'データ5'}
		];

	</script>
</head>
<body>

	<div id="values1-graph" class="graph"></div>
	<div id="values2-graph" class="graph"></div>

	<script type="text/javascript" src="graph.js"></script>
</body>

graph.js


(function basic_pie(container) {
    var graph;

    graph = Flotr.draw(
        container,
        company_sales_graph_values,
        {
            HtmlText : false,
            grid : {
                verticalLines : false,
                horizontalLines : false
            },
            xaxis : { showLabels : false },
            yaxis : { showLabels : false },
            pie : {
                show : true, 
                explode : 6
            },
            mouse : { track : true },
            legend : {
                position : 'ne',
                backgroundColor : '#ffffff'
            }
        }
    );
})(document.getElementById("values1-graph"));

(function bars_stacked(container, horizontal) {
  var graph, i;

  graph = Flotr.draw(
    container,
    month_sales_graph_values,
    {
        legend : {
            backgroundColor : '#D2E8FF' // Light blue 
        },
    bars : {
        show : true,
        stacked : true,
        horizontal : horizontal,
        barWidth : 0.6,
        lineWidth : 1,
        shadowSize : 0
    },
    xaxis : {
        noTicks : 12,
        tickFormatter : function (n) {
            n = Math.round(n);
            return n + '月';
        },
        min: 1,
        max: 12 
    },
    mouse : { track : true },
    grid : {
      verticalLines : horizontal,
      horizontalLines : !horizontal
    },
    legend : {
        position : 'ne',
        backgroundColor : '#ffffff'
    }
  });
})(document.getElementById("values2-graph"));

グラフ種類

  • lines
  • bars
  • candles
  • pies
  • bubbles
  • radar

  2013/09/26
HTML5エキスパートで有名な吉川さん(同性w)からCodeIQの問題があったので挑戦! 「DOM操作の最適化によるJavaScriptチューニングにチャレンジ!

オリジナル


    var button = document.querySelector('button'),
        ul = document.querySelector('#output'),
        itemCount = 0;

    function addItems() {
      for ( var i = 0; i < 10; i++ ) {
        itemCount++;
        ul.innerHTML += '<li><article class="item">'
                      + '<h1 class="title">アイテム' + itemCount + '</h1>'
                      + '<p class="detail">詳細' + itemCount + '</p>'
                      + '</article></li>';
      }
    }
30分くらいでざっとコーディングして提出

提出コード


    var button = document.querySelector('button'),
        ul = document.getElementById('output'),
        itemId = 0;

    var itemTemplate = '';
    var addCount = 10;
    var output = document.getElementById("output");

    function createItem() {
        itemId++;
        var item = new Object();
        item.title = 'アイテム' + itemId;
        item.detail = '詳細' + itemId;
        return item;
    }

    function loadItemTemplate(item) {
        var li = document.createElement('li'); 
        var article = document.createElement('article');
        var h1 = document.createElement('h1');
        var p = document.createElement('p');

        article.setAttribute('class', 'item');
        h1.setAttribute('class', 'title');
        p.setAttribute('class', 'detail');

        h1.textContent = item.title;
        p.textContent = item.detail;

        article.appendChild(h1);
        article.appendChild(p);
        li.appendChild(article);
        return li;
    }

    function addItems() {
      for ( var i = 0; i < addCount; i++ ) {
        itemTemplate = loadItemTemplate(createItem());
        document.getElementById('output').appendChild(itemTemplate);
      }
    }
テンプレートのHTML生成がループしてるので無駄だなと思いつつ、この程度だと計測時間が変わらなかったのでとりあえず。 丁寧にアドバイスを頂きました。 - Document Fragmentを経由 - getElementById()は高コストなのでキャッシュする

提出コード


    var button = document.querySelector('button'),
        ul = document.getElementById('output'),
        itemId = 0;

    var template;
    var addCount = 10;
    var li;
    var article;
    var h1;
    var p;

    loadItemTemplate();

    function createItem() {
        itemId++;
        var item = new Object();
        item.title = 'アイテム' + itemId;
        item.detail = '詳細' + itemId;
        return item;
    }

    function loadItemTemplate() {
        template = document.createElement('li'); 
        article = document.createElement('article');
        h1 = document.createElement('h1');
        p = document.createElement('p');

        article.setAttribute('class', 'item');
        h1.setAttribute('class', 'title');
        p.setAttribute('class', 'detail');

        article.appendChild(h1);
        article.appendChild(p);
        template.appendChild(article);
    }

    function bindItem(item) {
        h1.textContent = item.title;
        p.textContent = item.detail;
        var itemRow = template.cloneNode(true);
        ul.appendChild(itemRow);
    }

    function addItems() {
      for ( var i = 0; i < addCount; i++ ) {
          bindItem(createItem());
      }
    }
cloneNode()を利用してみたけど、なんかViewの分離がちょっと汚くなっちゃたかな? insertNode()とかを使って、ツリーを操作した方がスムーズなのかも。

  2013/01/16
ROMEのデモサイトで、HTML5 x WebGLを使ってミュージックビデオを作ろうというプロジェクトらしいです。 ライブラリは「Three.js」をメインに使っている模様。 WEBGL EXAMPLESにいくつかのサンプルがあります。 これとか凄い質感。 ソースどうやって吐き出してるんだろうか? いちおう、サンプルコードは 3-dreams-of-blackからダウンロードできるみたいです。

  2012/09/03
3DやWebGLをネーティブでコーディイングするのはやっぱり大変! Flashだと「Alternativa3D」「 Away3D」「Papervision3D」らが有名ですが、JavaScriptの場合は「Three.js」「Sprite3D.js」「jQuery 3D」とかでしょうか? この中でも「Three.js」が一番強力そう(妄想)なので試してみる事に。

GitHub

GitHub mrdoob / three.js この中に「example」があるので動作確認できます。

ドキュメント

three.js THREE.js Doc 引数説明とサンプルがあるので、どういう動作するのかの材料になるかと。

使ってみる

ライブラリを読み込み

とりあえずメインの「three.js(three.min.js)」とパフォーマンス監視ツール「Stats.js」を読み込む

<script src="build/three.min.js"></script>
<script src="js/Stats.js"></script>

3D描画の土台

グラフィック描画するベースのhtml要素を追加し、JavaScriptで取得する。 ここまでは、何の知識もいらないかと。

<div id="container"></div>

var container;
container = document.getElementById('container');

Cameraの追加

3Dオブジェクトの視点であるCameraを追加するが、今回はOrthographicCamera()を利用する。

var left = window.innerWidth / - 2;
var right = window.innerWidth / 2;
var top = window.innerHeight / 2;
var bottom = window.innerHeight / - 2;
var camera = new THREE.OrthographicCamera(left, right, top, bottom, -2000, 1000);
camera.position.x = 200;
camera.position.y = 100;
camera.position.z = 200;
引数の内容は、

OrthographicCamera(left, right, top, bottom, near, far, projectionMatrix)
ちなみに、現在3種類のカメラがある。

・THREE.OrthographicCamera:平行投影(正投影) ・THREE.PerspectiveCamera:透視投影 ・THREE.CombinedCamera:透視投影と平行投影の複合

透視投影と平行投影の図的表現の違い

Sceneの追加

Sceneはグラフィックオブジェクトを配置する元のオブジェクトです。

scene = new THREE.Scene();

3Dオブジェクトの追加

Three.jsの3Dオブジェクトは以下のものがあります。

・THREE.CubeGeometry ・THREE.CylinderGeometry ・THREE.ExtrudeGeometry ・THREE.IcosahedronGeometry ・THREE.LatheGeometry ・THREE.OctahedronGeometry ・THREE.PlaneGeometry ・THREE.SphereGeometry ・THREE.TorusGeometry ・THREE.TorusKnotGeometry ・THREE.BinaryLoader ・THREE.UTF8Loader

だいたい名前で想像がつくが、今回は直方体の CubeGeometry を利用。 MeshLambertMaterial() で光反射のマテリアルを作成。 元の3Dオブジェクトとマテリアルを引数に、Mesh()でCubeオブジェクトを作成し、Sceneに追加します。 (Three.jsの場合、Cubeオブジェクトというよりメッシュと言った方が通じるか?)

var geometry = new THREE.CubeGeometry(50, 50, 50);
var params =  {
    color: 0xffffff,
    shading: THREE.FlatShading,
    overdraw: true
};
var material = new THREE.MeshLambertMaterial(params);
var cube = new THREE.Mesh(geometry, material);
cube.scale.y = Math.floor(Math.random() * 2 + 1);
cube.position.x = Math.floor((Math.random() * 1000 - 500) / 50) * 50 + 25;
cube.position.y = (cube.scale.y * 50) / 2;
cube.position.z = Math.floor((Math.random() * 1000 - 500) / 50) * 50 + 25;
scene.add(cube);

SceneにLightを追加

Lightを追加する事で、3Dに影をつけて奥行き感を出します。

var directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.x = 0.5;
directionalLight.position.y = 1.5;
directionalLight.position.z = 3.5;
directionalLight.position.normalize();
scene.add(directionalLight);

var ambientLight = new THREE.AmbientLight(0x10);
scene.add(ambientLight);
Lightには以下のものがある。

・THREE.AmbientLight ・THREE.DirectionalLight ・THREE.PointLight ・THREE.SpotLight

どう違うかは、後に調べてみよう。。。

レンダリングする

Renderer系には以下の種類があるようだが、今回は無難に CanvasRenderer を利用する。

・CanvasRenderer ・WebGLRenderer ・DOMRenderer ・SVGRenderer

CanvasRenderer.domElement をcontainer(HTML要素)に追加後、Scene と Camera をレンダリングする。

renderer = new THREE.CanvasRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
renderer.render(scene, camera);
とりあえず3D静止オブジェクトが描画される。

アニメーションさせる

アニメーションさせる場合は requestAnimationFrame() で時間軸をつけてやる。

function animate() {
    requestAnimationFrame(animate);
    render();
}

function render() {
    var timer = Date.now() * 0.0001;
    camera.position.x = Math.cos(timer) * 200;
    camera.position.z = Math.sin(timer) * 200;
    camera.lookAt(scene.position);
    renderer.render(scene, camera);
}
animate() でrequestAnimationFrame()を連続で呼び、render()で状態に応じてレンダリング処理している。

Demo・サンプルソース

Demo

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Cube Sample</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
        <style>
            body {
                font-family: Monospace;
                background-color: #f0f0f0;
                margin: 0px;
                overflow: hidden;
            }
        </style>
    </head>
    <body>

        <div id="container"></div>

        <script src="build/three.min.js"></script>
        <script src="js/Stats.js"></script>

        <script>
            var container, stats;
            var camera, scene, renderer;

            init();
            animate();

            function init() {
                container = document.getElementById('container');

                addCamera();
                addSecne();
                addGrid();
                addMaterial();
                addLight();
                addRenderer();
                //addStatus();

                window.addEventListener('resize', onWindowResize, false);
            }

            function addCamera() {
                var left = window.innerWidth / -2;
                var right = window.innerWidth / 2;
                var top = window.innerHeight / 2;
                var bottom = window.innerHeight / -2;

                camera = new THREE.OrthographicCamera(left, right, top, bottom, -2000, 1000);
                camera.position.x = 200;
                camera.position.y = 100;
                camera.position.z = 200;
            }

            function addSecne() {
                scene = new THREE.Scene();
            }

             function addGrid () {
                var geometry = new THREE.Geometry();
                geometry.vertices.push( new THREE.Vector3(-500, 0, 0 ));
                geometry.vertices.push( new THREE.Vector3(500, 0, 0));

                for ( var i = 0; i <= 20; i ++ ) {
                    var parameters = { color: 0x000000, opacity: 0.2 };
                    var line = new THREE.Line(geometry, new THREE.LineBasicMaterial(parameters));
                    line.position.z = ( i * 50 ) - 500;
                    scene.add( line );

                    var line = new THREE.Line(geometry, new THREE.LineBasicMaterial(parameters));
                    line.position.x = ( i * 50 ) - 500;
                    line.rotation.y = 90 * Math.PI / 180;
                    scene.add( line );
                }
            }

            function addMaterial () {
                var geometry = new THREE.CubeGeometry( 50, 50, 50 );
                var material = new THREE.MeshLambertMaterial( { color: 0xffffff, shading: THREE.FlatShading, overdraw: true } );

                for ( var i = 0; i < 100; i ++ ) {
                    var cube = new THREE.Mesh( geometry, material );
                    cube.scale.y = Math.floor( Math.random() * 2 + 1 );
                    cube.position.x = Math.floor( ( Math.random() * 1000 - 500 ) / 50 ) * 50 + 25;
                    cube.position.y = (cube.scale.y * 50) / 2;
                    cube.position.z = Math.floor( ( Math.random() * 1000 - 500 ) / 50 ) * 50 + 25;
                    scene.add( cube );
                }
            }

            function addLight () {
                var directionalLight = new THREE.DirectionalLight(0xffffff);
                directionalLight.position.x = 0.5;
                directionalLight.position.y = 1.5;
                directionalLight.position.z = 3.5;
                directionalLight.position.normalize();
                scene.add(directionalLight);

                var directionalLight = new THREE.DirectionalLight(0xcccccc);
                directionalLight.position.x = 0.5;
                directionalLight.position.y = 1.5;
                directionalLight.position.z = 3.5;
                directionalLight.position.normalize();
                scene.add(directionalLight );

                var ambientLight = new THREE.AmbientLight(0x10);
                scene.add(ambientLight);
            }

            function addRenderer () {
                renderer = new THREE.CanvasRenderer();
                renderer.setSize( window.innerWidth, window.innerHeight );
                container.appendChild(renderer.domElement);
            }

            function addStatus() {
                stats = new Stats();
                stats.domElement.style.position = 'absolute';
                stats.domElement.style.top = '0px';
                container.appendChild(stats.domElement);
            }

            function onWindowResize() {
                camera.left = window.innerWidth / - 2;
                camera.right = window.innerWidth / 2;
                camera.top = window.innerHeight / 2;
                camera.bottom = window.innerHeight / - 2;
                camera.updateProjectionMatrix();
                renderer.setSize( window.innerWidth, window.innerHeight );
            }

            function animate() {
                requestAnimationFrame( animate );
                render();
                stats.update();
            }

            function render() {
                var timer = Date.now() * 0.0001;
                camera.position.x = Math.cos(timer) * 200;
                camera.position.y = Math.sin(timer) * 200;
                //camera.position.z = Math.sin(timer) * 200;
                camera.lookAt(scene.position);
                renderer.render(scene, camera);
            }

        </script>

    </body>
</html>
Chrome環境で、テクスチャーをつけてないので結構スムーズに動きます。 何となく、Papervision3Dに近い気がしました。 ただ、これだけのサンプルだと何のイベントもないので「で?」ですねw 次は、イベント使ったサンプルを調べてみよう。

メモ:モデル

iClone Real-time Filmmaking

  2012/08/24
HTML5 Filesystem APIと「input type="file"」利用してドラッグ&ドロップを実現するサンプル input[type="file"]とFileSystem APIを連携する方法

  2012/07/08
フロントエンドエンジニアのためのブラウザ上でHTML5コーディング・実行・共有できるサービス一覧 JS do JS Fiddle JS bin Dabllet Thimble Fiddlesalad Codepen Adobeオープンソース「Brackets」 とりあえず、投稿されたサンプルを観てるだけでも参考になりますね。

  2012/07/08
最近、HTML5を高速化する方法が流行ってますね。 HTML5でアプリ!と言ってもやはりネイティブに比べると格段に遅いです。 とくに相対的にスマホやタブレットアプリの処理では顕著だと思います。 ブラウザベースなので、基本どうやってもネイティブには勝てないと思いますが、それでも現状より速くする手法は色々ありますよね。 サイバーエージェントの中の人、「HTML5 Web Applicationのつくりかた」の記事も参考にちょっとメモしてみました。

小さな画像はbase64で直接埋め込み

小さな画像はCSSに直接画像をbase64で埋め込む。

<img src="data:image/png;base64,AjKCLokX....">
みたいな 画像をbase64に変換するには、プログラミングするもよし、ツールを使うもよし。 ちなみにPHPだったら、
<?php
$img = file_get_contents( '画像URL' );
if ( $img !== false ) {
    $img = base64_encode( $img );
}
?>

CSS Sprite

いわゆる1枚画像で座標を指定して、画像をパーツを表示する手法 ゲームのテクスチャでよく使われる手法ですね。 ちなみに、Adobe Fireworks CS6からは標準で書き出し機能が搭載されました。 (それ以前は機能拡張で対応) CSSスプライト書き出し機能の使い方

Canvasタグ

これは言わずもがな。 ただ、高機能な分面倒かな?と

<canvas id="sample" ext="jpg"></canvas>

var ctx = canvas.getContext('2d');
var img = new Image();
img.src = '画像URL';
$("#sample").attr('width', img.width);
$("#sample").attr('height', img.height);
ctx.drawImage(img, 0, 0, img.width, img.height);
※jQuery利用 画像サイズを取得して、Contextに描画する際にサイズ指定します。 事前にサイズがわかってる場合はCanvasにサイズ指定すればいいですが、それってどうよ?と個人的には思います。

SVG(AiファイルをCanvasに埋め込む)

MacBookPro Retinaの登場によりこれから、高解像度にも柔軟に対応する必要がでてきました。 そこで登場するのが恐らくSVGの技術かと。 Ai→Canvasっていうプラグインを使うと、ベジェ曲線とかパス情報データを書き出してくれます。 で、これをCanvas の Context に直接わりあてる何とも合理的な方法です。

JSON x gzip圧縮

転送データをJSONにしたり、圧縮をかける事によりデータ転送を減らすようにしてます。 (流石はソーシャルの中の人) gzip転送する場合は、Apacheで mod_deflat を有効にする必要があります。 まぁ、普通のサービス運営ではここまでする機会はないとは思いますが、知っておく知識ではありますね。

CSS拡張のメタ言語Sass

SassはCSSを拡張して、効率よくコーディングできるメタ言語です。 ※「Sassを覚えよう!」、「Sass、そしてSassy CSS (SCSS)」などを参考 環境構築は「Scout」を利用します。 OSX専用なら「Codekit」ってのもあります。 Sassは、それだけでトピックが長くなりそうなので割愛(と言うか勉強中)

PNG画像最適化

OptiPNGで必要の無い情報を削除し、画像容量を軽量化します。 画像数が多い場合には有利。

window.onhashchange

ちょっと高速化から話がずれますが、ブラウザ上でローカル処理をするとURLリンクが活用できません。 window.onhashchange を利用してページ遷移の履歴みたいに利用します。

http://hoge.com/page1#1

みたいな。 これでネット検索でアクセスした時に同じ結果を出す事ができます。

改行、空白などを削除

これも画像とは関係ないですが、HTMLの軽量化になるかと。 ただファイルアップする度にやる必要があるので、自動化する仕組みを作っておかないと忘れがちな作業ではありますが・・・。
<< Top < Prev Next > Last >>