Leaflet(1) —– leaflet + GeoJSON + ( Navigator对象的geoLocation获取当前位置 )

(一) 安装

yarn add leaflet

(二) 使用

(1) 在index.html中添加地图显示的容器

index.html

<div id="map" style="width:1000px; height:700px; display:block; margin: 10px"></div>




也可以把leaflet的css文件引入index.html ----- 则在js页面不引入
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.1.0/dist/leaflet.css" integrity="sha512-wcw6ts8Anuw10Mzh9Ytw4pylW8+NAD4ch3lqm9lzAsTxg0GFeJgoAtxuCLREZSC5lUXdVyo/7yfsqFjQ4S+aKw==" crossorigin="" />


(2) 引入并使用

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import L from 'leaflet';                     // 引入leaflet js
import 'leaflet/dist/leaflet.css';           // 引入leaflet css

class App extends Component {
  constructor(props) {
    super(props)
    this.map = null                          // 初始化map属性
  }
  componentDidMount() {
    const MAP = this.map = L.map('map', {    // 加载leaflet中心类   --- map类
      center: [39.9788, 116.30226],          // L.map(容器id, 配置项 )
      zoom: 18
    })

    L.tileLayer('http://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}', {
      subdomains: "1234",
      attribution: '高德地图'
    }).addTo(this.map);                 // 把瓦片图层添加到map上,map需要加载地图图层,即显示的内容

  }
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Welcome to React</h1>
        </header>
      </div>
    );
  }
}

export default App;




6493119-dd8ddf7bd99c5e2b.jpg
22222.jpg

map 常用配置项

    const MAP = this.map = L.map('map', {   // L.map(DOM, options)
      center: [39.9788, 116.30226],    // 初始化地图的地理中心
      zoom: 18,                        // 缩放
      zoomControl: true,               // 缩放控制开启和关闭
      attributionControl: true,        // 属性控制,可以通过 L.tileLayer().getAttribution()得到
      dragging: true,                  // 拖动控制
      layers: [tileX],                 // 初始化加载的图层     ---- 重要重要重要
      maxZoom: 18,                     // 最大缩放
      minZoom: 1,                      // 最小缩放
      crs: L.CRS.EPSG3857,      //要使用的坐标参考系统,默认的坐标参考系,互联网地图主流坐标系
     // crs: L.CRS.EPSG4326,    //WGS 84坐标系,GPS默认坐标系
    })


     crs 是 Coordinate Reference System 的缩写   -------  坐标参考系统

TileLayer常用配置项

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}{r}.png?{foo}', {foo: 'bar'}).addTo(..)

{s}:       subdomains 表示可用的子域
{z}:       zoom 表示缩放
{x}, {y}:  tile coordinates 表示坐标
{r} :      can be used to add "@2x" to the URL to load retina tiles

L.tileLayer(url, options)

const tileX = L.tileLayer(url, {
   subdomains: "1234",
   attribution: '高德地图'
 });

marker,popup,tooltip


    const marker = L.marker([39.9788, 116.30226]).addTo(this.map);  // 添加marker到地图

    marker.bindPopup('点击marker,显示popup')   // 给marker绑定Popup,点击marker时显示

    marker.bindTooltip("my tooltip text")    // 给marker绑定tooltip,hover时显示

    const marker2 = L.marker([39.9790, 116.30248], {    // marker的属性配置
      title: '这是marker2的title',
      icon:L.icon({                         // 更换maker的图标
        iconUrl: 'my-icon.png',
        iconSize: [38, 95],
        iconAnchor: [22, 94],
        popupAnchor: [-3, -76],
        shadowUrl: 'my-icon-shadow.png',
        shadowSize: [68, 95],
        shadowAnchor: [22, 94]
      })
    }).addTo(this.map)

circle,polyline,polygon多边形,rectangle矩形

   L.circle([39.9788, 116.30226], {radius: 50}).addTo(this.map);        // 圆

    var latlngs = [
      [39.9790, 116.30248],
      [39.9790, 116.30270],
      [39.9793, 116.30270],
      [39.9790, 116.30290],
    ];
    var latlngs2 = [
      [39.9790, 116.30208],
      [39.9790, 116.30250],
      [39.9793, 116.30250],
      [39.9790, 116.30208],
    ];
    var latlngs3 = [
      [45.51, -122.68],
      [37.77, -122.43],
      [34.04, -118.2]
  ];
  var polyline = L.polyline(latlngs, {color: 'red'}).addTo(this.map);      // 线条
  this.map.fitBounds(polyline.getBounds());               //填充边界,定位地图
 
  var latlngs = [latlngs];
  var polygon = L.polygon(latlngs2, {color: 'green'}).addTo(this.map);   // 多边形
  this.map.fitBounds(polygon.getBounds());

  var polyline = L.polyline(latlngs3, {color: 'red'}).addTo(this.map);



 // define rectangle geographical bounds     
 // geographical 地里的
 var bounds = [[54.559322, -5.767822], [56.1210604, -3.021240]];
 // create an orange rectangle
 L.rectangle(bounds, {color: "#ff7800", weight: 1}).addTo(map);
 // zoom the map to the rectangle bounds
 map.fitBounds(bounds);

添加图片做为地图

let imageUrl = 'http://www.lib.utexas.edu/maps/historical/newark_nj_1922.jpg',
let imageBounds = [[40.712216, -74.22655], [40.773941, -74.12544]];  
// 注意: bounds是边界,是 ( southWest ) 和 ( northEast ) 的值

L.imageOverlay(imageUrl, imageBounds).addTo(map);

获取用户当前的位置信息

地理位置 API 通过 navigator.geolocation 提供

  • navigator.geolocation 获取地理位置
  • getCurrentPosition 函数获取用户当前定位位置。
 const xyz = navigator.geolocation.getCurrentPosition((x) => {
    const xi = x.coords.latitude;
    const yi = x.coords.longitude;
    L.marker([xi, yi]).addTo(MAP);   // 用marker显示在地图上
 });

切换不同图层

class App extends Component {
  constructor(props) {
    super(props);
    this.map = null
  }
  componentDidMount() {

    const gaode = L.tileLayer('...', {
      subdomains: "1234",
      attribution: '高德地图'
    })

    const mapbox = L.tileLayer( '...', {
      attribution: '谷歌地图',
      subdomains: "1234",
    })

    var mymap = this.map = L.map('map', {
      center: [39.9788, 116.30226],
      zoom: 18,
      layers: [mapbox],
      drawControl: true
    })

    L.control.layers({            // L.control.layers
      '高德地图': gaode,
      '谷歌地图': mapbox,
    }).addTo(this.map)
}

把GeoJSON中的 coordinates 转换成 LatLng


    const aaa = [39.9788, 116.30226];
    const bbb = L.GeoJSON.coordsToLatLng(aaa);
    console.log(bbb)     
    // LatLng {lat: 116.30226, lng: 39.9788}


    const ccc = L.GeoJSON.latLngToCoords(bbb);
    console.log(ccc)
    // [39.9788, 116.30226]
  





GeoJSON对象

GeoJSON是一种对各种地理数据结构进行编码的格式。
GeoJSON对象可以表示几何、特征或者特征集合。(geometry, feature, featureCollection
GeoJSON支持这几种 几何类型:点、线、面、多点、多线、多面和几何集合。
GeoJSON里的特征包含一个几何对象和其他属性,特征集合表示一系列特征。

  • GeoJSON对象必须由一个名字为”type”的成员。这个成员的值是由GeoJSON对象的类型所确定的字符串。
    type成员的值必须是下面之一:"Point"点, "MultiPoint"多点, "LineString", "MultiLineString", "Polygon", "MultiPolygon", "GeometryCollection"几何集合, "Feature", 或者 "FeatureCollection"特征集合
  • GeoJSON对象可能有一个可选的”crs”成员,它的值必须是一个坐标参考系统的对象
    crs 是 Coordinate Reference System 的缩写 ------- 坐标参考系统
  • GeoJSON对象可能有一个”bbox”成员,它的值必须是边界框数组
    boundary边界

(1) 几何对象 geometry

geometry对象包含 ( type属性 ) 和 ( coordinates属性 – 总是数组 )

  • 几何是一种GeoJSON对象,这时type成员的值是下面字符串之一:”Point”, “MultiPoint”, “LineString”, “MultiLineString”, “Polygon”, “MultiPolygon”, 或者”GeometryCollection”。

  • 除了“GeometryCollection”外的其他任何类型的GeoJSON几何对象必须由一个名字为”coordinates”的成员。coordinates成员的值总是数组。这个数组里的元素的结构由几何类型来确定。

(2) 位置 coordinates

coordinates 总是数组 (数组或者嵌套数组)

  • 位置是基本的几何结构。几何对象的”coordinates”成员由一个位置(这儿是几何点)、位置数组(线或者几何多点),位置数组的数组(面、多线)或者位置的多维数组(多面)组成。

  • 位置由数字数组表示。必须至少两个元素,可以有更多元素。元素的顺序必须遵从x,y,z顺序(投影坐标参考系统中坐标的东向、北向、高度或者地理坐标参考系统中的坐标长度、纬度、高度

(3) 特征对象 Feature

Feature对象必须包含 ( geometry属性 ) 和 ( properties属性 )

类型为”Feature”的GeoJSON对象是特征对象。

  • 特征对象必须由一个名字为”geometry”的成员,这个几何成员的值是上面定义的几何对象或者JSON的null值。
  • 特征对戏那个必须有一个名字为“properties”的成员,这个属性成员的值是一个对象(任何JSON对象或者JSON的null值)。
  • 如果特征是常用的标识符,那么这个标识符应当包含名字为“id”的特征对象成员。

(4) 特征集合对象 FeatureCollection

FeatureCollection对象必须包含 ( features属性 ),是一个数组

类型为”FeatureCollection”的GeoJSON对象是特征集合对象。

  • 类型为”FeatureCollection”的对象必须由一个名字为”features”的成员。与“features”相对应的值是一个数组。这个数组中的每个元素都是上面定义的特征对象
{ "type": "FeatureCollection",   // GeoJSON对象必须有个type属性,这里值是 特征集合
  "features": [
    { "type": "Feature",      // Feature<Point>
      "geometry": {"type": "Point", "coordinates": [102.0, 0.5]},  // Geometry<Point>
      "properties": {"prop0": "value0"}
      },
    { "type": "Feature",    // 线数据
      "geometry": {
        "type": "LineString",
        "coordinates": [
          [102.0, 0.0], [103.0, 1.0], [104.0, 0.0], [105.0, 1.0]
          ]
        },
      "properties": {
        "prop0": "value0",
        "prop1": 0.0
        }
      },
    { "type": "Feature",
       "geometry": {
         "type": "Polygon",   // 多边形数据
         "coordinates": [
           [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0],
             [100.0, 1.0], [100.0, 0.0] ]
           ]
       },
       "properties": {
         "prop0": "value0",
         "prop1": {"this": "that"}
         }
       }
     ]
   }





// 2018.6.9更 ————– // 复习面向对象

        // 构造函数
            // 1. 首字母大写
            // 2. 函数内部使用this代表将要生成的实例对象
            // 3. 使用new命令,执行构造函数,返回实例对象
        
        // 忘记写 new命令
            // 在构造函数内部使用 'use strict'严格模式,在忘记new命令时,就会报错

        // return 
            // 构造函数内部,如果有return语句,
                // 1. return 后面跟一个对象,new命令就会返回该对象
                // 2. return 后满跟的不是一个对象, new就会返回this指代的实例对象

        // 对普通函数使用new命令,return后面跟的不是对象,会返回一个空对象

        // new命令总是返回一个对象,实例对象,或者return 指定的对象, 普通函数使用new命令,返回空对象或者return 指定的对象

        // Object.create() 创建实例对象
            // 1.构造函数为模板,可以生成实例对象,但有时,拿不到实例对象,只能通过现有的对象为模板,生成实例对象

        // ------------------------------------------------
        
        // this
            // this不管用在什么场合,都是返回一个对象

            // this是属性和方法当前所在的对象
                // 对象的属性可以赋值给另一个对象,所以,属性所在的当前对象是可变的,即 this的指向是可变的
                
            // 只要函数被赋值给另一个变量,this的指向就会变
            
            // 总结
                // this是函数运行时所在的对象 !!!!
                    // 在js中一切皆对象,运行环境也是对象,所以,函数都在某个对象中运行
                    // this就是函数运行时所在的对象

            // this的使用场合
                // 1.全局环境
                    // 全局环境使用this, this指的是顶层对象,即window对象
                // 2.构造函数
                    // 在构造函数中,this指向将要生成的实例对象
                // 3.对象的方法
                    // 在对象的方法中,this指向方法运行时,所在的对象
            // 注意
                // 如果this所在的方法不在对象的第一层,this只是指向当前一层的对象,而不会继承更上面的层 !!
                
                // 如果,将嵌套对象内部的方法赋值给一个变量,this依然会指向全局对象window 

                // 嵌套的this
                    // 使用一个变量固定this的值,然后内层函数调用这个变量,是非常常见的做法

            // Function.prototype.call(参数1, 参数2, ....)
                // 函数实例的call方法,可以指定函数内部this的指向,然后在所指定的作用域中,调用该函数

                // call()方法的参数是一个 对象, 如果参数是空,null, undefined,则默认传入全局对象

                // call()方法可以传入多个参数,第一个参数是所要绑定的对象,后面的参数是函数调用时传入的参数

                // call()方法会自动调用函数 ---- bind()方法则不会自动调用

            // Function.prototype.apply(参数1, [参数2, 参数3 , ...])    
                // apply方法的作用与call方法类似,也是改变this指向,然后再调用该函数。
                // 唯一的区别就是,它接收一个数组作为函数执行时的参数

            // Function.prototype.bind(参数1, 参数2, ....)
                // bind方法用于将函数体内的this绑定到某个对象,然后返回一个新函数
    

算法:

  1. 找出数组中最大的元素
var a = [1,11,111,30,40];
const b = Math.max.apply(null, a);   // Math.max() 是一个函数
console.log(b) // 111

Function.prototype.apply(需要绑定的对象,数组参数) // 第一个参数时null和undefined时,绑定全局对象

  1. 将数组的 ( 空元素 ) 替换成 ( undefined )
Array.apply(null, ['a', ,'b'])

// [ 'a', undefined, 'b' ]

prototype对象

  1. 构造函数的缺点
    同一个构造函数的多个实例,无法共享属性。(造成系统资源的浪费)
    构造函数的属性和方法都会生成在实例对象上
   const A = function() {
     this.name = function() {
        console.log('not equal')
      }
    };
    const b = new A();
    const c = new A();
    console.log(b.name === c.name)  // false

  // 构造函数的name方法,会定义在实例对象上,即 每个实例都会生成name方法
  1. 原型对象prototype
    原型对象的所有属性和方法都能被实例对象所共享

  2. js规定,每一个函数都有一个prototype属性,指向一个对象
    对于普通函数来说,该属性基本无用。但是,对于构造函数来说,生成实例的时候,该属性会自动成为实例对象的原型。

  • 对于构造函数来说,构造函数的prototype属性,会在构造函数生成实例对象的时候,自动成为实例对象的原型对象!!!
    // 对于构造函数,prototype属性会在生成实例对象的时候,成为实例对象的原型对象
    // 原型对象的属性和方法,被实例对象所共享
  • 原型对象的属性不是实例对象自身的属性。只要修改原型对象,变动就立刻会体现在所有实例对象上。
  • 当实例对象本身没有某个属性或方法的时候,它会到原型对象去寻找该属性或方法。
    如果实例对象自身就有某个属性或方法,它就不会再去原型对象寻找这个属性或方法。

总结: 原型对象的作用就是定义所有实例对象所共享的属性和方法,这也是它被称为原型对象的原因,而实例对象可以视作从原型对象衍生出来的子对象。

function Animal(name) {
  this.name = name;
}
Animal.prototype.color = 'white';   // 任何函数的prototype属性都指向一个对象

var cat1 = new Animal('大毛');
var cat2 = new Animal('二毛');

cat1.color // 'white'
cat2.color // 'white'

// 对于构造函数,prototype属性会在生成实例对象的时候,成为实例对象的原型对象
// 原型对象的属性和方法,被实例对象所共享

原型链

  1. JavaScript 规定,所有对象都有自己的原型对象(prototype)。
    一方面,任何一个对象,都可以充当其他对象的原型;
    另一方面,由于原型对象也是对象,所以它也有自己的原型。
    因此,就会形成一个“原型链”(prototype chain):对象到原型,再到原型的原型……
  2. 如果一层层上溯,所有对象的原型最终可以上溯到Object.prototype
    ( 即Object构造函数的prototype属性 )
  • 所有对象都继承了Object.prototype属性上的 属性和方法
    这就是所有对象都有valueOf和toString方法的原因,因为这是从Object.prototype继承的。
  • Object.prototype的原型是null,由于null没有任何属性,所以原型链到此为止。

3.读取属性时,如果本身对象没有该属性,就是上溯到该对象的原型对象上寻找,如果还没有,就一个向上到Object.prototype,如果还没有就返回 undefined

4.自身和原型有同名属性时,优先读取自身对象上的属性 —— 这叫做”覆盖”。

5. constructor 属性

prototype对象默认有一个constructor属性,指向prototype对象所在的构造函数

function P() {}
P.prototype.constructor === P // true
  • constructor属性定义在prototype对象上,因此,可以被实例对象所继承
const A = function() {
   console.log('这是一个构造函数')
};
const b = new A();

console.log( A.prototype.constructor === b.constructor );  //true
console.log( A.prototype.constructor === A);  //true
console.log( b.constructor === A);   //true
console.log( b.hasOwnProperty('constructor'));  // false ------- 不是自身属性
  1. constructor属性的作用
  • 1.constructor属性的作用,可以得知,实例对象到底是由哪个构造函数产生的
    1. 有了constructor,就可以从一个实例对象新建另一个实例对象

     const A = function() {
         console.log('这是构造函数A');
     };

     const b = new A();

     const c = new b.constructor();    // b.constructor === A === A.prototype.constructor

     console.log( c instanceof A );     // c 是 A 的实例    ----- 注意 instanceof 是小写 of

  • 修改原型对象时,一般要同时修改 constructor 属性
  1. constructor.name构造函数的名称
function Foo() {}
var f = new Foo();
f.constructor.name // "Foo"

8. instanceof 运算符

instanceof 返回一个boolean布尔值,表示对象是否是构造函数的实例

var v = new Vehicle();

v instanceof Vehicle // true

// instanceof是 实例的意思

instanceof运算符的左边是实例对象,右边是构造函数。

  1. instanceof会检查右边构建函数的原型对象(prototype),是否在左边对象的原型链上。
    因此,下面两种写法是等价的。
var v = new Vehicle();

v instanceof Vehicle
// 等同于
Vehicle.prototype.isPrototypeOf(v)
特例:

instanceof的原理是检查右边构造函数的prototype属性,是否在左边对象的原型链上。
有一种特殊情况,就是左边对象的原型链上,只有null对象。这时,instanceof判断会失真。

instanceof的用处:

instanceof运算符的一个用处,是判断值的类型。

  • 注意,instanceof运算符只能用于对象,不适用原始类型的值。
var x = [1, 2, 3];
var y = {};
x instanceof Array // true
y instanceof Object // true

console.log(typeof x)   // object  ---- 注意:数组的typeof是object



-----------------------------------------------
注意: instanceof只能用于对象,不能用于原始类型的值
var s = 'hello';
s instanceof String // false


object对象的相关方法

Object.getPrototypeOf()

Object.getPrototypeOf方法返回参数对象的原型。这是获取原型对象的标准方法。

  • Object.getPrototypeOf() 返回参数对象的原型对象
var F = function () {};
var f = new F();
Object.getPrototypeOf(f) === F.prototype // true


-----------------------------------------------------------------

    const a = {};
    const b = {name: 'wang'};
    a.__proto__ = b;
    console.log(a.name)   // wang

    // a.__proto__ = b  等价于  Object.setPrototypeOf(a,b);     !!!!!!!!!
  • 注意:
    根据语言标准,proto属性只有浏览器才需要部署,其他环境可以没有这个属性。它前后的两根下划线,表明它本质是一个内部属性,不应该对使用者暴露。因此,应该尽量少用这个属性,而是用Object.getPrototypeof()和Object.setPrototypeOf(),进行原型对象的读写操作。


获取实例对象的原型对象有三种方法

1. obj.__proto__
2. obj.constructor.prototype
3. Object.getPrototypeOf(obj)



上面三种方法之中,前两种都不是很可靠。

__proto__属性只有浏览器才需要部署,其他环境可以不部署。

而obj.constructor.prototype在手动改变原型对象时,可能会失效。


Object.getOwnPropertyNames()

Object.getOwnPropertyNames方法返回一个数组,成员是参数对象本身的所有属性的键名,不包含继承的属性键名。

Object.prototype.hasOwnProperty()

hasOwnProperty ————- 自身属性

对象实例的hasOwnProperty方法返回一个布尔值,用于判断某个属性定义在对象自身,还是定义在原型链上。

hasOwnProperty方法是 JavaScript 之中唯一一个处理对象属性时,不会遍历原型链的方法。!!!!!!!!!!

  • hasOwnProterty是唯一一个处理对象属性时,不会遍历原型链的方法 !!!

in 运算符 ——————- 不区分自身属性和继承属性

in运算符返回一个布尔值,表示一个对象是否具有某个属性。它不区分该属性是对象自身的属性,还是继承的属性。

对象的拷贝

如果要拷贝一个对象,需要做到下面两件事情。

  1. 确保拷贝后的对象,与原对象具有同样的原型。
  2. 确保拷贝后的对象,与原对象具有同样的实例属性。
  • 拷贝对象需要做到两点,与元对象具有相同的原型和相同的实例属性

转载自:https://blog.csdn.net/weixin_34152820/article/details/88135615

You may also like...