2023/03/23開催のNIKKEI Tech Talk #5メディア企業のデータ可視化開発 の発表資料です #nikkei_tech_talk 「WebGLやCanvasを使ったデータ可視化コンテンツ開発」というタイトルで東條さんが発表しました。 https://nikkei.connpass.com/event/275521/
WebGL や Canvas を使ったデータ可視化コンテンツ開発日本経済新聞社編集 データビジュアルセンター東條 晃博#nikkei_tech_talk1
View Slide
自己紹介東條 晃博 (Akihiro Tojo)編集 データビジュアルセンター主にビジュアルコンテンツ制作2020 年 新卒入社趣味: 映画館、美術館、読書#nikkei_tech_talk2
#nikkei_tech_talk3
WebGL や Canvas を使ったビジュアルコンテンツもつくっています#nikkei_tech_talk4
発表内容1. フロントエンドでのデータ可視化に使う技術2. WebGL (Three.js) を使ったコンテンツ事例3. Canvas (p5.js) を使ったコンテンツ事例#nikkei_tech_talk5
制作フロータスク 担当者データの前処理 記者 or エンジニアデザイン デザイナーHTML, CSS の実装 デザイナー or エンジニアJavaScript の実装 エンジニア#nikkei_tech_talk6
フロントエンドでのデータ可視化に使う技術技術 ライブラリ例 形式 長所SVG D3.js ベクター シンプルな図形の描画Canvas p5.js ラスター 高度な 2D グラフィックスの描画WebGL Three.js ラスター 高度な 3D グラフィックスの描画#nikkei_tech_talk7
SVGシンプルな図形の描画に適しているCSS で色などの見た目を変えられるため、デザイナーとの連携がとりやすいパスの多い複雑な図形を描画すると重くなるSVG 要素をデータドリブンに操作できるライブラリとして D3.js がある#nikkei_tech_talk8
Canvas高度な 2D グラフィックスの描画に適している図形をラスターとして扱うことで SVG よりも高度な表現ができるCanvas API を簡単に利用できるライブラリとして p5.js がある#nikkei_tech_talk9
WebGL高度な 3D グラフィックスの描画に適しているGPU で演算を処理することで Canvas よりも高度な表現ができるWebGL API を簡単に利用できるライブラリとして Three.js がある#nikkei_tech_talk10
WebGL (Three.js) を使ったコンテンツ事例#nikkei_tech_talk11
地球を覆う小型衛星 3 万基3D で描く新時代英語版https://asia.nikkei.com/static/vdata/infographics/how-smallsats-revolutionize-our-future/日本語版https://vdata.nikkei.com/newsgraphics/how-smallsats-revolutionize-our-future/#nikkei_tech_talk12
地球を覆う小型衛星 3 万基3D で描く新時代衛星データベースの軌道データをもとに、約 9000 基の 2022 年 12 月時点の位置を地球の周りに可視化1959 年以降の衛星数の増加を時系列のアニメーションで表現軌道の種類で 4 つに色分け#nikkei_tech_talk13
#nikkei_tech_talk14
#nikkei_tech_talk15
データの前処理#nikkei_tech_talk16
Two-Line Element (TLE)衛星軌道のデータ形式衛星の名前、国際識別番号、軌道情報などが格納されているTLE データを処理できる Python ライブラリを使い、 2022 年 12 月時点で打ち上げられている衛星の高度、緯度、経度を算出TLE データの例:NOAA 141 23455U 94089A 97320.90946019 .00000140 00000-0 10191-3 0 26212 23455 99.0090 272.6745 0008546 223.1686 136.8816 14.11711747148495http://celestrak.org/NORAD/documentation/tle-fmt.php#nikkei_tech_talk17
座標変換高度,緯度,経度(=距離+2つの角度)で表されている衛星の座標をx, y, z(=直交する3つの軸)に変換#nikkei_tech_talk18
Three.js で地球を表示する#nikkei_tech_talk19
Three.js の基本ジオメトリ: 3D オブジェクトの形状マテリアル: 3D オブジェクトの外観シーン: 3D オブジェクトを配置する空間#nikkei_tech_talk20
ジオメトリ3D オブジェクトの形状を定義する基本形状(直方体や球体など)のジオメトリは Three.js で最初から用意されているSphereGeometryで球体を表示できる球体を地球の見た目にするために、次ページの地球の画像を表面に貼り付けるconst geometry =new SphereGeometry(1);#nikkei_tech_talk21
#nikkei_tech_talk22
マテリアル3D オブジェクトの外観を定義する色、テクスチャ、反射率、透明度などの情報をもつ地球の画像をテクスチャに指定することで地球の見た目になるconst loader =new TextureLoader();const texture = loader.load('earth.jpeg');const material =new MeshPhongMaterial({map: texture,shininess:10,});#nikkei_tech_talk23
ライト3D シーン内のオブジェクトの明るさ、影、反射などを制御する点光源、平行光源、環境光など種類がある位置、色、強度、減衰などのパラメーターで見え方を調整できるconst pointLight =new PointLight(0x333ee,10);const ambientLight =new AmbientLight(0x3333ee,4);#nikkei_tech_talk24
もう少しリアルに見せる#nikkei_tech_talk25
雲の球体オブジェクトを作成球体のジオメトリに雲のテクスチャを貼り付けるconst geometry =new SphereGeometry(1.01);const loader =new TextureLoader();const texture = loader.load('cloud.jpeg');const material =new MeshPhongMaterial({map: texture,color:0xffffff,});#nikkei_tech_talk26
透過させる地球の球体オブジェクトと重ね合わせられるように透過させるconst material =new MeshPhongMaterial({map: texture,shininess:10,transparent:true,opacity:0.2,side:DoubleSide,color:0xffffff,});#nikkei_tech_talk27
地球と雲の球体を重ね合わせる完成#nikkei_tech_talk28
衛星(パーティクル)を描画する#nikkei_tech_talk29
衛星(パーティクル)のジオメトリBufferGeometry(幾何学形状の属性を格納するジオメトリ)に[衛星1のx座標,衛星1のy座標,衛星1のz座標,衛星2のx座標,衛星2のy座標,衛星2のz座標, ...]といった衛星の座標の 1 次元配列を登録するconst geometry =new BufferGeometry();geometry.setAttribute('position',new BufferAttribute(new Float32Array(vertices),3));#nikkei_tech_talk30
衛星(パーティクル)のマテリアルシェーダー(3D グラフィックスのレンダリング用のプログラム)で点の大きさや色、透明度などを定義するRawShaderMaterialで点の描画にシェーダーを使うよう指定するconst material =new RawShaderMaterial({vertexShader,fragmentShader,transparent:true,blending:AdditiveBlending,});#nikkei_tech_talk31
スクロールに応じてカメラを回転させる#nikkei_tech_talk32
#nikkei_tech_talk33
スクロール量に応じて角度の変数を定義スクロール 0% = 角度 0°スクロール 50% = 角度 180°スクロール 100% = 角度 360°(= 0°)定義した角度をもとに、三角関数を使ってカメラの位置 (x, y, z) を算出const rotation =2 *Math.PI * scrollProgress;camera.position.set(radius *Math.cos(rotation),radius *Math.cos(rotation),radius *Math.sin(rotation));camera.lookAt(0,0,0);#nikkei_tech_talk34
Canvas (p5.js) を使ったコンテンツ事例#nikkei_tech_talk35
ロシア、口実捏造の軌跡英語版https://asia.nikkei.com/static/vdata/infographics/russia-fake-news/日本語版https://vdata.nikkei.com/newsgraphics/russia-fake-news/#nikkei_tech_talk36
ロシア、口実捏造の軌跡ウクライナ侵攻で拡散された偽情報について、テレグラム(旧ソ連圏で広く使われるSNS)上での拡散の様子をネットワーク図に可視化アカウントの種類(政府系、拡散工作用、反政府など)で色分けアカウントどうしのつながりを時系列のアニメーションで表現#nikkei_tech_talk37
#nikkei_tech_talk38
#nikkei_tech_talk39
データ収集データ提供サービスの API を利用記者が偽情報の投稿を特定偽情報の投稿を引用・転送した投稿を収集→ その投稿を引用・転送した投稿を収集→ ...... 繰り返し※ mention = 引用、forward = 転送#nikkei_tech_talk40
エッジアカウントのペアの配列引用・転送したアカウント引用・転送されたアカウントA BA C... ...#nikkei_tech_talk41
ノード種別で色分けして表示アカウント 種別A 政府系B 拡散工作用C 反政府... ...※ 種別は記者がアカウントの投稿内容を確認して分類#nikkei_tech_talk42
ノード投稿が閲覧された回数で大きさを変えるアカウント 種別 閲覧数 ...A 政府系 2000 ...B 拡散工作用 500 ...C 反政府 300 ...... ... ... ...#nikkei_tech_talk43
グラフ配置の計算ネットワーク可視化ライブラリを使ってノードの座標を計算する言語 ライブラリ例JavaScript d3-force などPython NetworkX などGUI ツール Gephi, Cytoscape など#nikkei_tech_talk44
p5.js でネットワークを描画する#nikkei_tech_talk45
p5.js の基本setup: 最初に 1 度だけ実行draw: 毎フレーム繰り返し実行function setup() {createCanvas(400,400);}function draw() {background('#000');ellipse(200,200,50,50);}#nikkei_tech_talk46
ノードを描画するfill: 塗りの色を指定ellipse: 円を描画function draw() {// ...fill('#ff3333');ellipse(100,200,50,50);fill('#00c2ff');ellipse(300,200,50,50);}#nikkei_tech_talk47
エッジを描画するstroke: 線の色を指定line: 線を描画function draw() {// ...stroke('#fff');line(100,200,300,200);}#nikkei_tech_talk48
色をグラデーションさせるp5.js では色をグラデーションできないので、生の Canvas API ( createLinearGradient) を使うfunction draw() {// ...const gradient = drawingContext.createLinearGradient(100,200,300,200);gradient.addColorStop(0,'#ff3333');gradient.addColorStop(1,'#00c2ff');drawingContext.strokeStyle = gradient;line(100,200,300,200);}#nikkei_tech_talk49
スクロールアニメーションスクロール量に応じてエッジを伸ばすノードの位置をベクトルで表し、始点と終点のノード位置をスクロール進捗率で補間することでエッジの先端の位置を求めるfunction draw() {// ...const nodeFrom =createVector(100,200);const nodeTo =createVector(300,200);const edgeFrom = nodeFrom;const edgeTo = p5.Vector.lerp(nodeFrom, nodeTo, progress);line(edgeFrom.x, edgeFrom.y, edgeTo.x, edgeTo.y);}#nikkei_tech_talk50
#nikkei_tech_talk51
Three.js や p5.js のいいところコミュニティが大規模で活用事例が充実しているOpenProcessing: https://openprocessing.org/three.js examples: https://threejs.org/examples/WebGL や Canvas の API を抽象化し簡単に扱えるようにすることで、低い学習コストで高度な表現を実現企画をすばやくコンテンツ化するうえでは重要一方で、より高度で自由な表現をするには低レイヤーの理解や数学力が必要#nikkei_tech_talk52
まとめシンプルなチャートだけでなくWebGL や Canvas を使ったデータ可視化コンテンツもつくっています技術 長所SVG シンプルな図形Canvas 2D グラフィックWebGL 3D グラフィック#nikkei_tech_talk53