introduce

Arcgis has long been well-known as the world’s leading GIS platform software service provider. However, due to the influence of the two major map services entrenched in the Domestic Internet and the innate language advantage, I have not had too much contact with Arcgis for Js. Until one day, forced by the demand scene, a project needed a more detailed base map and a special projection coordinate system, so I had to patiently read the API Reference and Sample Code of Arcgis for JS with huge words, and applied them to the project according to the Sample and documents. It smells good when you look back after the project.

The product functions and performance of Arcgis have made a qualitative leap since 4.1x version compared with the old version. However, its detailed documentation and flexible interface design are what makes Arcgis amazing.

advantage

Compared with domestic Internet map services, Arcgis may have at least the following advantages:

  1. Supports custom deployment of map slicing services
  2. Support various official or custom geographic coordinates, projection coordinates
  3. Support to use three.js as renderer for 3D layer development
  4. Excellent performance in processing massive data
  5. Complete documentation and flexible interfaces

Simple development examples

Arcgis has too many functions. This time, the realization of displaying mass point marks will be explained step by step:

  1. Installing dependency packages
  2. Initialize the map
  3. Initialize the layer
  4. Layer data filtering
  5. The mouse interaction

Installing dependency packages

The vuE-CLI project is used as an example. The installation instructions are as follows. You are advised to use a version later than 4.18

npm i @arcgis/core -S
Copy the code

After installation, copy part of the ArcGIS static directory to the distribution package, find./node_modules/@arcgis/core/assets, and copy them to public/assets.

You can also perform the same action at build time with instructions

"copy": "cp -R ./node_modules/@arcgis/core/assets ./dist/assets",
Copy the code

In order to ensure the normal display of arcGIS built-in components, the theme CSS (which can be switched freely) is introduced into the entry HTML file.

<link href="./assets/esri/themes/light/main.css" rel="stylesheet"/>

Copy the code

Initialize the map

Create a page called Featurelayer.vue to put all the code in. The simplest map creation code is as follows.

The map needs basemap as the basemap. We can use various base maps with or without tokens provided by arcgis or map services created by ourselves as the basemap. Based on the base image, you can also use the Layers property to overlay more layers on the map, such as road network, water network, power grid, and so on.

In addition to declaring a map, you need to instantiate a view (MapView is a 2D view, SceneView is a 3D view). In this case, you need to declare the container and various initial values of the 2D view.

<template>  
    <div class="wrap">    
        <div id="viewDiv" class="container"></div>
    </div>
</template>
<script>
   import Map from '@arcgis/core/Map';
   import MapView from '@arcgis/core/views/MapView';
   export defaultname: 'FeatureLayer', 
        data () {

        },
        mounted () {
            this.initMap()
        },
        methods: {
            initMap(){
                const map = new Map({  
                    basemap: "hybrid" / / satellite imagery
                })
                // Create a 2D view
                const view = new MapView({  
                    container: "viewDiv".map: map,  
                    zoom: 11.center: [113.54735115356235.22.78385103258788],})this.map = map
               this.view = view
            }
        }
   }
</script>
Copy the code

Initialize the layer

FeatureLayer is a FeatureLayer for large layers. There are three main steps: instantiate layers, give layers to Map, and stuff layers with data.

Instantiate the layer and hand it to Map

const layer = new FeatureLayer({
   // The layer can be found by using map.findLayerById(id)
  id: 'deviceLayer'.title: "Device Layer".// Internal fields obtained from attributes
  fields: [{name: "ObjectID".type: "oid"
    },
    {
      name: "id".type: "string"
    },
    {
      name: "deviceUid".type: "string"
    },
    {
      name: "deviceStatus".type: "string"}].// Make all fields externally accessible
  outFields: ["*"].// The unique identifier of the dot marker
  objectIdField: "ObjectID".geometryType: "point".// Initial data
  source: [].renderer: {
    type: "unique-value".// Extract deviceStatus as an identifier of the render icon type
    valueExpression: `return $feature.deviceStatus`.// All icon type declarations
    uniqueValueInfos,
    // Adjust the size according to the scale
    visualVariables: [{type: "size".valueExpression: "$view.scale".stops: [{value: 500000.size: 1 },
          { value: 250000.size: 5 },
          { value: 125000.size: 15 },
          { value: 32000.size: 20},]}]},// Click the dot mark to pop up the content template
  popupTemplate: {
    title: "{deviceUid}".content: [{
      type: "fields".fieldInfos: [{
        label: 'equipment Uid'.fieldName: 'deviceUid'}, {label: 'device id'.fieldName: 'id'}, {label: 'Device status'.fieldName: 'deviceStatus'}}}}]])// Give the layer to Map
this.map.add(layer)
Copy the code

The initialization code is very important of the two attributes is the renderer uniqueValueInfos and the renderer valueExpression, the former statement for all types of ICONS, which make a sound and clear as ICONS in the field or combination type of unique identifiers.

Renderer. valueExpression = return $feature.deviceStatus (ONLINE, OFFINE, UNACTIVATED) to determine which icon the data will be displayed on.

The renderer. UniqueValueInfos statement as follows, we declared the three ICONS

uniqueValueInfos = [{
    value: 'ONLINE'.symbol: {
      type: "picture-marker".url: `images/svg/camera_m_1.svg`
    }
},{
    value: 'OFFINE'.symbol: {
      type: "picture-marker".url: `images/svg/camera_m_2.svg`
    }
},{
    value: 'UNACTIVATED'.symbol: {
      type: "picture-marker".url: `images/svg/camera_m_3.svg`}}]Copy the code

Stuff data into layers

There are two ways to do this: (1) fill the source property during the example layer and (2) dynamically add data to the layer with layer.applyedits ({addFeatures: source})

Here’s how to add data to a layer dynamically

layer.applyEdits({addFeatures: source}).then(results= > {
      // Run the following command to print the added data
     console.log(`addFeatures:${results.addFeatureResults.length}`)})Copy the code

The form of source is an array of graphic. Each graphic declares the shape of point annotations (possibly point, line, surface, body, custom graphic, etc.) and its own attributes.

It is important to note that if a specific reference coordinate system is used in the current view, the coordinate system must be declared through spatialReference in Geometry, otherwise the final point marks are likely not displayed in the layer.

 // Raw data
 const data = [{
    location: {latitude: 33.longitude: 112}, / / coordinates
    deviceStatus: 'ONLINE'// Custom attributes
    deviceUid: '123'
 }]
 
// Create an array of graphic
const graphics = []
data.forEach(item= > {
      const {longitude, latitude} = item.location
      let graphic = new Graphic({
        // The geographical attributes of each point
        geometry: {
          type: "point",
          latitude,
          longitude,
          // spatialReference: { wkid: WKID },
        },
        // Attributes for each point
        attributes: item
      })
      graphics.push(graphic)
})
Copy the code

Layer data filtering

As shown in the figure, to screen the layer at the front end and only show the point marks that meet the conditions, it is necessary to call the filter attribute of the layer. We directly assign the filtering conditions to filter (various ArcGIS classes can read and write their attributes directly) and re-render the layer.

// Call the filter method
filterDeviceLayer({
    mode: 'deviceStatus'.values: ['ONLINE'.'OFFLINE']
})


filterDeviceLayer ({mode, values = []} = {}) {

    const deviceLayer = this.map.findLayerById('deviceLayer')

    this.view.whenLayerView(deviceLayer).then(function (layerView) {

      let queryStr = ' '
      if (values.length > 0) {
        queryStr +=  values.map(o= > {
          return `${mode}= '${o}'`
        }).join(' OR ')}console.log('queryStr: ', queryStr)  
      //queryStr: deviceStatus = 'ONLINE' OR deviceStatus = 'OFFLINE'
      layerView.filter = {where: queryStr}

      // re-render
      deviceLayer.refresh()
    })

}

Copy the code

The mouse interaction

There are only two types of mouse interaction for layers, hover and click.

The mouse is suspended

Listen for mouse movement and detect collision objects. If the object is a point annotation of the deviceLayer layer, Tip displays the Uid of the point annotation, otherwise Tip is removed.

this.view.on("pointer-move".(event) = > {

      const {x, y} = event

      _view.hitTest(event).then((res) = > {

        const results = res.results

        if (results.length && results[0].graphic) {

          const {sourceLayer, attributes} = results[0].graphic
          if(! sourceLayer || ! attributes) {return
          }
          const {deviceUid} = attributes

          if (sourceLayer && ['deviceLayer'].includes(sourceLayer.id)) {
            / / tip
            this.currTip = `Uid: ${deviceUid}`
            / / positioning tip
            this.currTipStyle = {top: y + 15 + 'px'.left: x + 15 + 'px'}}else {
            this.currTip = ' '}}else {
          //tip is not displayed when the content is empty
          this.currTip = ' '}})})Copy the code

The mouse to click

It is important to note that the default popover behavior and template are configured by declaring popupTemplate during layer initialization. If you don’t want to use the default popover, don’t declare popupTemplate and write your own popover logic in the t.view.hittest callback.

You can get custom attributes for the dot annotations from results[0].graphic.Attributes if they were declared with Fields when the layer was initialized.

const t = this
this.view.on('click'.(event) = > {

  const {x, y} = event.mapPoint
  console.log({x, y})

   // Close the built-in popover declared during layer initialization
  // t.view.popup.autoOpenEnabled = false

  t.view.hitTest(event).then((res) = > {
    // Logic like levitation
    console.log(res.results)
  })
})
Copy the code

This completes all the steps for this code example.

At the end

Limited space, only a common function of Arcgis for Js, later need to share others, the above content has been organized into a project on Github/study-ArcGIS.

A link to the

Developers.arcgis.com/javascript/…