Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Web Graphics of the present time,
and the near future

yomotsu
April 11, 2015

Web Graphics of the present time,
and the near future

yomotsu

April 11, 2015
Tweet

More Decks by yomotsu

Other Decks in Design

Transcript

  1. Web Graphics of the present time,
 and the near future

    Presented by Akihiro Oyamada (@yomotsu) 
 at WCAN on 11th Apr, 2015
  2. Windows Vista IE 9 - Windows 7 IE 11 -

    Windows 8.1 IE 11 - Windows 10 Spartan ( IE11 )
  3. 1. SVG with SnapSVG 2. Canvas with EaselJS 3. WebGL

    with pixi.js and three.js 4. WebVR
  4. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>=^.^=</title> </head> <body> !

    <button>Animate it!</button> ! <svg class="pathAnim2" width="512" height="300" viewBox="0 0 512 300"> <path d="M12.5,130c0,0,46.5-60.5,172-60.5S333,...." fill="none" stroke="#ffffff" stroke-opacity="0.5" strokeMiterLimit="10" stroke-width="4" stroke-dasharray="12, 6"
  5. ! <button>Animate it!</button> ! <svg class="pathAnim2" width="512" height="300" viewBox="0 0

    512 300"> <path d="M12.5,130c0,0,46.5-60.5,172-60.5S333,...." fill="none" stroke="#ffffff" stroke-opacity="0.5" strokeMiterLimit="10" stroke-width="4" stroke-dasharray="12, 6" stroke-dashoffset="100"/> <image xlink:href="truck.svg" width="128" height="128"> </svg> ! ! <script src="./lib/snap.svg-min.js"></script> class attribute guide path moving object
  6. ! ! <script src="./lib/snap.svg-min.js"></script> <script> ! var pathAnim = Snap(

    '.pathAnim2' ); var path = pathAnim.select( 'path' ); var truck = pathAnim.select( 'image' ); var pathLength = path.getTotalLength(); var duration = 5000; ! var playAnim = function () { ! Snap.animate( 0, 1, function( progress ) { ! var movePoint = path.getPointAtLength( pathLength * progress ); ! truck.transform( 't' + ( movePoint.x - 64 ) + ',' +
  7. var pathLength = path.getTotalLength(); var duration = 5000; ! var

    playAnim = function () { ! Snap.animate( 0, 1, function( progress ) { ! var movePoint = path.getPointAtLength( pathLength * progress ); ! truck.transform( 't' + ( movePoint.x - 64 ) + ',' + ( movePoint.y - 64 ) + 'r' + ( movePoint.alpha - 180 ) ); ! }, duration, mina.easeinout ); ! }; ! playAnim();
  8. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>=^.^=</title> </head> <body> !

    <svg width="128" height="128" viewBox="0 0 64 64" class="octoIcon"> ! <defs> ! <path class="default" d="M11.2,37.6c-0.1-...."/> <path class="hover" d="M7,39.8c0,0-0.1-0..."/> ! </defs> ! <path fill="#fff" class="main"/>
  9. </head> <body> ! <svg width="128" height="128" viewBox="0 0 64 64"

    class="octoIcon"> ! <defs> ! <path class="default" d="M11.2,37.6c-0.1-...."/> <path class="hover" d="M7,39.8c0,0-0.1-0..."/> ! </defs> ! <path fill="#fff" class="main"/> ! </svg> ! ! <script src="./lib/snap.svg-min.js"></script> <script> !
  10. <path fill="#fff" class="main"/> ! </svg> ! ! <script src="./lib/snap.svg-min.js"></script> <script>

    ! var icon = Snap( document.querySelector( '.octoIcon' ) ); var pathMain =icon.select('.main'); var pathDefault=icon.select('.default').attr('d'); var pathHover =icon.select(‘.hover').attr('d'); ! pathMain.attr( 'd', pathDefault ); ! icon.node.addEventListener('mouseover',function(){ ! pathMain.animate( { d: pathHover
  11. pathMain.attr( 'd', pathDefault ); ! icon.node.addEventListener('mouseover',function(){ ! pathMain.animate( { d:

    pathHover }, 500, mina.bounce ); ! }); ! icon.node.addEventListener('mouseout',function(){ ! pathMain.animate( { d: pathDefault }, 500, mina.bounce ); ! }); ! </script> !
  12. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>=^.^=</title> </head> <body> !

    <svg class="graph" width="800" height="480" viewBox="0 0 800 480"></svg> ! ! <script src="./lib/snap.svg-min.js"></script> <script src="./lib/underscore-min.js"></script> <script> // // snapsvg ʹ΋؆୯ͳςϯϓϨʔτߏจΛαϙʔτ͍ͯ͠Δ͕ػ ೳ͸͔ͳΓগͳ͍ //
  13. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>=^.^=</title> </head> <body> !

    <svg class="graph" width="800" height="480" viewBox="0 0 800 480"></svg> ! ! <script src="./lib/snap.svg-min.js"></script> <script src="./lib/underscore-min.js"></script> <script> // // snapsvg ʹ΋؆୯ͳςϯϓϨʔτߏจΛαϙʔτ͍ͯ͠Δ͕ػ ೳ͸͔ͳΓগͳ͍ //
  14. } ! var template = _.template( [ '<% var gridBottom

    = ( data.cellLength.y - 1 ) * data.cellSize.height + data.cellOffset.y; %>', '<g class=“grid">', ! // grid holizontal '<% for ( var i = 0, l = data.cellLength.y; i < l; i ++ ) { %>’, ! '<% var x1 = data.cellOffset.x - 20; %>', '<% var y1 = data.cellOffset.y + data.cellSize.height * i; %>', '<% var x2 = data.cellOffset.x + data.cellSize.width * ( data.cellLength.x - 1 ); %>', '<% var y2 = y1; %>', '<line x1="<%= x1 %>" y1="<%= y1 %>" x2="<%= x2 %>" y2="<%= y2 %>" stroke="#ffffff" stroke- dasharray="6, 6" stroke-width="2"/>', '<text x="<%= x1 - 10 %>" y="<%= y1 %>" font-
  15. ].join( '\n' ) ); ! ! ! var svgSource =

    template( { data: data } ); var svgDOM = Snap.parse( svgSource ); graph.append( svgDOM ); ! ! var point = graph.selectAll( '.point' ); var points = graph.selectAll( '.points' ); var surface = graph.select( '.surface' ); ! _.each( point, function ( el ) { ! var mat1 = new Snap.Matrix(); var mat2 = new Snap.Matrix(); ! mat1.translate( +el.attr( 'data-cx1' ), +el.attr( 'data-cy1' ) );
  16. • K2VFSZͷΑ͏ͳ47(%0.ૢ࡞
 SVG DOM manipulation, like jQuery • Ξχϝʔγϣϯ
 Animations

    • ςϯϓϨʔτల։
 Templating • "KBYʹΑΔ֎෦47(ಡΈࠐΈ
 Import external SVG file with Ajax • 47(ಠࣗػೳͷαϙʔτ
 SVG features support, like masking, clipping, patterns etc...
  17. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>=^.^=</title> </head> <body> !

    <canvas width="640" height="360" id=“myCanvas"> </canvas> ! <script src=“./lib/createjs-2014.12.12.min.js"> </script> <script> ! var canvas = document.querySelector( '#myCanvas' ); var stage = new createjs.Stage( canvas ); !
  18. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>=^.^=</title> </head> <body> !

    <canvas width="640" height="360" id=“myCanvas"> </canvas> ! <script src=“./lib/createjs-2014.12.12.min.js"> </script> <script> ! var canvas = document.querySelector( '#myCanvas' ); var stage = new createjs.Stage( canvas ); ! make a canvas element
  19. <meta charset="utf-8"> <title>=^.^=</title> </head> <body> ! <canvas width="640" height="360" id=“myCanvas">

    </canvas> ! <script src=“./lib/createjs-2014.12.12.min.js"> </script> <script> ! var canvas = document.querySelector( '#myCanvas' ); var stage = new createjs.Stage( canvas ); ! var robot = new createjs.Bitmap( './img/ craftybot.png' ); robot.set( { x: 200, y: 100 load create.js
  20. <canvas width="640" height="360" id=“myCanvas"> </canvas> ! <script src=“./lib/createjs-2014.12.12.min.js"> </script> <script>

    ! var canvas = document.querySelector( '#myCanvas' ); var stage = new createjs.Stage( canvas ); ! var robot = new createjs.Bitmap( './img/ craftybot.png' ); robot.set( { x: 200, y: 100 } ); stage.addChild( robot ); ! var update = function() { make a stage
  21. </script> <script> ! var canvas = document.querySelector( '#myCanvas' ); var

    stage = new createjs.Stage( canvas ); ! var robot = new createjs.Bitmap( './img/ craftybot.png' ); robot.set( { x: 200, y: 100 } ); stage.addChild( robot ); ! var update = function() { ! stage.update(); ! } make a display object
  22. var canvas = document.querySelector( '#myCanvas' ); var stage = new

    createjs.Stage( canvas ); ! var robot = new createjs.Bitmap( './img/ craftybot.png' ); robot.set( { x: 200, y: 100 } ); stage.addChild( robot ); ! var update = function() { ! stage.update(); ! } ! createjs.Ticker.setFPS( 60 ); createjs.Ticker.addEventListener( 'tick', update ); add to the stage
  23. craftybot.png' ); robot.set( { x: 200, y: 100 } );

    stage.addChild( robot ); ! var update = function() { ! stage.update(); ! } ! createjs.Ticker.setFPS( 60 ); createjs.Ticker.addEventListener( 'tick', update ); </script> ! </body> </html> update to render
  24. • อ࣋Ϟʔυ"1*ͷΑ͏ͳɺ
 ΦϒδΣΫτ؅ཧ
 Specific objects management, like retained mode APIs

     • 4QSJUF΍4QJOFͷΞχϝʔγϣϯ
 Sprite and Spine animations  • ϐΫηϧૢ࡞΍جຊతͳϑΟϧλʔ
 Pixel manipulation and basic filters  • Ϛ΢εͱλονΠϕϯτ
 Mouse and touch events
  25. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>=^.^=</title> </head> <body> !

    <script src="./lib/pixi.js"></script> ! <script> var renderer=new PIXI.autoDetectRenderer(640,360); document.body.appendChild( renderer.view ); ! var stage = new PIXI.Stage( 0xffffff ); ! var robot = new PIXI.Sprite.fromImage( './img/ craftybot.png' ); robot.position.set( 200, 100 );
  26. <html> <head> <meta charset="utf-8"> <title>=^.^=</title> </head> <body> ! <script src="./lib/pixi.js"></script>

    ! <script> var renderer=new PIXI.autoDetectRenderer(640,360); document.body.appendChild( renderer.view ); ! var stage = new PIXI.Stage( 0xffffff ); ! var robot = new PIXI.Sprite.fromImage( './img/ craftybot.png' ); robot.position.set( 200, 100 ); stage.addChild( robot ); ! ( function animate() { load pixi.js
  27. <title>=^.^=</title> </head> <body> ! <script src="./lib/pixi.js"></script> ! <script> var renderer=new

    PIXI.autoDetectRenderer(640,360); document.body.appendChild( renderer.view ); ! var stage = new PIXI.Stage( 0xffffff ); ! var robot = new PIXI.Sprite.fromImage( './img/ craftybot.png' ); robot.position.set( 200, 100 ); stage.addChild( robot ); ! ( function animate() { ! requestAnimationFrame( animate ); renderer.render( stage ); make a renderer canvas
  28. ! <script src="./lib/pixi.js"></script> ! <script> var renderer=new PIXI.autoDetectRenderer(640,360); document.body.appendChild( renderer.view

    ); ! var stage = new PIXI.Stage( 0xffffff ); ! var robot = new PIXI.Sprite.fromImage( './img/ craftybot.png' ); robot.position.set( 200, 100 ); stage.addChild( robot ); ! ( function animate() { ! requestAnimationFrame( animate ); renderer.render( stage ); ! } )(); ! make a stage
  29. ! <script> var renderer=new PIXI.autoDetectRenderer(640,360); document.body.appendChild( renderer.view ); ! var

    stage = new PIXI.Stage( 0xffffff ); ! var robot = new PIXI.Sprite.fromImage( './img/ craftybot.png' ); robot.position.set( 200, 100 ); stage.addChild( robot ); ! ( function animate() { ! requestAnimationFrame( animate ); renderer.render( stage ); ! } )(); ! </script> ! make a display object
  30. document.body.appendChild( renderer.view ); ! var stage = new PIXI.Stage( 0xffffff

    ); ! var robot = new PIXI.Sprite.fromImage( './img/ craftybot.png' ); robot.position.set( 200, 100 ); stage.addChild( robot ); ! ( function animate() { ! requestAnimationFrame( animate ); renderer.render( stage ); ! } )(); ! </script> ! </body> </html> add to the stage
  31. var stage = new PIXI.Stage( 0xffffff ); ! var robot

    = new PIXI.Sprite.fromImage( './img/ craftybot.png' ); robot.position.set( 200, 100 ); stage.addChild( robot ); ! ( function animate() { ! requestAnimationFrame( animate ); renderer.render( stage ); ! } )(); ! </script> ! </body> </html> render it!
  32. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>=^.^=</title> </head> <body> !

    <script src="./lib/pixi.js"></script> ! <script> ! var MyFilter = ( function () { ! var MyFilter = function() { ! PIXI.AbstractFilter.call( this ); ! this.passes = [ this ]; !
  33. ! var MyFilter = ( function () { ! var

    MyFilter = function() { ! PIXI.AbstractFilter.call( this ); ! this.passes = [ this ]; ! // types // '1f': scalar // '2f': vec2 // '3f': vec3 // '4f': vec4 // 'mat4': mat4 this.uniforms = { size: { type: '1f', value:0.01 } }; ! // http://www.html5gamedevs.com/topic/10585-list- of-available-filter-shader-uniforms/ extend Filter class
  34. // http://wp.applesandoranges.eu/?p=14 this.fragmentSrc = [ ! 'precision mediump float;', 'varying

    vec2 vTextureCoord;', 'varying vec4 vColor;', 'uniform sampler2D uSampler;', ! 'uniform float size;', ! 'void main( void ) {', ! 'vec4 sum = vec4( 0 );', ! 'for ( int i = -4; i < 4; i ++ ) {', ! 'for( int j = -4; j < 4; j++ ){', ! 'sum += texture2D( uSampler, vTextureCoord + vec2( j, i ) * size ) * 0.05;', ! '}', write your 
 fragment
 shader
  35. 'if ( alpha > 0.8 ) {', ! 'gl_FragColor =

    texColor;', ! '} else {', ! 'gl_FragColor = sum;', ! '}', ! '}' ! ]; ! }; ! MyFilter.prototype = Object.create( PIXI.AbstractFilter.prototype ); ! return MyFilter; ! } )();
  36. • &BTFM+4ͱΑ͘ࣅͨ"1*
 Very similar APIs to EaselJS  • 8FC(-Λར༻ͨ͠ߴ଎ॲཧ


    High speed pixel manipulation with WebGL  • ಠࣗγΣʔμʔͷ௥Ճ
 Custom shaders
  37. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>=^.^=</title> </head> <body> <script

    src="./lib/three.min.js"></script> <script> var width = window.innerWidth, height = window.innerHeight; ! var scene = new THREE.Scene(); ! var camera = new THREE.PerspectiveCamera( 40, width / height, 1, 1000 ); camera.position.set( 0, 0, 3 ); ! var renderer = new
  38. var width = window.innerWidth, height = window.innerHeight; ! var scene

    = new THREE.Scene(); ! var camera = new THREE.PerspectiveCamera( 40, width / height, 1, 1000 ); camera.position.set( 0, 0, 3 ); ! var renderer = new THREE.WebGLRenderer( { antialias: true } ); renderer.setSize( width, height ); document.body.appendChild( renderer.domElement ); ! var directionalLight = new THREE.DirectionalLight( 0xffffff ); directionalLight.position.set( 0, 1, 1 ).normalize(); scene.add( directionalLight ); ! var box = new THREE.Mesh(
  39. THREE.WebGLRenderer( { antialias: true } ); renderer.setSize( width, height );

    document.body.appendChild( renderer.domElement ); ! var directionalLight = new THREE.DirectionalLight( 0xffffff ); directionalLight.position.set( 0, 1, 1 ).normalize(); scene.add( directionalLight ); ! var box = new THREE.Mesh( new THREE.BoxGeometry( 1, 1, 1 ), new THREE.MeshPhongMaterial( { color: 0xff0000 } ) ); scene.add( box ); ! ( function renderLoop () { ! requestAnimationFrame( renderLoop ); box.rotation.y += 0.01;
  40. directionalLight.position.set( 0, 1, 1 ).normalize(); scene.add( directionalLight ); ! var

    box = new THREE.Mesh( new THREE.BoxGeometry( 1, 1, 1 ), new THREE.MeshPhongMaterial( { color: 0xff0000 } ) ); scene.add( box ); ! ( function renderLoop () { ! requestAnimationFrame( renderLoop ); box.rotation.y += 0.01; renderer.render( scene, camera ); ! } )(); </script> ! </body>
  41. new THREE.MeshPhongMaterial( { color: 0xff0000 } ) ); scene.add( box

    ); ! ( function renderLoop () { ! requestAnimationFrame( renderLoop ); box.rotation.y += 0.01; renderer.render( scene, camera ); ! } )(); </script> ! </body> </html>
  42. • %ϞσϧಡΈࠐΈ
 Import 3D models  • Ξχϝʔγϣϯ
 Animations 

    • ܭࢉܥͷػೳ ϕΫτϧɺߦྻͳͲ 
 Math functions, like vector, matrix • ಠࣗγΣʔμʔͷ௥Ճ
 Custom shaders Post process, Debugging WebGL, Rapid update,  BOENPSF
  43. • d[ i ].VRDevice (Type of the device) • d[

    i ].VREyeParameters • FOV • eyeTranslation • d[ i ].VRPositionState • position • velocity • orientation • angularVelocity • othres… d = navigator.
 getVRDevices()
  44. Virtuix Omni Locomotion HMD Cyberith Virtualizer OCULUS Rift SONY Morpheus

    HTC Vine • Leap Motion • PrioVR • Control VR • Sixense Stem • Razer Hydra Others
  45. Drop-in Phone
 Viewers • Different APIs
 (use DeviceOrientation API instead)

    • Limited performance
 (stereo rendering on mobile device)