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

WebGLやCanvasを使ったデータ可視化コンテンツ開発/nikkei-tech-talk5-3

 WebGLやCanvasを使ったデータ可視化コンテンツ開発/nikkei-tech-talk5-3

2023/03/23開催のNIKKEI Tech Talk #5メディア企業のデータ可視化開発 の発表資料です #nikkei_tech_talk
「WebGLやCanvasを使ったデータ可視化コンテンツ開発」というタイトルで東條さんが発表しました。
https://nikkei.connpass.com/event/275521/

More Decks by 日本経済新聞社 エンジニア採用事務局

Other Decks in Technology

Transcript

  1. WebGL や Canvas を使った
    データ可視化コンテンツ開発
    日本経済新聞社
    編集 データビジュアルセンター
    東條 晃博
    #nikkei_tech_talk
    1

    View full-size slide

  2. 自己紹介
    東條 晃博 (Akihiro Tojo)
    編集 データビジュアルセンター
    主にビジュアルコンテンツ制作
    2020 年 新卒入社
    趣味: 映画館、美術館、読書
    #nikkei_tech_talk
    2

    View full-size slide

  3. #nikkei_tech_talk
    3

    View full-size slide

  4. WebGL や Canvas を使った
    ビジュアルコンテンツも
    つくっています
    #nikkei_tech_talk
    4

    View full-size slide

  5. 発表内容
    1. フロントエンドでのデータ可視化に使う技術
    2. WebGL (Three.js) を使ったコンテンツ事例
    3. Canvas (p5.js) を使ったコンテンツ事例
    #nikkei_tech_talk
    5

    View full-size slide

  6. 制作フロー
    タスク 担当者
    データの前処理 記者 or エンジニア
    デザイン デザイナー
    HTML, CSS の実装 デザイナー or エンジニア
    JavaScript の実装 エンジニア
    #nikkei_tech_talk
    6

    View full-size slide

  7. フロントエンドでのデータ可視化に使う技術
    技術 ライブラリ例 形式 長所
    SVG D3.js ベクター シンプルな図形の描画
    Canvas p5.js ラスター 高度な 2D グラフィックスの描画
    WebGL Three.js ラスター 高度な 3D グラフィックスの描画
    #nikkei_tech_talk
    7

    View full-size slide

  8. SVG
    シンプルな図形の描画に適している
    CSS で色などの見た目を変えられるた
    め、デザイナーとの連携がとりやすい
    パスの多い複雑な図形を描画すると重くな

    SVG 要素をデータドリブンに操作できる
    ライブラリとして D3.js がある
    #nikkei_tech_talk
    8

    View full-size slide

  9. Canvas
    高度な 2D グラフィックスの描画に適して
    いる
    図形をラスターとして扱うことで SVG よ
    りも高度な表現ができる
    Canvas API を簡単に利用できるライブラ
    リとして p5.js がある
    #nikkei_tech_talk
    9

    View full-size slide

  10. WebGL
    高度な 3D グラフィックスの描画に適して
    いる
    GPU で演算を処理することで Canvas よ
    りも高度な表現ができる
    WebGL API を簡単に利用できるライブラ
    リとして Three.js がある
    #nikkei_tech_talk
    10

    View full-size slide

  11. WebGL (Three.js) を使ったコンテンツ事例
    #nikkei_tech_talk
    11

    View full-size slide

  12. 地球を覆う小型衛星 3 万基
    3D で描く新時代
    英語版
    https://asia.nikkei.com/static/vdata/
    infographics/how-smallsats-
    revolutionize-our-future/
    日本語版
    https://vdata.nikkei.com/newsgraph
    ics/how-smallsats-revolutionize-
    our-future/
    #nikkei_tech_talk
    12

    View full-size slide

  13. 地球を覆う小型衛星 3 万基
    3D で描く新時代
    衛星データベースの軌道データをもとに、
    約 9000 基の 2022 年 12 月時点の位置を
    地球の周りに可視化
    1959 年以降の衛星数の増加を時系列のア
    ニメーションで表現
    軌道の種類で 4 つに色分け
    #nikkei_tech_talk
    13

    View full-size slide

  14. #nikkei_tech_talk
    14

    View full-size slide

  15. #nikkei_tech_talk
    15

    View full-size slide

  16. データの前処理
    #nikkei_tech_talk
    16

    View full-size slide

  17. Two-Line Element (TLE)
    衛星軌道のデータ形式
    衛星の名前、国際識別番号、軌道情報などが格納されている
    TLE データを処理できる Python ライブラリを使い、 2022 年 12 月時点で打ち上
    げられている衛星の高度、緯度、経度を算出
    TLE データの例:
    NOAA 14
    1 23455U 94089A 97320.90946019 .00000140 00000-0 10191-3 0 2621
    2 23455 99.0090 272.6745 0008546 223.1686 136.8816 14.11711747148495
    http://celestrak.org/NORAD/documentation/tle-fmt.php
    #nikkei_tech_talk
    17

    View full-size slide

  18. 座標変換
    高度,
    緯度,
    経度(=距離+2
    つの角度)
    で表されている衛星の座標を
    x, y, z
    (=直交する3
    つの軸)
    に変換
    #nikkei_tech_talk
    18

    View full-size slide

  19. Three.js で地球を表示する
    #nikkei_tech_talk
    19

    View full-size slide

  20. Three.js の基本
    ジオメトリ: 3D オブジェクトの形状
    マテリアル: 3D オブジェクトの外観
    シーン: 3D オブジェクトを配置する空間
    #nikkei_tech_talk
    20

    View full-size slide

  21. ジオメトリ
    3D オブジェクトの形状を定義する
    基本形状(直方体や球体など)のジオメト
    リは Three.js で最初から用意されている
    SphereGeometry
    で球体を表示できる
    球体を地球の見た目にするために、次ペー
    ジの地球の画像を表面に貼り付ける
    const geometry =
    new SphereGeometry(
    1);
    #nikkei_tech_talk
    21

    View full-size slide

  22. #nikkei_tech_talk
    22

    View full-size slide

  23. マテリアル
    3D オブジェクトの外観を定義する
    色、テクスチャ、反射率、透明度などの情
    報をもつ
    地球の画像をテクスチャに指定することで
    地球の見た目になる
    const loader =
    new TextureLoader();
    const texture = loader.
    load(
    'earth.jpeg');
    const material =
    new MeshPhongMaterial({
    map: texture,
    shininess:
    10,
    });
    #nikkei_tech_talk
    23

    View full-size slide

  24. ライト
    3D シーン内のオブジェクトの明るさ、
    影、反射などを制御する
    点光源、平行光源、環境光など種類がある
    位置、色、強度、減衰などのパラメーター
    で見え方を調整できる
    const pointLight =
    new PointLight(
    0x333ee,
    10);
    const ambientLight =
    new AmbientLight(
    0x3333ee,
    4);
    #nikkei_tech_talk
    24

    View full-size slide

  25. もう少しリアルに見せる
    #nikkei_tech_talk
    25

    View full-size slide

  26. 雲の球体オブジェクトを作成
    球体のジオメトリに雲のテクスチャを貼り付け

    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_talk
    26

    View full-size slide

  27. 透過させる
    地球の球体オブジェクトと重ね合わせられるよ
    うに透過させる
    const material =
    new MeshPhongMaterial({
    map: texture,
    shininess:
    10,
    transparent:
    true,
    opacity:
    0.2,
    side:
    DoubleSide,
    color:
    0xffffff,
    });
    #nikkei_tech_talk
    27

    View full-size slide

  28. 地球と雲の球体を重ね合わせる
    完成
    #nikkei_tech_talk
    28

    View full-size slide

  29. 衛星(パーティクル)を描画する
    #nikkei_tech_talk
    29

    View full-size slide

  30. 衛星(パーティクル)のジオメトリ
    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_talk
    30

    View full-size slide

  31. 衛星(パーティクル)のマテリアル
    シェーダー(3D グラフィックスのレンダ
    リング用のプログラム)で点の大きさや
    色、透明度などを定義する
    RawShaderMaterial
    で点の描画にシェー
    ダーを使うよう指定する
    const material =
    new RawShaderMaterial({
    vertexShader,
    fragmentShader,
    transparent:
    true,
    blending:
    AdditiveBlending,
    });
    #nikkei_tech_talk
    31

    View full-size slide

  32. スクロールに応じてカメラを回転させる
    #nikkei_tech_talk
    32

    View full-size slide

  33. #nikkei_tech_talk
    33

    View full-size slide

  34. スクロール量に応じて角度の変数を定義
    スクロール 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_talk
    34

    View full-size slide

  35. Canvas (p5.js) を使ったコンテンツ事例
    #nikkei_tech_talk
    35

    View full-size slide

  36. ロシア、口実捏造の軌跡
    英語版
    https://asia.nikkei.com/static/vdata/
    infographics/russia-fake-news/
    日本語版
    https://vdata.nikkei.com/newsgraph
    ics/russia-fake-news/
    #nikkei_tech_talk
    36

    View full-size slide

  37. ロシア、口実捏造の軌跡
    ウクライナ侵攻で拡散された偽情報につい
    て、テレグラム(旧ソ連圏で広く使われる
    SNS)上での拡散の様子をネットワーク図
    に可視化
    アカウントの種類(政府系、拡散工作用、
    反政府など)で色分け
    アカウントどうしのつながりを時系列のア
    ニメーションで表現
    #nikkei_tech_talk
    37

    View full-size slide

  38. #nikkei_tech_talk
    38

    View full-size slide

  39. #nikkei_tech_talk
    39

    View full-size slide

  40. データ収集
    データ提供サービスの API を利用
    記者が偽情報の投稿を特定
    偽情報の投稿を引用・転送した投稿を収集
    → その投稿を引用・転送した投稿を収集
    → ...... 繰り返し
    ※ mention = 引用、forward = 転送
    #nikkei_tech_talk
    40

    View full-size slide

  41. エッジ
    アカウントのペアの配列
    引用・転送した
    アカウント
    引用・転送された
    アカウント
    A B
    A C
    ... ...
    #nikkei_tech_talk
    41

    View full-size slide

  42. ノード
    種別で色分けして表示
    アカウント 種別
    A 政府系
    B 拡散工作用
    C 反政府
    ... ...
    ※ 種別は記者がアカウントの投稿内容を確認
    して分類
    #nikkei_tech_talk
    42

    View full-size slide

  43. ノード
    投稿が閲覧された回数で大きさを変える
    アカウント 種別 閲覧数 ...
    A 政府系 2000 ...
    B 拡散工作用 500 ...
    C 反政府 300 ...
    ... ... ... ...
    #nikkei_tech_talk
    43

    View full-size slide

  44. グラフ配置の計算
    ネットワーク可視化ライブラリを使ってノード
    の座標を計算する
    言語 ライブラリ例
    JavaScript d3-force など
    Python NetworkX など
    GUI ツール Gephi, Cytoscape など
    #nikkei_tech_talk
    44

    View full-size slide

  45. p5.js でネットワークを描画する
    #nikkei_tech_talk
    45

    View full-size slide

  46. p5.js の基本
    setup
    : 最初に 1 度だけ実行
    draw
    : 毎フレーム繰り返し実行
    function setup() {
    createCanvas(
    400,
    400);
    }
    function draw() {
    background(
    '#000');
    ellipse(
    200,
    200,
    50,
    50);
    }
    #nikkei_tech_talk
    46

    View full-size slide

  47. ノードを描画する
    fill
    : 塗りの色を指定
    ellipse
    : 円を描画
    function draw() {
    // ...
    fill(
    '#ff3333');
    ellipse(
    100,
    200,
    50,
    50);
    fill(
    '#00c2ff');
    ellipse(
    300,
    200,
    50,
    50);
    }
    #nikkei_tech_talk
    47

    View full-size slide

  48. エッジを描画する
    stroke
    : 線の色を指定
    line
    : 線を描画
    function draw() {
    // ...
    stroke(
    '#fff');
    line(
    100,
    200,
    300,
    200);
    }
    #nikkei_tech_talk
    48

    View full-size slide

  49. 色をグラデーションさせる
    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_talk
    49

    View full-size slide

  50. スクロールアニメーション
    スクロール量に応じてエッジを伸ばす
    ノードの位置をベクトルで表し、始点と終
    点のノード位置をスクロール進捗率で補間
    することでエッジの先端の位置を求める
    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_talk
    50

    View full-size slide

  51. #nikkei_tech_talk
    51

    View full-size slide

  52. Three.js や p5.js のいいところ
    コミュニティが大規模で活用事例が充実している
    OpenProcessing: https://openprocessing.org/
    three.js examples: https://threejs.org/examples/
    WebGL や Canvas の API を抽象化し簡単に扱えるようにすることで、低い学習
    コストで高度な表現を実現
    企画をすばやくコンテンツ化するうえでは重要
    一方で、より高度で自由な表現をするには低レイヤーの理解や数学力が必要
    #nikkei_tech_talk
    52

    View full-size slide

  53. まとめ
    シンプルなチャートだけでなく
    WebGL や Canvas を使った
    データ可視化コンテンツも
    つくっています
    技術 長所
    SVG シンプルな図形
    Canvas 2D グラフィック
    WebGL 3D グラフィック
    #nikkei_tech_talk
    53

    View full-size slide