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:
- Supports custom deployment of map slicing services
- Support various official or custom geographic coordinates, projection coordinates
- Support to use three.js as renderer for 3D layer development
- Excellent performance in processing massive data
- 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:
- Installing dependency packages
- Initialize the map
- Initialize the layer
- Layer data filtering
- 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 default {
name: '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/…