LoginSignup
0
0

More than 5 years have passed since last update.

Leaflet.PixiOverlayをReactで使ってみる その2

Last updated at Posted at 2018-06-06

Leaflet.PixiOverlayをReactで使ってみる その1 - Qiita
Leaflet.PixiOverlayをReactで使ってみる その2 - Qiita

はじめに

LeafletとWebGLのライブラリであるPixi.jsの橋渡しをする「Leaflet.PixiOverlay」をReactでやってみます。

今回はマーカー1,000,000個の表示をやってみます。

image

拡大するとこんな沢山のマーカー。
image

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

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: '&copy; <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の編集

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にマーカーが表示されれば成功

image

拡大するとこんな沢山のマーカー。
image

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0