Leaflet.PixiOverlayをReactで使ってみる その1 - Qiita
Leaflet.PixiOverlayをReactで使ってみる その2 - Qiita
はじめに
LeafletとWebGLのライブラリであるPixi.jsの橋渡しをする「Leaflet.PixiOverlay」をReactでやってみます。
今回はマーカー1,000,000個の表示をやってみます。
Git
今回作成した成果物は以下に置いてます。
sugasaki/leaflet-pixioverlay-trial-react
デモは以下です。
leaflet-pixioverlay-trial-react
JS版の説明
過去に書いたJS版は以下です。以下で説明した内容をReactに置き換えています。
その1:Leaflet.PixiOverlay その1マーカーの表示 - Qiita
その2:Leaflet.PixiOverlay その2many-markers - Qiita
create-react-app
Leaflet.PixiOverlayをReactで使ってみる その1 - Qiitaで作ったプロジェクトに付け足していきます。
many-markers
Leaflet.PixiOverlayのExample - many-markersをコンポーネントにしていきます。
Leaflet.PixiOverlay/many-markers.html at master · manubb/Leaflet.PixiOverlay
MarkerContainer.js
ParticleContainerの拡張用JSであるMarkerContainer.jsを以下から取得し、src/components/配下にコピーします。
Leaflet.PixiOverlay/MarkerContainer.js at master · manubb/Leaflet.PixiOverlay
drawMarkerコンポーネントを作成
src/components/manyMarkers.js
import React, { Component } from 'react'
//leaflet
import 'leaflet/dist/leaflet.css';
import L from 'leaflet'
//pixi-overlay
import * as PIXI from "pixi.js";
import 'leaflet-pixi-overlay'
//ParticleContainerの拡張用JSをロードする
import './MarkerContainer'
export default class ManyMarker extends Component {
state = {
mapLayer: null
}
componentDidMount() {//ComponentがDOMツリーに追加された状態で呼ばれます。
this.leafletInit();
}
componentDidUpdate() { //Componentが更新された後に呼ばれます。
this.pixiOverlayInit(this.state.mapLayer);
}
getRandom(min, max) {
return min + Math.random() * (max - min);
}
leafletInit() {
var map = L.map('map-many-marker').setView([48.838565, 2.449264526367], 13);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
//pixiOverlayでmapオブジェクトを参照できるようにstateにセット
this.setState({ mapLayer: map });
}
pixiOverlayInit(mapLayer) {
//マーカー最大個数
var markersLength = 1000000;
var getRandom = this.getRandom; //pixiOverlayからgetRandom関数にアクセスできるようにポインタ保存
//Draw a marker
var loader = new PIXI.loaders.Loader();
loader.add('marker', './img/marker-icon.png'); //リソースにmarkerという名で'img/marker-icon.png'を登録
loader.load(function (loader, resources) { //リソース(marker)をロードする
var texture = resources.marker.texture;
var pixiContainer = new PIXI.Container();
var innerContainer = new PIXI.particles.ParticleContainer(markersLength, { vertices: true });
innerContainer.texture = texture;
innerContainer.baseTexture = texture.baseTexture;
innerContainer.anchor = { x: 0.5, y: 1 };
pixiContainer.addChild(innerContainer);
var firstDraw = true;
var prevZoom;
var initialScale;
var pixiOverlay = L.pixiOverlay(function (utils) { //Leafletでズームやパンを行う度にコールされます。ドラッグ中はコールされない
var zoom = utils.getMap().getZoom(); //Leafletのズーム率 ex. 0~18
var container = utils.getContainer();
var renderer = utils.getRenderer();
var project = utils.latLngToLayerPoint; //Leaflet座標系LatLngからオーバーレイの座標系に投影されたL.Pointを返す。
var scale = utils.getScale();
var invScale = 1 / scale;
if (firstDraw) {
var origin = project([(48.7 + 49) / 2, (2.2 + 2.8) / 2]);
innerContainer.x = origin.x;
innerContainer.y = origin.y;
initialScale = invScale / 8;
innerContainer.localScale = initialScale;
for (var i = 0; i < markersLength; i++) {
var x = getRandom(48.7, 49);
var y = getRandom(2.2, 2.8);
var coords = project([x, y]);
// our patched particleContainer accepts simple {x: ..., y: ...} objects as children:
innerContainer.addChild({
x: coords.x - origin.x,
y: coords.y - origin.y
});
}
}
if (firstDraw || prevZoom !== zoom) {
innerContainer.localScale = zoom < 8 ? 0.1 : initialScale;// 1 / scale;
}
firstDraw = false;
prevZoom = zoom;
renderer.render(container); //オーバーレイ上にあるオブジェクトの再描画する。
}, pixiContainer);
pixiOverlay.addTo(mapLayer);
});
}
render() {
return <div>
<div id='map-many-marker'></div>
</div>;
}
}
App.jsの編集
import React, { Component } from 'react';
import './App.css';
import DrawMarker from './components/drawMarker';
import ManyMarker from './components/manyMarkers';
class App extends Component {
componentDidMount() {
}
render() {
return (
<div className="App">
<DrawMarker />
<ManyMarker />
</div>
);
}
}
export default App;
実行
yarn start
で実行します。
leafletにマーカーが表示されれば成功