3 Revize 2e23ee0ee3 ... 02f6f6c922

Autor SHA1 Zpráva Datum
  HuangKai 02f6f6c922 定位卡重构,增加移动动画 před 5 dny
  HuangKai 2263ce1e15 增加POI标识显示 před 5 dny
  HuangKai 5fdfaf004c MapUtil的map属性初始化赋值 před 5 dny

+ 11 - 0
package-lock.json

@@ -45,6 +45,7 @@
         "leaflet-textpath": "^1.2.0",
         "leaflet-toolbar": "^0.4.0-alpha.2",
         "leaflet-trackplayer": "^2.0.2",
+        "leaflet.marker.slideto": "^0.3.0",
         "martinez-polygon-clipping": "^0.7.3",
         "mdi-react": "^5.5.0",
         "mousetrap": "^1.6.3",
@@ -14570,6 +14571,11 @@
       "resolved": "https://registry.npmmirror.com/leaflet-trackplayer/-/leaflet-trackplayer-2.0.2.tgz",
       "integrity": "sha512-7Eor1jVXvjCLfhp71jC11ReWNjmWxqCsOukkPMnTMllAvDfldPtPJXbqhsYZ2ud8cVipWBDg2Sn7SB56spQ/7g=="
     },
+    "node_modules/leaflet.marker.slideto": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmmirror.com/leaflet.marker.slideto/-/leaflet.marker.slideto-0.3.0.tgz",
+      "integrity": "sha512-BQwOy5CuDBuEXIbeJ1mjO9SqlY3au65LhWJ1hjkwQYy/XhOhaF7kIF3+0DRasONIvbFYL+QwQ2/QjEjDUZgn4A=="
+    },
     "node_modules/left-pad": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz",
@@ -36860,6 +36866,11 @@
       "resolved": "https://registry.npmmirror.com/leaflet-trackplayer/-/leaflet-trackplayer-2.0.2.tgz",
       "integrity": "sha512-7Eor1jVXvjCLfhp71jC11ReWNjmWxqCsOukkPMnTMllAvDfldPtPJXbqhsYZ2ud8cVipWBDg2Sn7SB56spQ/7g=="
     },
+    "leaflet.marker.slideto": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmmirror.com/leaflet.marker.slideto/-/leaflet.marker.slideto-0.3.0.tgz",
+      "integrity": "sha512-BQwOy5CuDBuEXIbeJ1mjO9SqlY3au65LhWJ1hjkwQYy/XhOhaF7kIF3+0DRasONIvbFYL+QwQ2/QjEjDUZgn4A=="
+    },
     "left-pad": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz",

+ 1 - 0
package.json

@@ -61,6 +61,7 @@
     "leaflet-textpath": "^1.2.0",
     "leaflet-toolbar": "^0.4.0-alpha.2",
     "leaflet-trackplayer": "^2.0.2",
+    "leaflet.marker.slideto": "^0.3.0",
     "martinez-polygon-clipping": "^0.7.3",
     "mdi-react": "^5.5.0",
     "mousetrap": "^1.6.3",

+ 13 - 1
src/view/Map.js

@@ -28,6 +28,8 @@ import MapStyler from '../model/mapcss/MapStyler';
 import LevelSelector from './common/LevelSelector';
 import NorthPointer from './common/NorthPointer';
 import HistoryTrack from './layers/HistoryTrack';
+import POIObject from './layers/POIObject';
+import MapUtil from './utils/MapUtil';
 
 
 const MAP_MAX_ZOOM = 22;
@@ -434,7 +436,7 @@ class MyMap extends Component {
 					/>
 				}
 
-				{!this.state.loading && this.state.dataready && this.props.mode === Body.MODE_EXPLORE &&
+				{!this.state.loading && this.state.dataready &&
 					<MoveableObject
 						styler={this.mapStyler}
 						level={this.props.level}
@@ -442,6 +444,14 @@ class MyMap extends Component {
 					/>
 				}
 
+				{!this.state.loading && this.state.dataready &&
+					<POIObject
+						styler={this.mapStyler}
+						level={this.props.level}
+						floor={this.props.floor}
+					/>
+				}
+
 				{this.state.initHisTrack &&
 					<HistoryTrack
 						map={this.elem}
@@ -464,6 +474,8 @@ class MyMap extends Component {
 			this._loadData();
 		}, 500);
 
+		MapUtil.map = this.elem.leafletElement;
+
 		// URL hash for map
 		this._mapHash = new L.Hash(this.elem.leafletElement);
 

+ 26 - 7
src/view/common/LocationCard.js

@@ -1,24 +1,43 @@
 /** * 定位卡
  * 
 */
+import PubSub from "pubsub-js";
+import MapUtil from "../utils/MapUtil";
+import App from "../App";
 
 export default class LocationCard{
 /** * 定位卡
-    * @param {Number} lat - 定位卡纬度 
-    * @param {Number} lng - 定位卡经度 
+    * @param {Number} x - 定位卡x坐标 
+    * @param {Number} y - 定位卡y坐标 
     * @param {String} milli_time - 定位时间戳(毫秒)
-    * @param {String} locTime - 定位时间 
+    * @param {String} loc_time - 定位时间 
     * @param {Number} card_id - 定位卡ID 
     * @param {JSX} info - jsx详细信息 
     * @param {String} src - 标记图标路径
    */
-    constructor(lat, lng, loc_time, milli_time, card_id, info, src){
-        this.lat = lat;
-        this.lng = lng;
+    constructor(x, y, loc_time, milli_time, card_id, info, src){
+        let latlng = MapUtil.distancePointToLatLng(App.origin, x, y);
+        this.lat = latlng.lat;
+        this.lng = latlng.lng;
         this.milli_time = milli_time;
         this.loc_time = loc_time;
-        this.card = card_id;
+        this.card_id = card_id;
         this.src = src ? src : "img/move.png";
         this.info = info;
     }
+
+    add(){
+        PubSub.publish('map.card.add', this);
+    }
+
+    move(x, y){
+        let latlng = MapUtil.distancePointToLatLng(App.origin, x, y);
+        this.lat = latlng.lat;
+        this.lng = latlng.lng;
+        PubSub.publish('map.card.move', this);
+    }
+
+    remove(){
+        PubSub.publish('map.card.remove', this);
+    }
 }

+ 33 - 11
src/view/common/MoveableMarker.js

@@ -1,6 +1,9 @@
 import React, { Component } from 'react';
 import { Marker, /*Popup, */Tooltip, withLeaflet } from "react-leaflet";
-import { Icon } from 'leaflet';
+import { Icon, LatLng } from 'leaflet';
+import bearing from '@turf/bearing';
+import PubSub from 'pubsub-js';
+import 'leaflet.marker.slideto/Leaflet.Marker.SlideTo.js'
 
 class MoveableMarker extends Component{
     createInfo(data){
@@ -16,23 +19,42 @@ class MoveableMarker extends Component{
         return infos;
     }
 
+    componentDidMount(){       
+        this.card_id =  this.props.data.card_id;
+		
+		PubSub.subscribe('map.marker.move', (msg, data) => {
+            if(this.card_id === data.id){
+                // console.log(this.marker, 'slideTo' in this.marker);
+                let oldLatlng = this.marker.leafletElement.getLatLng();
+                let newLatlng = new LatLng(data.lat, data.lng);
+                let b = bearing([oldLatlng.lat, oldLatlng.lng], [newLatlng.lat, newLatlng.lng]) + 90;
+                console.log(b, b * 0.33333);
+                this.marker.leafletElement.setRotationAngle(b * 0.33333);
+                this.marker.leafletElement.slideTo([data.lat, data.lng], {
+                    duration: data.duration,
+                    keepAtCenter: false
+                });
+            }
+        });
+    }
+
     render(){
         return <>
-            <Marker position={[this.props.data.lat, this.props.data.lng] } icon={new Icon({
-                // iconUrl: window.EDITOR_URL + "img/move.png",
-                iconUrl: window.EDITOR_URL + this.props.data.src,
-                iconSize: [20,20],
-                iconAnchor: [10,10]
-            })} name={`${this.props.data.card}`} key={this.props.key}>
+            <Marker 
+                position={[this.props.data.lat, this.props.data.lng] } 
+                icon={new Icon({
+                    iconUrl: window.EDITOR_URL + this.props.data.src,
+                    iconSize: [20,20],
+                    iconAnchor: [10,10]
+                })}
+                name={`${this.card_id}`} key={this.card_id}
+                ref={marker => this.marker = marker}
+            >
                 {this.props.data.info &&
                     <Tooltip>
                         { this.createInfo(this.props.data.info) }
                     </Tooltip>
                 }
-                {/* <Popup>
-                    <span>{}</span>
-                    <button onClick={() => {console.log(`marker-${this.props.data.id}`)}}>点击</button>
-                </Popup> */}
             </Marker>;
         </>
     }

+ 41 - 0
src/view/common/POI.js

@@ -0,0 +1,41 @@
+/** * POI点
+ * 
+*/
+import PubSub from "pubsub-js";
+import MapUtil from "../utils/MapUtil";
+import App from "../App";
+
+export default class POI{
+/** * POI点
+    * @param {Number} id - POI id
+    * @param {Number} x - POI x坐标
+    * @param {Number} y - POI y坐标 
+    * @param {String} name - POI 名称
+    * @param {Array<String>} info - jsx详细信息 
+    * @param {String} src - 标记图标路径
+   */
+    constructor(id, x, y, name, info, src){
+        let latlng = MapUtil.distancePointToLatLng(App.origin, x, y);
+        this.lat = latlng.lat;
+        this.lng = latlng.lng;
+        this.src = src ? src : "img/move.png";
+        this.info = info;
+        this.name = name;
+        this.id = id;
+    }
+
+    add(){
+        PubSub.publish('map.poi.add', this);
+    }
+
+    // move(x, y){
+    //     let latlng = MapUtil.distancePointToLatLng(App.origin, x, y);
+    //     this.lat = latlng.lat;
+    //     this.lng = latlng.lng;
+    //     PubSub.publish('map.poi.move', this);
+    // }
+
+    remove(){
+        PubSub.publish('map.poi.remove', this);
+    }
+}

+ 53 - 0
src/view/common/POIMarker.js

@@ -0,0 +1,53 @@
+import React, { Component } from 'react';
+import { Marker, Popup, Tooltip, withLeaflet } from "react-leaflet";
+import { DivIcon, Icon } from 'leaflet';
+
+class POIMarker extends Component{
+    createInfo(data){
+        let infos = [];
+        for (let i = 0; i < data.length; i++) { 
+            const element = data[i];
+            if(element !== ','){
+                infos.push(<span key={data[i]}>{element}</span>);
+            }else{
+                infos.push(<br/>);
+            }
+        }
+        return infos;
+    }
+
+    render(){
+        return <>
+            <Marker 
+                position={[this.props.data.lat, this.props.data.lng] } 
+                icon={new Icon({
+                    iconUrl: window.EDITOR_URL + this.props.data.src,
+                    iconSize: [20,20],
+                    iconAnchor: [10,10],
+                    popupAnchor: [0, -10]
+                })}
+                name={`${this.props.data.id}`} key={this.props.data.id}
+                ref={marker => this.marker = marker}
+            >
+                {this.props.data.info &&
+                    <Popup>
+                        { this.createInfo(this.props.data.info) }
+                    </Popup>
+                }
+            </Marker>;
+                <Marker 
+                    position={[this.props.data.lat, this.props.data.lng] } 
+                    icon={new DivIcon({
+                        html: <div>{this.props.data.name}</div>,
+                        iconSize: [80,20],
+                        iconAnchor: [40,-10]
+                    })}
+                    key={"poi-text-" + this.props.data.name}
+                >
+
+                </Marker>
+        </>
+    }
+}
+
+export default withLeaflet(POIMarker);

+ 39 - 14
src/view/layers/MoveableObject.js

@@ -1,6 +1,6 @@
 import React, { Component } from 'react';
 import PubSub from 'pubsub-js';
-import {  withLeaflet } from 'react-leaflet';
+import {  withLeaflet, LayerGroup } from 'react-leaflet';
 import MoveableMarker from '../common/MoveableMarker';
 
 /**
@@ -8,33 +8,58 @@ import MoveableMarker from '../common/MoveableMarker';
  */
 class MoveableObjectLayer extends Component {
 	state = {
-		markers: []
+		markers: [],
 	}
 
 	componentDidMount(){
-		PubSub.subscribe('body.data.got', (msg, data) => {
-			let els = [];
-			for (let i = 0; i < data.length; i++) {
-				let element = <MoveableMarker 
-					data={data[i]} 
-					key={data[i].card}
+		PubSub.subscribe('map.card.add', (msg, data) => {
+			let ms = this.state.markers;
+			let element = <MoveableMarker 
+					data={data} 
+					key={data.card_id}
+					ref={this.marker}
 				></MoveableMarker>
-				els.push(element)
+			this.setState({markers: [...this.state.markers, element]});
+		});
+
+        PubSub.subscribe('map.card.move', (msg, data) => {
+			let marker = this.state.markers.filter(m => m.key == data.card_id);
+			if(marker.length > 0){
+				// let element = <MoveableMarker 
+				// 	data={data} 
+				// 	key={data.card_id}
+				// 	ref={this.marker}
+				// ></MoveableMarker>
+				// this.setState({markers: [...this.state.markers.filter(m => m.key != data.card_id), element]});
+				PubSub.publish("map.marker.move", {id: data.card_id, lat: data.lat, lng: data.lng, duration: 1000});
 			}
-			this.setState({markers: els});
-			// console.log("MoveableObjectLayer", this.state.markers);
 		});
+
+        PubSub.subscribe('map.card.remove', (msg, data) => {
+			let markers = this.state.markers.filter(m => m.key != data.card_id);
+			this.setState({markers: markers});
+		});
+	}
+
+	move(){
+
+	}
+
+	stop(){
+		
 	}
 
 	componentWillUnmount(){
-		PubSub.unsubscribe('body.data.got');
+		PubSub.unsubscribe('map.card.add');
+		PubSub.unsubscribe('map.card.move');
+		PubSub.unsubscribe('map.card.remove');
 	}
 
 	render() {
 		return (
-			<>
+			<LayerGroup key="moveable">
 				{ this.state.markers }
-			</>
+			</LayerGroup>
 		);
 	}
 }

+ 56 - 0
src/view/layers/POIObject.js

@@ -0,0 +1,56 @@
+import React, { Component } from 'react';
+import PubSub from 'pubsub-js';
+import {  withLeaflet, LayerGroup } from 'react-leaflet';
+import POIMarker from '../common/POIMarker';
+
+/**
+ * MoveableObject layer allows to show 
+ */
+class POIObjectLayer extends Component {
+	state = {
+		markers: [],
+	}
+
+	componentDidMount(){
+		PubSub.subscribe('map.poi.add', (msg, data) => {
+			let element = <POIMarker 
+					data={data} 
+					key={data.id}
+					ref={this.marker}
+				></POIMarker>
+			this.setState({markers: [...this.state.markers, element]});
+		});
+
+        // PubSub.subscribe('map.poi.move', (msg, data) => {
+		// 	let marker = this.state.markers.filter(m => m.key == data.id);
+		// 	if(marker.length > 0){
+		// 		let element = <POIMarker 
+		// 			data={data} 
+		// 			key={data.id}
+		// 			ref={this.marker}
+		// 		></POIMarker>
+		// 		this.setState({markers: [...this.state.markers.filter(m => m.key != data.id), element]});
+		// 	}
+		// });
+
+        PubSub.subscribe('map.poi.remove', (msg, data) => {
+			let markers = this.state.markers.filter(m => m.key != data.id);
+			this.setState({markers: markers});
+		});
+	}
+
+	componentWillUnmount(){
+		PubSub.unsubscribe('map.poi.add');
+		PubSub.unsubscribe('map.poi.move');
+		PubSub.unsubscribe('map.poi.remove');
+	}
+
+	render() {
+		return (
+			<LayerGroup key="poi">
+				{ this.state.markers }
+			</LayerGroup>
+		);
+	}
+}
+export default withLeaflet(POIObjectLayer);

+ 19 - 18
src/view/utils/MapUtil.js

@@ -2,15 +2,16 @@ import { LatLng, Point } from 'leaflet';
 import MyMap from '../Map';
 
 export default class MapUtil {
+    static map;
     /** 
      * 给定地理坐标,转换为相对于origin pixel的相应像素坐标。(在地图上进行位置叠加时比较有用)
      * @param {{lat: number, lng: number}} latlng - 经纬度
      * @returns {{x:number, y:number}} - 像素点坐标
      */
     static latLngToLayerPoint(latlng){
-        if(!MyMap.map){ console.error("请先初始化地图!"); return; }
+        if(!MapUtil.map){ console.error("请先初始化地图!"); return; }
         let ll = new LatLng(latlng.lat, latlng.lng);
-        let p = MyMap.map.latLngToLayerPoint(ll);
+        let p = MapUtil.map.latLngToLayerPoint(ll);
         return {x: p.x, y: p.y};
     }
 
@@ -20,9 +21,9 @@ export default class MapUtil {
      * @returns {{lat: number, lng: number}} - 经纬度
      */
     static layerPointToLatLng(point){
-        if(!MyMap.map){ console.error("请先初始化地图!"); return; }
+        if(!MapUtil.map){ console.error("请先初始化地图!"); return; }
         let p = new Point(point.x, point.y);
-        let ll = MyMap.map.layerPointToLatLng(p);
+        let ll = MapUtil.map.layerPointToLatLng(p);
         return {lat: ll.lat, lng: ll.lng};
     }
 
@@ -32,9 +33,9 @@ export default class MapUtil {
      * @returns {{x:number, y:number}} - 像素点坐标
      */
     static latLngToContainerPoint(latlng){
-        if(!MyMap.map){ console.error("请先初始化地图!"); return; }
+        if(!MapUtil.map){ console.error("请先初始化地图!"); return; }
         let ll = new LatLng(latlng.lat, latlng.lng);
-        let p = MyMap.map.latLngToContainerPoint(ll);
+        let p = MapUtil.map.latLngToContainerPoint(ll);
         return {x: p.x, y: p.y};
     }
 
@@ -44,9 +45,9 @@ export default class MapUtil {
      * @returns {{lat: number, lng: number}} - 经纬度
      */
     static containerPointToLatLng(point){
-        if(!MyMap.map){ console.error("请先初始化地图!"); return; }
+        if(!MapUtil.map){ console.error("请先初始化地图!"); return; }
         let p = new Point(point.x, point.y);
-        let ll = MyMap.map.containerPointToLatLng(p);
+        let ll = MapUtil.map.containerPointToLatLng(p);
         return {lat: ll.lat, lng: ll.lng};
     }
 
@@ -57,8 +58,8 @@ export default class MapUtil {
      * @returns {{x:number, y:number}} - 像素点坐标
      */
     static project(latlng, zoom){
-        if(!MyMap.map){ console.error("请先初始化地图!"); return; }
-        let p = MyMap.map.project(latlng, zoom);
+        if(!MapUtil.map){ console.error("请先初始化地图!"); return; }
+        let p = MapUtil.map.project(latlng, zoom);
         return {x: p.x, y: p.y};
     }
 
@@ -69,8 +70,8 @@ export default class MapUtil {
      * @returns {{lat: number, lng: number}} - 经纬度
      */
     static unproject(point, zoom){
-        if(!MyMap.map){ console.error("请先初始化地图!"); return; }
-        let ll = MyMap.map.unproject(point, zoom);
+        if(!MapUtil.map){ console.error("请先初始化地图!"); return; }
+        let ll = MapUtil.map.unproject(point, zoom);
         return {lat: ll.lat, lng: ll.lng};
     }
 
@@ -81,8 +82,8 @@ export default class MapUtil {
      * @returns {number} - 比例因子
      */
     static scale(toZoom, fromZoom){
-        if(!MyMap.map){ console.error("请先初始化地图!"); return; }
-        return MyMap.map.getZoomScale(toZoom, fromZoom);
+        if(!MapUtil.map){ console.error("请先初始化地图!"); return; }
+        return MapUtil.map.getZoomScale(toZoom, fromZoom);
     }
 
     /** 
@@ -92,8 +93,8 @@ export default class MapUtil {
      * @returns {number} - 缩放级别
      */
     static zoom(scale, fromZoom){
-        if(!MyMap.map){ console.error("请先初始化地图!"); return; }
-        return MyMap.map.getScaleZoom(scale, fromZoom);
+        if(!MapUtil.map){ console.error("请先初始化地图!"); return; }
+        return MapUtil.map.getScaleZoom(scale, fromZoom);
     }
 
     /** 
@@ -103,11 +104,11 @@ export default class MapUtil {
      * @returns {number} - 距离(单位:米)
      */
     static distance(latlng1, latlng2){       
-        if(!MyMap.map){ console.error("请先初始化地图!"); return; } 
+        if(!MapUtil.map){ console.error("请先初始化地图!"); return; } 
 		let ll1 = new LatLng(latlng1.lat, latlng1.lng);
 		let ll2 = new LatLng(latlng2.lat, latlng2.lng);
 		// let distance = ll1.distanceTo(ll2) / 1000;
-        return MyMap.map.distance(ll1, ll2);
+        return MapUtil.map.distance(ll1, ll2);
     }
 
     /**