angular id标记_使用传单在Angular中构建地图,第2部分:标记服务

news/2024/7/6 1:53:48

angular id标记

In my last post, we set up our environment to create a basic map using Leaflet and Angular. Let’s go a bit further now and add markers to our map.

在上一篇文章中 ,我们设置了环境以使用Leaflet和Angular创建基本地图。 现在让我们再走一点,在地图上添加标记。

Maps are great, but augmenting our maps with data is even better. Let’s discuss how we can add markers to our map in an Angular way. That is, we’ll be using a service to manage our marker logic.

地图很棒,但是用数据扩充我们的地图更好。 让我们讨论如何以Angular方式向地图添加标记。 也就是说,我们将使用服务来管理标记逻辑。

建立 (Setup)

Recall that our directory structure looked like this:

回想一下我们的目录结构如下:

leaflet-example
|_ node_modules/
|_ package.json
\_ src/
    \_ app/
        |_ app.module.ts
        |_ app.routing.ts
        |_ app.component.ts
        |_ app.component.html
        |_ app.component.scss
        |
        |_ map/
        |     |_ map.component.ts
        |     |_ map.component.html
        |     \_ map.component.scss
        |
        \_ _services/

Navigate to the _services/ directory at the CLI and generate the service that will be responsible for managing our marker data:

导航至CLI的_services/目录,并生成将负责管理标记数据的服务:

$ ng generate service marker

Add this new service as a provider in your app.module.ts. We’ll also be loading the data from our assets folder so we’ll need to include the HttpClientModule In all, our new app.module.ts should look like this:

将此新服务添加为您的app.module.ts的提供者。 我们还将从资产文件夹中加载数据,因此我们需要包括HttpClientModule 。总之,新的app.module.ts应该如下所示:

app.module.ts
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { MapComponent } from './map/map.component';
import { MarkerService } from './_services/marker.service';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [
    AppComponent,
    MapComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [
    MarkerService
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

The data I’ll be plotting is stored as a GeoJSON containing the US State capitals. I’ve also added properties to each capital including the state name, capital name, and population. We’ll be using these additional properties later, for now let’s just load the data and plot them as markers.

我将要绘制的数据存储为包含美国州首府的GeoJSON 。 我还向每个首都添加了属性,包括州名称,首都名称和人口。 稍后我们将使用这些附加属性,现在让我们仅加载数据并将其绘制为标记。

加载和绘制标记 (Loading and Plotting Markers)

Open up your newly minted marker.service.ts and add HttpClient to the constructor. Let’s also declare the path to the geojson file.

打开新marker.service.ts并将HttpClient添加到构造函数中。 我们还要声明geojson文件的路径。

marker.service.ts
标记服务
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class MarkerService {

  capitals: string = '/assets/data/usa-capitals.geojson';

  constructor(private http: HttpClient) {
  }
}

Create a new function that will load the geojson data and create the markers. I’ll call mine makeCapitalMarkers. This function will take in a Leaflet map as a parameter, so we have to import Leaflet into this service.

创建一个新函数,该函数将加载geojson数据并创建标记。 我将其命名为makeCapitalMarkers 。 此功能将以Leaflet映射作为参数,因此我们必须将Leaflet导入此服务。

marker.service.ts
标记服务
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import * as L from 'leaflet';

@Injectable({
  providedIn: 'root'
})
export class MarkerService {

  capitals: string = '/assets/data/usa-capitals.geojson';

  constructor(private http: HttpClient) {
  }

 makeCapitalMarkers(map: L.map): void {

  }
}

Using HttpClient, get the data and subscribe to the result. Once we have our data, we then loop through each feature, construct a marker, and add it to the map.

使用HttpClient ,获取数据并订阅结果。 有了数据后,我们便遍历每个要素,构造一个标记,然后将其添加到地图中。

marker.service.ts
标记服务
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import * as L from 'leaflet';

@Injectable({
  providedIn: 'root'
})
export class MarkerService {

  capitals: string = '/assets/data/usa-capitals.geojson';

  constructor(private http: HttpClient) {
  }

  makeCapitalMarkers(map: L.map): void {
    this.http.get(this.capitals).subscribe((res: any) => {
      for (const c of res.features) {
        const lat = c.geometry.coordinates[0];
        const lon = c.geometry.coordinates[1];
        const marker = L.marker([lon, lat]).addTo(map);
      }
    });
  }
}

We’ve now written the logic for loading and adding our markers to our map, so now all we have to do now is call this method from MapComponent.

现在,我们已经编写了将标记加载和添加到地图的逻辑,因此现在要做的就是从MapComponent调用此方法。

map.component.ts
map.component.ts
import { AfterViewInit, Component } from '@angular/core';
import * as L from 'leaflet';
import { icon, Marker } from 'leaflet';
import { MarkerService } from '../_services/marker.service';

@Component({
  selector: 'app-map',
  templateUrl: './map.component.html',
  styleUrls: ['./map.component.scss']
})
export class MapComponent implements AfterViewInit {

  private map;

  constructor(private markerService: MarkerService) {
  }

  ngAfterViewInit(): void {
    this.initMap();
    this.markerService.makeCapitalMarkers(this.map);
  }

  private initMap(): void {
    this.map = L.map('map', {
      center: [39.8282, -98.5795],
      zoom: 3
    });

    const tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
      maxZoom: 19,
      attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
    });

    tiles.addTo(this.map);
  }
}


At the time of writing this, there is a known Leaflet bug causing default marker images to not display.

在撰写本文时,有一个已知的Leaflet Bug,导致默认标记图像无法显示。

When using the Angular CLI, Leaflet’s assets don’t get properly copied to our build folder causing the app to complain that markers are missing. If your markers aren’t showing up check your browser’s console for any error messages similar to this:

使用Angular CLI时,Leaflet的资产未正确复制到我们的build文件夹中,导致应用程序抱怨缺少标记。 如果您的标记未显示,请检查浏览器的控制台中是否有类似以下内容的错误消息:

marker-icon-2x.png:1 Failed to load resource: the server responded with a status of 404 (Not Found)
marker-shadow.png:1 Failed to load resource: the server responded with a status of 404 (Not Found)

This is remedied by doing a couple things:

通过执行以下几项操作可以纠正此问题:

  • Edit our angular.json file to copy Leaflet’s assets locally

    编辑我们的angular.json文件以在本地复制Leaflet的资产

  • Set the default icon in the marker prototype

    在标记原型中设置默认图标

To do the first step, open up angular.json and add the following lines to your “assets” stanza:

要执行第一步,请打开angular.json并将以下行添加到“资产”节中:

angular.json
angular.json
"assets": [
  "src/favicon.ico",
  "src/assets",
  {
    "glob": "**/*",
    "input": "node_modules/leaflet/dist/images/",
    "output": "./assets"
  }
],

This will copy leaflet’s marker images locally.

这将在本地复制传单的标记图像。

Then, in map.component.ts add the following lines before the @Component to set the marker icon:

然后,在map.component.ts ,在@Component之前添加以下几行以设置标记图标:

map.component.ts
map.component.ts
const iconRetinaUrl = 'assets/marker-icon-2x.png';
const iconUrl = 'assets/marker-icon.png';
const shadowUrl = 'assets/marker-shadow.png';
const iconDefault = L.icon({
  iconRetinaUrl,
  iconUrl,
  shadowUrl,
  iconSize: [25, 41],
  iconAnchor: [12, 41],
  popupAnchor: [1, -34],
  tooltipAnchor: [16, -28],
  shadowSize: [41, 41]
});
L.Marker.prototype.options.icon = iconDefault;


Run your app and launch http://localhost:4200 to see your state capitals.

运行您的应用程序并启动http:// localhost:4200来查看您的州首字母。

Success! 🏆

成功! 🏆

圆形标记 (Circle Markers)

We can now load and plot our markers. However, suppose that we want to visualize the relative sizes of the capital populations. Earlier, I mentioned that I added population data to the geojson properties, so all we have to do is leverage this property in some way when plotting the markers. Let’s do this by creating circle markers instead of the default markers.

现在,我们可以加载并绘制标记。 但是,假设我们要可视化资本人口的相对规模。 之前,我提到我将填充数据添加到geojson属性,因此我们要做的就是在绘制标记时以某种方式利用此属性。 通过创建圆形标记而不是默认标记来实现。

In our MarkerService, let’s create a different function called makeCapitalCircleMarkers() that will create circle markers instead of regular markers.

在我们的MarkerService ,我们创建另一个名为makeCapitalCircleMarkers()函数,该函数将创建圆形标记而不是常规标记。

marker.service.ts
标记服务
makeCapitalCircleMarkers(map: L.map): void {
    this.http.get(this.capitals).subscribe((res: any) => {
      for (const c of res.features) {
        const lat = c.geometry.coordinates[0];
        const lon = c.geometry.coordinates[1];
        const circle = L.circleMarker([lon, lat]).addTo(map);
      }
    });

Call this function in MapComponent:

在MapComponent中调用此函数:

map.component.ts
map.component.ts
ngAfterViewInit(): void {
    this.initMap();
    // this.markerService.makeCapitalMarkers(this.map);
    this.markerService.makeCapitalCircleMarkers(this.map);
  }

Hey, nice circles you got there, but that doesn’t tell me anything about the population size. One thing to mention is that the circle marker styles can be set upon initialization using an optional parameters object, and one of these styles includes the circle’s radius. We’ll set the radius of each circle using this way. For example, we can set each circle’s radius to 20 using the following:

嘿,您到过的圈子不错,但这并没有告诉我有关人口数量的任何信息。 值得一提的是,圆形标记样式可以在初始化时使用可选参数对象进行设置,其中一种样式包括圆形的半径。 我们将使用这种方式设置每个圆的半径。 例如,我们可以使用以下命令将每个圆的半径设置为20:

marker.service.ts
标记服务
const circle = L.circleMarker([lon, lat], 
    {
      radius: 20
    }
).addTo(map);

This sizes all radii to be the same value (20), so instead of setting the radius as a number we’ll define the radius as a function that will scale the radius based on population.

这会将所有半径的大小设置为相同的值(20),因此,我们将半径定义为一个函数,该函数将根据总体比例缩放半径,而不是将半径设置为数字。

Create that scaling function at the top of your service:

在服务顶部创建该缩放功能:

static ScaledRadius(val: number, maxVal: number): number {
  return 20 * (val / maxVal);
}

This function takes in a value (population), a max value (maximum population), and returns a radius in the range [0 - 20].

此函数输入一个值(人口),一个最大值(最大人口),并返回范围为[0-20]的半径。

We find the maximum population by using this slick one-liner:

我们使用这种光滑的单线查找最大人口:

const maxVal = Math.max(...res.features.map(x => x.properties.population), 0);

Finally, we put it all together by using ScaledRadius as our radius function.

最后,我们将ScaledRadius用作半径函数将它们放在一起。

Highlighting our changes, our final MarkerService now looks like this:

强调我们的更改,我们最终的MarkerService现在看起来像这样:

marker.service.ts
标记服务
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import * as L from 'leaflet';

@Injectable({
  providedIn: 'root'
})
export class MarkerService {

  capitals: string = '/assets/data/usa-capitals.geojson';

  static ScaledRadius(val: number, maxVal: number): number {
    return 20 * (val / maxVal);
  }

  constructor(private http: HttpClient) {
  }

  makeCapitalMarkers(map: L.map): void {
    this.http.get(this.capitals).subscribe((res: any) => {
      for (const c of res.features) {
        const lat = c.geometry.coordinates[0];
        const lon = c.geometry.coordinates[1];
        const marker = L.marker([lon, lat]).addTo(map);
      }
    });
  }

  makeCapitalCircleMarkers(map: L.map): void {
    this.http.get(this.capitals).subscribe((res: any) => {

      // Find the maximum population to scale the radii by.
      const maxVal = Math.max(...res.features.map(x => x.properties.population), 0);

      for (const c of res.features) {
        const lat = c.geometry.coordinates[0];
        const lon = c.geometry.coordinates[1];
        const circle = L.circleMarker([lon, lat], {
  radius: MarkerService.ScaledRadius(c.properties.population, maxVal)
}).addTo(map);
      }
    });
  }
}

Launch the app and navigate to http://localhost:4200 to reveal our new scaled circle markers.

启动应用程序并导航到http:// localhost:4200,以显示我们新的缩放圆圈标记。

And this is the moment you realize that the most populous state capital is Phoenix, Arizona. Who knew?

这是您意识到人口最多的州首府是亚利桑那州凤凰城的时刻。 谁知道?

回顾 (Recap)

In this post, we’ve created a marker service that loads our data and constructs markers. We learned how to create two types of markers: L.marker and L.circleMarker. Finally, we learned how to define the size of each circle marker by passing a function for the radius.

在本文中,我们创建了一个标记服务,用于加载数据并构造标记。 我们学习了如何创建两种类型的标记: L.markerL.circleMarker 。 最后,我们学习了如何通过传递半径函数来定义每个圆形标记的大小。

In the next post, we’ll add some interactivity to our markers.

在下一篇文章中,我们将为标记添加一些交互性。

Happy mapping!

祝您映射愉快!

其他资源 (Additional Resources)

  • GeoJSON

    GeoJSON

翻译自: https://www.digitalocean.com/community/tutorials/angular-angular-and-leaflet-marker-service

angular id标记


http://www.niftyadmin.cn/n/3649613.html

相关文章

Java高新技术---反射动态代理

2015-04-25 一、反射 1、概述 JAVA反射机制是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够知道这个类的所有属性和方法&#xff1b;对于任意一个对象&#xff0c;都能够调用它的任意一个方法和属 性&#xff1b;这种动态获取的信息以及动态调用对象的方…

[xmlpull]XmlPull常见错误

[xmlpull]XmlPull常见错误编写者日期关键词郑昀ultrapower2005-9-28Xmlpull kxml java Xmlpull官方站点&#xff1a;http://www.xmlpull.org/优点&#xff1a;不必等整个文档解析完成&#xff0c;部分求值结果早就可以开始反馈给用户。What Is It?XmlPull project is dedicate…

C#实战系列—学生信息管理系统(一)项目展示

最近在整理自己电脑上的学习资料&#xff0c;突然发现大二时小组一起做的C#项目——学生信息管理系统。就想运行起来玩玩。可是现在主机里面都是一些开发Android和Java的软件。visual studio 2010也早就卸载了。不过想到我们开发的这个系统在Windows 10系统上的兼容性不太好。所…

在VS Code中使用ESLint进行整理和格式化

介绍 (Introduction) When writing JavaScript with an editor such as Visual Studio Code, there are a number of ways you can ensure your code is syntactically correct and in line with current best practices. For example, it is possible to integrate a linter s…

C#实战系列—学生信息管理系统(二)源码分析

对部分核心源代码进行分析&#xff0c;项目已开源&#xff0c;查看完整代码&#xff0c;文章底部有链接。 学生信息管理系统分为三个部分 项目展示 源码分析 项目打包 现在展示的是对原有系统进行二次开发的结果。为2.0版本。 一、界面设计 1、新建项目 新建项目的时候选择Wi…

如何使用MongoDB和Docker设置Flask

The author selected the Internet Archive to receive a donation as part of the Write for DOnations program. 作者选择了Internet存档作为“ Write for DOnations”计划的一部分来接受捐赠。 介绍 (Introduction) Developing web applications can become complex and ti…

[p2p-jxta]myJXTA试用体验(1)

下载了jxta-myjxta-2.3.5.zip&#xff0c;解压缩后直接运行myjxta.bat&#xff0c;立马登录入JXTA网络&#xff0c;上面还真有几个对端呢。第一次用到这么直截了当的P2P Java程序。IBM上的JXTA资源&#xff1a;http://www-128.ibm.com/developerworks/cn/java/wi-jxta2/index.h…