Angular 2+和实现传单地图(开放式街道地图) [英] Angular 2+ and implementing Leaflet maps (Open Street Map)

查看:79
本文介绍了Angular 2+和实现传单地图(开放式街道地图)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在我的网页上实现(ASP.NET Core SPA模板(使用Angular 2+-由yeoman生成)传单地图.

I would like to implement on my web page (ASP.NET Core SPA template (with Angular 2+ - generated with yeoman) Leaflet maps.

所以我在leafletjs.com上搜索了教程

So I search for tutorial on leafletjs.com

首先测试了此示例(它可以独立运行):

Firstly tested this example (and it works as standalone):

<html>
<head>
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css"
   integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ=="
   crossorigin=""/>
    <script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet.js"
   integrity="sha512-A7vV8IFfih/D732iSSKi20u/ooOfj/AGehOKq0f4vLT1Zr2Y+RX7C+w8A1gaSasGtRUZpF/NZgzSAu4/Gc41Lg=="
   crossorigin=""></script>

   <style>
       #map { height: 180px; }
    </style>
</head>

<body>   
<div id="map"></div>


<script>
    var map = L.map('map').setView([50.0817444,19.9253805], 13);

L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
    attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);

L.marker([50.0817444,19.9253805]).addTo(map)
    .bindPopup('A pretty CSS3 popup.<br> Easily customizable.')
    .openPopup();
</script>

</body>
</html>

比起我尝试在Angular 2+中使用它并创建一些简单的组件(如LeafletMapComponent.),我已经完成了以下步骤:

Than I have tried to use it with Angular 2+ and create some simple component like LeafletMapComponent. I have done below steps:

  1. 将依赖项添加到 package.json

"dependencies": {
    ...
   "leaflet":"^1.0.3"
    ...
}
"devDependencies": {
    ...
    "@types/geojson":"^1.0.2",
    "@types/leaflet":"^1.0.60"
}

  1. webpack.config.vendor.js
  2. 中添加传单
  1. add leaflet in webpack.config.vendor.js

entry: {
            vendor: [
                '@angular/common',
                '@angular/compiler',
                '@angular/core',
                '@angular/http',
                '@angular/platform-browser',
                '@angular/platform-browser-dynamic',
                '@angular/router',
                '@angular/platform-server',
                'angular2-universal',
                'angular2-universal-polyfills',
                'bootstrap',
                'bootstrap/dist/css/bootstrap.css',
                'es6-shim',
                'es6-promise',
                'event-source-polyfill',
                'jquery',
                'zone.js',
                'leaflet',
            ]
        },
        output: {
            publicPath: '/dist/',
            filename: '[name].js',
            library: '[name]_[hash]'
        },

  1. 然后我用如此简单的代码创建了新组件

import {Component, OnInit} from '@angular/core'; 
  import * as L from 'leaflet';

@Component({
    selector: 'leaflet-map',
    templateUrl: 'leaflet-map.component.html',
    styleUrls: ['leaflet-map.component.css', '../../../..//node_modules/leaflet/dist/leaflet.css'], }) export class
 LeafletMapComponent implements OnInit { 

    ngAfterViewInit() {
            L.map('leafletMap').setView([50.0817444,19.9253805], 13);
    }

    ngOnInit() {  

    }    
  }

  1. 当然我也应用了#leafletMap div和样式

 #leafletMap { 
     height: 400px; 
     width: 600px;
  }

  <div id="leafletMap"></div>

  1. 我已经运行了这样的应用程序:

  $ npm install
  $ rimraf dist && ./node_modules/.bin/webpack --config  
   webpack.config.vendor.js && ./node_modules/.bin/webpack --config
   webpack.config.js
  $ dot net run

但是我仍然收到这样的错误:

But I am still getting an error like this:

失败:Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware [0] 发生未处理的异常:调用Node模块失败,并显示以下错误:由于错误,Prerendering失败:ReferenceError: 窗口未定义

fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[0] An unhandled exception has occurred: Call to Node module failed with error: Prerendering failed because of error : ReferenceError: window is not defined

推荐答案

似乎您在ASP.NET Core Angular启动程序中使用Angular Universal(服务器端渲染).在服务器端,没有定义窗口对象(LeafletMap可能在内部使用).

It seems like you are using Angular Universal (server side rendering) in your ASP.NET Core Angular starter. On server side there is no window object defined (that LeafletMap might use internally).

有两种选择:

  1. 通过从Views/Home/Index.cshtml中的元素中删除asp-prerender-module属性来禁用项目中的服务器端呈现.
  2. 通过在代码中实现专用的执行分支,将LeafletMap的使用范围限制为客户端部分(请参见
  1. Disable server side rendering in your project by removing asp-prerender-module attribute from the element in Views/Home/Index.cshtml.
  2. Limit the use of LeafletMap to the client side part by implementing a dedicated execution branch in your code (see https://github.com/angular/universal#universal-gotchas)

编辑

根据选项2,您必须注意,在加载第三方库(如jquery或LeafletMap)时,没有万能药.只是import语句本身(如果未在代码优化中将其删除)会在服务器端引起奇怪的副作用.一种可能"的做法(因为没有最佳"的做法)可以是实现有条件地加载这些库的服务.

According to option 2 you must note that there is no panacea on that when loading third party libraries like jquery or LeafletMap. Just the import statement itself (if not removed on code optimization) can cause strange side effects on server side. A "possible" practice (since there is no "best" practice) can be to implement a service that conditionally loads those libraries.

import { Injectable, Inject, PLATFORM_ID, Component, OnInit } from '@angular/core';
import { isPlatformBrowser, isPlatformServer } from '@angular/common';

@Injectable()
export class LegacyService {
    private _L : any;
    private _jquery : any;

    public constructor(@Inject(PLATFORM_ID) private _platformId: Object) {
        this._init();
    }

    public getJquery() {
        return this._safeGet(() => this._jquery);
    }

    public getL() {
        return this._safeGet(() => this._L);
    }

    private _init() {
        if(isPlatformBrowser(this._platformId)){
            this._requireLegacyResources();     
        }
    }

    private _requireLegacyResources() {
        this._jquery = require('jquery');
        this._L = require('leaflet');
    }

    private _safeGet(getCallcack : () => any) {
        if(isPlatformServer(this._platformId)){
            throw new Error ('invalid access to legacy component on server');
        }

        return getCallcack();
    }
}

在组件实现上,您还应该实现仅在客户端使用服务的条件分支:

On component implementation you should also implement conditional branches that only use the service on client side:

ngAfterViewInit() {
    if(isPlatformBrowser(this.platformId)){
      this._legacyService.getL().map('leafletMap').setView([50.0817444,19.9253805], 13);
    }
  }

这篇关于Angular 2+和实现传单地图(开放式街道地图)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆