🦜
mapbox-gl-js上でParrotをPartyさせる方法3選
mapbox-gl-jsは素晴らしい地図ライブラリですが、残念ながらParty Parrotはサポートされていないようです。 本記事ではネット上で色々検索して見つけたParrotをPartyさせる方法を3つ紹介します。
NG例: GIFをそのまま描画する
このようにloadImage
関数でGIFファイルを渡してやると、エラーは起こらないですが、ParrotがPartyしてくれません 😢 コードはこちら
map.on('load', () => {
map.loadImage('partyparrot.gif',
(e, image) => {
map.addImage('parrot', image);
map.addSource('point', {
'type': 'geojson',
'data': {
'type': 'FeatureCollection',
'features': [{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [139.763906, 35.6811649]
}}]
}});
map.addLayer({ 'id': 'points', 'type': 'symbol', 'source': 'point', 'layout': { 'icon-image': 'parrot', 'icon-size': 0.25 } });
});
});
1. 動画にする
GIFファイルをezgif.comでwebm形式に変換してmapgox-gl-jsにvideoアセットとしてロードしてみました。mp4だと背景を透過にできないのでwebm形式にしました。コードはこちら。
- メリット
- コード的には簡単?
- デメリット
- GIFをwebm形式に変換するのが面倒
- ビデオリソースの矩形座標(coordinates)を正確に知るのが難しい。ちょっと縦長になってる?w
- ズームインするとアニメーションのサイズがスケーリングする?
map.on('load', () => {
map.addSource('video', {
'type': 'video',
'urls': [
'partyparrot.webm',
],
'coordinates': [
[139.763906, 35.6811649],
[139.764906, 35.6811649],
[139.764906, 35.6801649],
[139.763906, 35.6801649],
]
});
map.addLayer({
'id': 'video',
'type': 'raster',
'source': 'video'
});
});
background-image
を使う
2. StackOverflowで見つけた方法で、CSSのbackgroup-image
プロパティでGIFアニメーションを差し込んでやります。コードはこちら。
- メリット
- GIFアニメーションサイズが指定したピクセルで固定される
- コード的には一番シンプル?
- デメリット
- Parrotを追加するたびにdivが増えていく
map.on('load', () => {
var el = document.createElement('div');
el.className = 'marker';
el.setAttribute('style', 'background-image: url(partyparrot.gif); width: 32px; height: 32px; background-size: 32px 32px;');
new mapboxgl.Marker(el)
.setLngLat([139.763906, 35.6811649])
.addTo(map);
});
3. Canvasを使う
mapbox-gl-jsはCanvasベースのアニメーションをレンダリングする機能があるので、giflerというGIFをCanvasにレンダリングするJSライブラリを使ってアニメーションさせてやります。コードはこちら。
- メリット
- プログラマティックに停止・再開したり再生速度を調節できる
- デメリット
- コード的量が多い
- 少し負荷が大きそう
const size = 128;
const parrot = {
width: size,
height: size,
data: new Uint8Array(size * size * 4),
onAdd: function () {
const canvas = document.createElement('canvas');
canvas.width = this.width;
canvas.height = this.height;
this.context = canvas.getContext('2d');
this.parrot = gifler('partyparrot.gif');
this.parrot.animate(canvas);
},
render: function () {
this.data = this.context.getImageData(0, 0, this.width, this.height).data;
map.triggerRepaint();
return true;
}
};
map.on('load', () => {
map.addImage('parrot', parrot, { pixelRatio: 2 });
map.addSource('parrot-point', {
'type': 'geojson',
'data': {
'type': 'FeatureCollection',
'features': [
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [139.763906, 35.6811649]
}
}
]
}
});
map.addLayer({
'id': 'layer-with-parrot',
'type': 'symbol',
'source': 'parrot-point',
'layout': {
'icon-image': 'parrot'
}
});
まとめ
mapbox-gl-js上でPartyParrotを動かす方法を紹介しました。3つの方法は一長一短がありますが、個人的には以下の結論です。
- 普通にGIFを表示したいだけなら2.background-imageを使う
- リッチに動かしたい場合は3. Canvasを使う
この他にいい方法を知っている人があったら、コメントで教えてくれると嬉しいです。
Discussion