📹

Mapbox Newsletter WEEKLY TIPSの解説 -「動画を追加」

2023/06/29に公開

はじめに

この記事は、先日配信されたMapbox NewsletterのWEEKLY TIPSで紹介されていた「動画を追加」についての解説です。また、Newsletterの購読はこちらからお申し込みいただけます。

コードを確認

まずExamplesのコードを見に行きましょう。

日本語サイト

英語サイト

タイトルが日本語・英語以外は同じなので今回はどちらを参照してもOKです。

HTML/CSS

まずHTMLを見ていきましょう。

以下は地図を表示するエレメントです。

<div id="map"></div>

Mapの作成

次にJavaScriptのコードを見ていきます。const videoStyleは後回しにします。その先の以下のコードはいつも通り、Mapオブジェクトを作成しています。containerで地図を表示するHTMLエレメントのidを指定します。

const map = new mapboxgl.Map({
  container: 'map',
  minZoom: 14,
  zoom: 17,
  center: [-122.514426, 37.562984],
  bearing: -96,
  style: videoStyle
});

さて、いつもとの違いはsytleにURLではなくvideoStyleオブジェクトを指定している点です。実はoptions.styleはURLの他にオブジェクトをパラメータに取ることもできます。ドキュメントにも以下のように記載されています。

The map's Mapbox style. This must be an a JSON object conforming to the schema described in the Mapbox Style Specification , or a URL to such JSON.

ということで、今回はStyle Specに準拠したオブジェクトを直接記述しているということになります。スタイルで最低限必要なのは、データであるソースとそのソースを元に定義されたレイヤーです。

まず、ソースを見てみましょう。ここではソースを2つ準備しています。1つ目がsatelliteで、Mapboxが提供するmapbox.satelliteタイルセットを使用しています。このタイルセットはrasterなのでraster sourceのスペックにしたがった記述を行っています。2つ目のvideourlscoordinatesが必須のソースです。coordinatesで指定した四角形に動画をはめ込む形になります。coordinatesは時計回りに左上、右上、右下、左下の順に座標を指定します。

'sources': {
  'satellite': {
    'type': 'raster',
    'url': 'mapbox://mapbox.satellite',
    'tileSize': 256
  },
  'video': {
    'type': 'video',
    'urls': [
      'https://static-assets.mapbox.com/mapbox-gl-js/drone.mp4',
      'https://static-assets.mapbox.com/mapbox-gl-js/drone.webm'
    ],
    'coordinates': [
      [-122.51596391201019, 37.56238816766053],
      [-122.51467645168304, 37.56410183312965],
      [-122.51309394836426, 37.563391708549425],
      [-122.51423120498657, 37.56161849366671]
    ]
  }
},

次にレイヤーを見ます。ここでは3つのレイヤーを定義しています。1つ目はbackgroundです。名前の通り背景色や画像を指定するレイヤーです。今回は2つ目のsatelliteレイヤーで覆われるので基本的に見えませんが、satelliteレイヤーが読み込まれる直前に一瞬見える地の色を設定しています。2つ目のsatelliteレイヤーはソースをsatelliteとするラスターレイヤーです。3つ目がvideoをソースとするラスターレイヤーです。

'layers': [
  {
    'id': 'background',
    'type': 'background',
    'paint': {
      'background-color': 'rgb(4,7,14)'
    }
  },
  {
    'id': 'satellite',
    'type': 'raster',
    'source': 'satellite'
  },
  {
    'id': 'video',
    'type': 'raster',
    'source': 'video'
  }
]

つまり、動画はrasterレイヤーとして描画できるということです。また、その際に使用する動画ファイルや表示する座標位置はvideoソースで指定します。

クリック処理

地図上の任意の点がクリックされた際に動画を停止、再生する処理です。VideoSourceクラスにはplayおよびpauseメソッドが実装されているので、クリックイベント時にこれらを実行するコードとなっています。

let playingVideo = true;
 
map.on('click', () => {
  playingVideo = !playingVideo;
   
  if (playingVideo) {
    map.getSource('video').play();
  } else {
    map.getSource('video').pause();
  }
});

実験

特に「スタイルとしてレイヤーを追加しないといけない」という制約はないので、MaploadイベントでaddSourceaddLayerを使って動画を表示してみます。ここでは以下の動画を使用し、東京駅の駅舎あたりの台形領域に動画を表示します。

https://www.pexels.com/ja-jp/video/855282/

Mapの作成はいつも通りです。ラスターベースのスタイルを使わなければならないという制約もないので、Mapbox Light v11を使用します。

const map = new mapboxgl.Map({
  container: "map",
  style: "mapbox://styles/mapbox/light-v11",
  zoom: 15,
  center: [139.763906, 35.6811649]
});

loadイベントの処理は以下のとおりです。addSourceおよびaddLayerで指定する項目はサンプルのスタイルで指定したものと同じです。

map.on("load", () => {
  map.addSource("source", {
    type: "video",
    urls: [
      "https://player.vimeo.com/progressive_redirect/download/204437641/container/e3021c36-fb23-4d62-a30a-6a402a3a992d/f2000a68/little_kitten_playing_his_toy_mouse%20%28360p%29.mp4?expires=1688046038&loc=external&oauth2_token_id=57447761&signature=bfc144ffa6ac029f70a0f8f96c29a2329ab0ecae76f847e2bf19330a5dcae117"
    ],
    coordinates: [
      [139.76591373007977, 35.68194904016656],
      [139.7682164472434, 35.68294045983515],
      [139.76659322039075, 35.678739617787556],
      [139.76528457238538, 35.68048744025002]
    ]
  });

  map.addLayer({
    id: "layer",
    type: "raster",
    source: "source"
  });
});

結果は以下のとおりです。

このようにしてみると、videoソースは地図の任意の四角形に動画をはめ込んでいるだけというのがわかりやすいですね。先程のサンプルで動画がきれいに衛星画像と重なっていたのは、座標が既知の動画を使用しているからです。

まとめ

動画はvideoソースをrasterレイヤーで描画できることがわかりました。

GitHubで編集を提案
マップボックス・ジャパン合同会社

Discussion