HTML5 による描画のテスト

プログラム

    var context=canvas.getContext('2d');
    context.fillRect(20,40,50,100);    左側の黒長方形
    context.strokeStyle='rgb(00,00,255)'; 線は青
    context.fillStyle='rgb(255,00,00)';   赤で塗りつぶす
    context.strokeRect(200,80,100,50);  右側の長方形枠
    context.arc(150,75,60,Math.P
I*1,Math.PI*2,true); 中央の半円
    context.fill();

 HTML5では、canvas タグの中で、描画を行なうことができる。
(1)二次元描画
 var context=canvas.getContext('2d');
(2)三次元描画
 var context=canvas.getContext('webgl');
 var context=canvas.getContext('webgl2');
(3)その他
 getContext( contextId ) で、
  contexId が空ならNULLを返す
  ユーザーエージェントがサポートしない場合NULLを返す
  ブラウザベンダーは、実験的なコンテキストを定義できる。
  構文:moz-3dのようにvendername-context
 ブラウザ対応状況:
 Firefox 2-, Safari 2-, Chrome 1-, Opera 9.2-, IE 9.- ExplorerCanvas 0002-

2d

長方形、円弧などの基本的などを組み合わせて図形を定義する
var context=canvas.getContext('2d');
context.fillRect(20,40,50,100);

 canvas 2d でできること
 四角形を描画する c.fillRect
 四角形を線画する c.strokeRect
 直線を描画する
 折れ線を描画する
 多角形を描画する
 beginPath()で開始、プロッタ風に moveTo(x,y) とlineTo(x,y)で形状指定 endPath()で閉じ, stroke()で描画
 ベジェ曲線を描画する
 円/円弧を描画する
 arc(x,y,r,startAngle,endAngle,anticlockwise); で形状定義、fill()またはstroke()で描画
 直線から連なる円弧を描画する
 線のスタイルを設定する
 角の形状を設定する
詳細
表示領域と描画領域
(1)<canvas width="200" height="100></canvas>
 描画領域が200x100となり、同じサイズの領域が表示される。
(2)<canvas style="width:200px;height:100px"></canvas>
描画領域を指定しなかった場合、規定値は300×150
 (2)→styleで表示領域のサイズは変更されるが描画領域には反映されず、
 300x150の描画領域に描かれたグラフィクスが拡大縮小される。
(3)<canvas style="width:100%"></canvas>
300x150の描画領域に描かれた結果をウィンドウ幅に拡大縮小して表示する。
描画処理に先立って
canvas.width=canvas.offsetWidth;
を実行することにより、描画領域のサイズをその要素の表示領域のサイズに一致させる。
(4)実例
(5)フーリエ変換の結果グラフを自動生成した例→1→2

webgl

GLを用いて三次元表示を行なう
main関数から始まる二つのシェーダ(テキスト)を定義する
IE11では未対応だが、getContext('experimental-webgl')で通る
"> document.addEventListener('DOMContentLoaded', function(event){
 /**
 * Inits the WebGL or returns false if it couldn't be loaded.
 */
 function getWebGL(){
  var canvas = document.getElementById('canvas');
//  var canvas = document.querySelector("#canvas");
  var webgl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
  if(!webgl || !(webgl instanceof WebGLRenderingContext)){
   return false;
  }
  return webgl;
 }
width="800px"  /**
  * Creates the vertex buffer, binds it, passes the vortex data to it,
  * and sets the color.
  */
 function initWebGL(webgl, vortexes){
  var vertexBuffer = webgl.createBuffer();
  webgl.bindBuffer(webgl.ARRAY_BUFFER, vertexBuffer);
  webgl.bufferData(
   webgl.ARRAY_BUFFER,
   new Float32Array(vortexes),
   webgl.STATIC_DRAW
  );
  webgl.clearColor(0, 0.5, 0.5, 0.9);
  webgl.clear(webgl.COLOR_BUFFER_BIT);
 }
 /**
  * Creates the vertex shader object frwidth="800px" om the source code defined in
  * 2_vertex_shader.js.
  */
  function createVertexShader(){
   var vertexShader = webgl.createShader(webgl.VERTEX_SHADER);
   webgl.shaderSource(vertexShader, vertexCode);
   webgl.compileShader(vertexShader);
   return vertexShader;
  }
  /**
  * Creates the fragment shader object from the source code defined in
  * 2_vertex_shader.js.
  */
 function createFragmentShader(){
  var fragmentShader = webgl.createShader(webgl.FRAGMENT_SHADER);
  webgl.shaderSource(fragmentShader, fragmentCode);
  webgl.compileShader(fragmentShader);
  return fragmentShader;
 }
 /**
  * Create and attach eht shader programs from the shader compiled objects.
  */
 function createShaderProgram(webgl, vertexShader, fragmentShader){
  var shaderProgram = webgl.createProgram();
  webgl.attachShader(shaderProgram, vertexShader);
  webgl.attachShader(shaderProgram, fragmentShader);
  webgl.linkProgram(shaderProgram);
  webgl.useProgram(shaderProgram);
  return shaderProgram;
 }
 /**
  * Gets and sets the coordinates associating the compiled shader pgograms
  * to buffer objects.
width="800px"   */
 function transformCoordinatesAndSet(webgl, shaderProgram){
  var coordinates = webgl.getAttribLocation(
   shaderProgram,
   'coordinates'
  );
  webgl.vertexAttribPointer(
   coordinates,
   2,
   webgl.FLOAT,
   false,
   0,
   0
  );
  webgl.enableVertexAttribArray(coordinates);
 }
 /**
  * Draws the arrays.
  */
 function drawArrays(webgl){
  webgl.drawArrays(webgl.TRIANGLES, 0, 3);
 }
 var vortexes = [0.8, 0.0, 0.0, 1, 1, 0.8];
 webgl = getWebGL();
 if(webgl){
  initWebGL(webgl, vortexes);
  var vertexShader = createVertexShader();
  var fragmentShader = createFragmentShader();
  var shaderProgram = createShaderProgram(webgl, vertexShader, fragmentShader);
  transformCoordinatesAndSet(webgl, shaderProgram);
  drawArrays(webgl);
 }
});

THREE

 THREEライブラリを通して、webgl表示を行なう
window.addEventListener("DOMContentLoaded",init);
function init(){
  const width = 960;
  const height = 540;
  const renderer = new THREE.WebGLRenderer({
   canvas: document.querySelector("#myCanvas") //id="myCanvas"
  });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(width,height);
  const scene = new THREE.Scene();
  const camera = new THREE.PerspectiveCamera( 45, width/height, 1, 10000);
  camera.position.set(0,0,+1000);
  const geometry = new THREE.BoxGeometry(500,500,500);
  const material = new THREE.MeshStandardMaterial({ color: 0x0000ff });
  const box = new THREE.Mesh(geometry, material);
  scene.add(box);
  const directionalLight = new THREE.DirectionalLight(0xffffff);
  directionalLight.position.set(1,1,1);
  //light.intensity = 2;
  scene.add(directionalLight);
  //light.posision.set(1,1,1);
  renderer.render(scene, camera);
}

試行例

2d
 canvas タグを用いた単純な図形(矩形、円弧)の表示canvas.htm(直接記述)
 canvas を複数並べた例canvas2d.htm(直接記述)
webgl
 タグの取得結果のテストcanvas3d.htm(直接書込)
 webglを用いた三角形表示canvas0.htm(2_webgl.js, 2_fragment_shader.js, 2_vertex_shader.js)
THREE
 動画表示未完成canvas03.htm(3_three.js, three.js)
 静止画表示完動T1.htm(T1.js, three.js)
 動作表示完動T2.htm(T2.js, three.js)

BRLトップページへの実装

 トップマトリクス 上段:表題、中段:章構成、下段:canvasテスト表示
 canvasテスト表示の構成:
1.左('yourCanvas')
 全てindex.htmlの中で完結
 sample 関数を、ヘッダーの中で定義
 でロード時に起動
2.中('ourCanvas')
 tableS.jsの中で定義
 インクルードされた時点で、
  document.addEventListener('DOMContentLoaded',function(event){  });
  で実行。処理内容は、直接定義
3.右('myCanvas')
 tableS.jsの中で定義
 インクルードされた時点で、
 window.addEventListener('DOMContentLoaded',init);
 で実行。処理内容は、init()関数の中で定義

1の処理内容
    function sample(){
     var canvas=document.getElementById('yourCanvas');
     if(canvas.getContext){
        var context=canvas.getContext('2d');
        context.fillRect(4,8,10,20);
        context.strokeStyle='rgb(00,00,255)';
        context.fillStyle='rgb(00,255,00)';
        context.strokeRect(30,20,20,10);
        context.arc(30,45,12,Math.PI*1,Math.PI*2,true);
        context.fill();
      }
    }
2の処理内容
//関数定義
  function getWebGL(){
    var canvas = document.getElementById('ourCanvas');
//    var canvas = document.querySelector("#canvas");
    var webgl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
    if(!webgl || !(webgl instanceof WebGLRenderingContext)){
      return false;
    }
    return webgl;
  }
  /**
   * Creates the vertex buffer, binds it, passes the vortex data to it,
   * and sets the color.
   */
  function initWebGL(webgl, vortexes){
    var vertexBuffer = webgl.createBuffer();
    webgl.bindBuffer(webgl.ARRAY_BUFFER, vertexBuffer);
    webgl.bufferData(
      webgl.ARRAY_BUFFER,
      new Float32Array(vortexes),
      webgl.STATIC_DRAW
    );
    webgl.clearColor(0, 0.5, 0.5, 0.9);
    webgl.clear(webgl.COLOR_BUFFER_BIT);
  }
  /**
   * Creates the vertex shader object from the source code defined in 
   * 2_vertex_shader.js.
   */
   function createVertexShader(){
     var vertexShader = webgl.createShader(webgl.VERTEX_SHADER);
     webgl.shaderSource(vertexShader, vertexCode);
     webgl.compileShader(vertexShader);
     return vertexShader;
   }
   /**
    * Creates the fragment shader object from the source code defined in
    * 2_vertex_shader.js.
    */
  function createFragmentShader(){
    var fragmentShader = webgl.createShader(webgl.FRAGMENT_SHADER);
    webgl.shaderSource(fragmentShader, fragmentCode);
    webgl.compileShader(fragmentShader);
    return fragmentShader;
  }
  /**
   * Create and attach eht shader programs from the shader compiled objects.
   */
  function createShaderProgram(webgl, vertexShader, fragmentShader){
    var shaderProgram = webgl.createProgram();
    webgl.attachShader(shaderProgram, vertexShader);
    webgl.attachShader(shaderProgram, fragmentShader);
    webgl.linkProgram(shaderProgram);
    webgl.useProgram(shaderProgram);
    return shaderProgram;
  }
  /**
   * Gets and sets the coordinates associating the compiled shader pgograms
   * to buffer objects.
   */
  function transformCoordinatesAndSet(webgl, shaderProgram){
    var coordinates = webgl.getAttribLocation(
      shaderProgram,
      'coordinates'
    );
    webgl.vertexAttribPointer(
      coordinates,
      2,
      webgl.FLOAT,
      false,
      0,
      0
    );
    webgl.enableVertexAttribArray(coordinates);
  }
  /**
   * Draws the arrays.
   */
  function drawArrays(webgl){
    webgl.drawArrays(webgl.TRIANGLES, 0, 3);
  }

//本体
  var vortexes = [0.8, 0.0, 0.0, 1, 1, 0.8];
  webgl = getWebGL();
  if(webgl){
    initWebGL(webgl, vortexes);
    var vertexShader = createVertexShader();
    var fragmentShader = createFragmentShader();
    var shaderProgram = createShaderProgram(webgl, vertexShader, fragmentShader);
    transformCoordinatesAndSet(webgl, shaderProgram);
    drawArrays(webgl);
  }

3.three.js で定義された関数を参照している。
function init(){
//    const width = 900;
//    const height = 540;
    const width = 60;
    const height = 60;//過大にすると桝が縦長になる
    const renderer = new THREE.WebGLRenderer({
      canvas: document.querySelector("#myCanvas")
    });
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(width,height);
    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera( 45, width/height, 1, 10000);
    camera.position.set(0,0,+1000);
    const geometry = new THREE.BoxGeometry(500,500,500);
    const material = new THREE.MeshStandardMaterial({ color: 0x0000ff });
    const box = new THREE.Mesh(geometry, material);
    scene.add(box);
    const directionalLight = new THREE.DirectionalLight(0xffffff);
    directionalLight.intensity = 2;
    directionalLight.position.set(1,1,1);
    scene.add(directionalLight);
    
    tick();
    
    function tick(){
      requestAnimationFrame(tick);
      box.rotation.x += 0.01;
      box.rotation.y += 0.01;
      renderer.render(scene, camera);
    }
}

イベント'DOMContentLoaded'
HTML5で定義
DOMツリーの構築が完了したことを判定する
但し、scriptの実行を待つ(例えばdocument.writeの結果)
scriptはstylesheetの解析を待つ

HTMLコンテンツがロードされ、そこから参照される画像などがロードされる前のタイミングで
実行したい処理を記述する方法として、
(1) 
(2) 
(3)  の直前に

window と document のどちらにも登録することができる。

イベント'load'は画像含め全てがロードされた後にトリガー
windowに対してのみ登録でき、documentには登録できない。
window.addEventListener('load',…)
画像を含む

canvasの位置指定

 table の td の升目の中にcanvasを配置する場合に、スタイルシートで、
style="margin: 上px 右px 下px 左px"
 または、
style="margin-top:20px”
 のように指定する。

文字の影付け

 文字を立体的に表示するために、style の中で"text-shadow: ..."を指定している。
・文字から下方に1ドットづつ、ゴーストを付けて立体化している。 ・文字から下方に、拡散する黒い影を付けている。
   text-shadow:
 0 1px 0 #ccc,
    0 2px 0 #c9c9c9,
    0 3px 0 #bbb,
    0 4px 0 #b9b9b9,
    0 5px 0 #aaa,
    0 6px 1px rgba(0,0,0,.1),
    0 0 5px rgba(0,0,0,.1),
    0 1px 3px rgba(0,0,0,.3),
    0 3px 5px rgba(0,0,0,.2),
    0 5px 10px rgba(0,0,0,.25),
    0 10px 10px rgba(0,0,0,2),
    0 20px 20px rgba(0,0,0,.25) }