arcade

字数统计: 5.2k
阅读时长: 约 16 分钟
当前版本: 4.29

AMD: require(["geoscene/arcade"], (arcade) => { /* code goes here */ });

ESM: import * as arcade from "@geoscene/core/arcade.js";

对象: geoscene/arcade

起始版本:GeoScene Maps SDK for JavaScript 4.24

此模块允许您评估传统 GeoScene Arcade 配置文件之外的 Arcade 表达式。配置文件可定义有效输入变量 (即配置文件变量) 的表达式、支持的函数和表达式的有效返回类型。GeoScene Maps SDK for JavaScript 中执行的所有 Arcade 表达式必须符合编写它们的配置文件的规则。createArcadeExecutor 方法提供了一个 API,用于在预定义的 GeoScene Arcade 配置文件的上下文之外执行 Arcade 表达式。

此模块允许您执行以下操作:

  • 在另一上下文中执行已为现有 GeoScene 配置文件编写的表达式。例如,最终用户可能为 WebMap 中的渲染器、弹出窗口或标签编写了表达式,并且表达式生成的数据应在 WebMap 外部的自定义组件、表或图表中显示。

  • 定义自定义 Arcade 配置文件,并在应用程序中提供可配置的体验,以便用户编写自己的表达式。

  • 开发人员可能希望利用 Arcade 提供的可链接功能集简化过滤和查询数据的过程。

方法概述

名称返回值类值描述对象
createArcadeExecutor()Promise<ArcadeExecutor>将 Arcade 表达式及其配置文件编译为执行程序。arcade
createArcadeProfile()Profile为 GeoScene Maps SDK for JavaScript 中实现的 Arcade 配置文件创建配置文件定义。arcade

方法详细说明

createArcadeExecutor

createArcadeExecutor(script, profile){Promise<ArcadeExecutor>}

将 Arcade 表达式及其配置文件编译为执行程序。执行程序可提供函数来评估配置文件变量的结果。

参数

scriptString

要编译和执行的 Arcade 表达式

profileProfile

用于执行给定表达式的配置文件定义。配置文件定义了配置文件变量名称和数据类型,用户可以将其用作表达式中的输入。变量实例提供给执行程序函数。

返回

类型描述
Promise<ArcadeExecutor>解析为 ArcadeExecutor,它提供一个同步 (如果适用) 和异步函数,用于在提供有效的输入配置文件变量时计算编译的 Arcade 表达式。

示例

js
// Synchronous execution for all features in layer view
// % of the population not in labor force
const arcadeScript = "(($feature.POP_16UP - $feature.EMP_CY) / $feature.POP_16UP) \* 100"

const profile = {
  variables: [{
    name: "$feature",
    type: "feature"
  }]
};

const laborForceExecutor = await createArcadeExecutor(arcadeScript, profile);
// ensures data values from fields used in the expression are
// available when the expression executes.
layer.outFields = laborForceExecutor.fieldsUsed;

const { features } = await layerView.queryFeatures();

const allValues = features.map( (feature) => {
  return laborForceExecutor.execute({
    "$feature": feature
  });
});

// allValues can be displayed in a chart, or used to
// report stats for this variable
html
// Asynchronous execution for one feature clicked in the view

const profile = {
  variables: [{
    name: "$feature",
    type: "feature"
  }, {
    name: "$layer",
    type: "featureSet"
  }]
};

// This expression executes on each feature click. It compares the % of the population
// not participating in the labor force with the same value of all features within
// one mile of the selected feature's location
const arcadeScript = `
  var featureNotLaborForce = Round((($feature.POP_16UP - $feature.EMP_CY)/$feature.POP_16UP)\*100);
  var id = $feature.OBJECTID;

  var neighbors = Filter( Intersects( $layer, BufferGeodetic($feature, 1, "mile") ), "OBJECTID <> @id" );
  if( Count(neighbors) == 0 ){
    return "No neighbors within 1 mile";
  }

  var neighborsNotLaborForceAverage = Average(neighbors, "( (POP_16UP - EMP_CY) / POP_16UP) \* 100");
  var difference = Round(featureNotLaborForce - neighborsNotLaborForceAverage);
  var differenceText = IIF(difference > 0, "+"+difference, Text(difference));
  return differenceText;
`;

const neighborhoodExecutor = await createArcadeExecutor(arcadeScript, profile);
// ensures data values from fields used in the expression are
// available when the expression executes.
layer.outFields = neighborhoodExecutor.fieldsUsed;

view.on("click", async (event) => {
  const hitResponse = await view.hitTest(event, include: { layer });
  const hitGraphic = hitResponse?.results[0].graphic;

  const scriptResult = await neighborhoodExecutor.executeAsync({
    "$feature": hitGraphic,
    "$layer": hitGraphic.layer
  }, {
    spatialReference: view.spatialReference
  });

  // display the value of scriptResult in a UI component or use it
  // in some form of client-side analysis
});

createArcadeProfile

createArcadeProfile(profileName){Profile}

起始版本:GeoScene Maps SDK for JavaScript 4.25

为 GeoScene Maps SDK for JavaScript 中实现的 Arcade 配置文件创建配置文件定义。此操作的结果应提供给 createArcadeExecutor 方法。

参数

profileNameString

要创建的 Arcade 配置文件定义的名称。

可能值:"form-constraint"|"feature-z"|"field-calculation"|"form-calculation"|"labeling"|"popup"|"popup-element"|"feature-reduction-popup"|"feature-reduction-popup-element"|"visualization"

返回

类型描述
Profile返回用于使用 ArcadeExecutor 执行表达式的配置文件定义。

另请参阅

示例

js
const labelingProfile = arcade.createArcadeProfile("labeling");
// creates the following object to be provided to the createArcadeExecutor method.
// {
//   variables: [{
//     name: "$feature",
//     type: "feature"
//   }]
// }

const labelExecutor = await createArcadeExecutor("$feature.NAME + ' COUNTY'", labelingProfile);

类型定义

ArcadeExecutor

ArcadeExecutor

该执行程序提供一个同步 (如果适用) 和异步函数,用于使用声明的配置文件变量的输入来计算编译的 Arcade 表达式。它还提供有关编译结果的元数据。

属性

executeExecuteFunction

可调用的函数,用于评估一组配置文件变量的编译表达式。将返回评估结果。仅当 isAsync 为 false 时,此函数才可用。

executeAsyncExecuteFunctionAsync

计算编译表达式的异步函数。此函数可始终用于评估表达式,但如果 isAsync 为 true,则必须使用此函数。

fieldsUsedString[]

使用 $feature 配置变量或需要字段名的函数 (如 Expects) 时,引用编译表达式中使用的字段名。此处引用的字段名应由底层图层或数据存储请求。在 JavaScript 中,这通常使用 layer.outFields 完成。

geometryUsedBoolean

指示表达式是访问还是使用要素的几何。

isAsyncBoolean

指示编译后的表达式是否使用 FeatureSet 函数访问数据,因此必须使用 executeAsync 函数执行。如果为 false,则可以使用 executeexecuteAsync 执行表达式。

另请参阅

示例

js
// Synchronous execution for all features in layer view
// % of the population not in labor force
const arcadeScript = "(($feature.POP_16UP - $feature.EMP_CY) / $feature.POP_16UP) \* 100"

const profile = {
  variables: [{
    name: "$feature",
    type: "feature"
  }]
};

const laborForceExecutor = await createArcadeExecutor(arcadeScript, profile);
// ensures data values from fields used in the expression are
// available when the expression executes.
layer.outFields = laborForceExecutor.fieldsUsed;

const { features } = await layerView.queryFeatures();

const allValues = features.map( (feature) => {
  return laborForceExecutor.execute({
    "$feature": feature
  });
});

// allValues can be displayed in a chart, or used to
// report stats for this variable
html
// Asynchronous execution for one feature clicked in the view

const profile = {
  variables: [{
    name: "$feature",
    type: "feature"
  }, {
    name: "$layer",
    type: "featureSet"
  }]
};

// This expression executes on each feature click. It compares the % of the population
// not participating in the labor force with the same value of all features within
// one mile of the selected feature's location
const arcadeScript = `
  var featureNotLaborForce = Round((($feature.POP_16UP - $feature.EMP_CY)/$feature.POP_16UP)\*100);
  var id = $feature.OBJECTID;

  var neighbors = Filter( Intersects( $layer, BufferGeodetic($feature, 1, "mile") ), "OBJECTID <> @id" );
  if( Count(neighbors) == 0 ){
    return "No neighbors within 1 mile";
  }

  var neighborsNotLaborForceAverage = Average(neighbors, "( (POP_16UP - EMP_CY) / POP_16UP) \* 100");
  var difference = Round(featureNotLaborForce - neighborsNotLaborForceAverage);
  var differenceText = IIF(difference > 0, "+"+difference, Text(difference));
  return differenceText;
`;

const neighborhoodExecutor = await createArcadeExecutor(arcadeScript, profile);
// ensures data values from fields used in the expression are
// available when the expression executes.
layer.outFields = neighborhoodExecutor.fieldsUsed;

view.on("click", async (event) => {
  const hitResponse = await view.hitTest(event, include: { layer });
  const hitGraphic = hitResponse?.results[0].graphic;

  const scriptResult = await neighborhoodExecutor.executeAsync({
    "$feature": hitGraphic,
    "$layer": hitGraphic.layer
  }, {
    spatialReference: view.spatialReference
  });

  // display the value of scriptResult in a UI component or use it
  // in some form of client-side analysis
});
js
const profile = {
  variables: [{
    name: "$feature",
    type: "feature"
  }]
};

// Arcade expression defined by user...
const syncExecutor = await createArcadeExecutor(arcadeScript, profile);
// ensures data values from fields used in the expression are
// available when the expression executes.
layer.outFields = syncExecutor.fieldsUsed;

// throw error if expression from user uses
// invalid functions that require async execution
if(syncExecutor.isAsync){
  throw new Error("Invalid expression. Expression should not use FeatureSet functions.");
}

const { features } = await layerView.queryFeatures();

const allValues = features.map( (feature) => {
  return syncExecutor.execute({
    "$feature": feature
  });
});

// allValues can be displayed in a chart, or used to
// report stats for this variable

ArrayElementType

ArrayElementType

array 类型的配置文件变量的类型定义。

属性

typeString|String

变量的 Arcade 数据类型。请参阅 ProfileVariableInstanceType 以查看 Arcade 类型到 JavaScript 类型的映射。

可能值:"dictionary"|"feature"|"featureSet"|"featureSetCollection"|"geometry"|"number"|"text"|"date"|"dateOnly"|"time"|"boolean"|"knowledgeGraph"

propertiesProfileVariable[]

optional

仅在 typedictionary 时适用。字典属性的类型定义。这些属性的名称不应以 $ 字符开头。

elementTypeArrayElementType

optional

仅在 typearray 时适用。数组项目的类型定义。当用作输入配置文件变量时,Arcade 数组必须是单一类型。指示 elementType 时,不需要为元素指定名称。

ArrayVariable

ArrayVariable

Arcade 数组配置文件变量的类型定义。

属性

nameString

配置文件变量的名称。为遵循 Arcade 命名约定,这应以 $ 字符开头,除非该变量嵌套在 DictionaryVariable 中。

typeString

变量的 Arcade 数据类型。对于 ArrayVariable,类型总是 array。Arcade Array 对应的 JavaScript 类型是遵循 ProfileVariableInstanceType 中定义的规范的数组。

elementTypeArrayElementType

optional

数组项目的类型定义。当用作输入配置文件变量时,Arcade 数组必须是单一类型。指示 elementType 时,不需要为元素指定名称。

示例

js
const profile = {
  variables: [{
    name: "$checkpoints",
    type: "array",
    elementType: {
      type: "feature"
    }
  }]
};

DictionaryVariable

DictionaryVariable

Arcade 字典配置变量的类型定义。

属性

nameString

配置文件变量的名称。为遵循 Arcade 命名约定,这应以 $ 字符开头,除非该变量嵌套在另一个 DictionaryVariable 中。请参见下面的示例。

typeString

变量的 Arcade 数据类型。Arcade Dictionary 对应的 JavaScript 类型是遵循 ProfileVariableInstanceType 中定义的规范的纯对象。

值通常是 "dictionary"。

propertiesProfileVariable[]

optional

字典属性的类型定义。这些属性的名称不应以 $ 字符开头。

示例

js
const profile = {
  variables: [{
    name: "$analysisParams",
    type: "dictionary",
    properties: [{
      name: "distance",
      type: "number"
    }, {
      name: "projectType",
      type: "text"
    }, {
      name: "includeBuffer",
      type: "boolean"
    }]
  }, {
     name: "$projectLocation",
     type: "feature"
  }]
};

ExecuteContext

ExecuteContext

Arcade 表达式的执行上下文。

属性

spatialReferenceSpatialReference

optional

几何函数中输入几何的预期空间参考。如果在地图的上下文中执行表达式,则将视图的空间参考设置为此属性。如果在图层的上下文中执行表达式,则使用该图层的空间参考。如果未指定,则空间参考默认为 WebMercator

timeZoneString

自 4.28 开始 定义创建和显示 Arcade 日期类型的默认时区。可能值包括在 View.timeZone 上设置的任何时区。通常,如果 Arcade 上下文的配置文件涉及地图或源自地图的要素,则应在此处设置 View.timeZone 值。默认情况下,时区设置为"system”。

默认值:system

示例

js
// the input feature's geometry is expected
// to be in the spatial reference of the view
// All Arcade dates will be represented in the
// time zone of the view or web map.
await executor.executeAsync({
  "$feature": feature
}, {
  spatialReference: view.spatialReference,
  timeZone: view.timeZone
});
js
// the input feature's geometry is expected
// to be in the spatial reference of the layer
await executor.executeAsync({
  "$feature": feature
}, {
  spatialReference: layer.spatialReference
});
js
// the input feature's geometry is expected
// to be Web Mercator
await executor.executeAsync({
  "$feature": feature
});

ExecuteFunction

ExecuteFunction(profileVariableInstances, context?){ResultType}

与给定的配置文件变量实例同步执行编译的 Arcade 表达式。如果表达式使用 FeatureSet 函数访问数据,则不能使用此函数。

参数

profileVariableInstancesObject

键/值对的对象,其中键是创建执行器时定义的 ProfileVariable 的名称。键值类型必须为 ProfileVariableInstanceType

contextExecuteContext

optional

用于执行表达式的上下文。

返回

类型描述
ResultType返回计算表达式的值。

示例

js
// Synchronous execution for all features in layer view
// % of the population not in labor force
const arcadeScript = "(($feature.POP_16UP - $feature.EMP_CY) / $feature.POP_16UP) \* 100"

const profile = {
  variables: [{
    name: "$feature",
    type: "feature"
  }]
};

const laborForceExecutor = await createArcadeExecutor(arcadeScript, profile);
// ensures data values from fields used in the expression are
// available when the expression executes.
layer.outFields = laborForceExecutor.fieldsUsed;

const { features } = await layerView.queryFeatures();

const allValues = features.map( (feature) => {
  return laborForceExecutor.execute({
    "$feature": feature
  });
});

// allValues can be displayed in a chart, or used to
// report stats for this variable
js
const profile = {
  variables: [{
    name: "$feature",
    type: "feature"
  }]
};

// Arcade expression defined by user...
const syncExecutor = await createArcadeExecutor(arcadeScript, profile);
// ensures data values from fields used in the expression are
// available when the expression executes.
layer.outFields = syncExecutor.fieldsUsed;

// throw error if expression from user uses invalid functions
if(syncExecutor.isAsync){
  throw new Error("Invalid expression. Expression should not use FeatureSet functions.");
}

const { features } = await layerView.queryFeatures();

const allValues = features.map( (feature) => {
  return syncExecutor.execute({
    "$feature": feature
  });
});

// allValues can be displayed in a chart, or used to
// report stats for this variable

ExecuteFunctionAsync

ExecuteFunctionAsync(profileVariableInstances, context?){Promise<ResultType>}

与给定的配置文件变量实例异步执行编译的 Arcade 表达式。

参数

profileVariableInstancesObject

键/值对的对象,其中键是创建执行程序时定义的 ProfileVariable 的名称,其值的类型必须为 ProfileVariableInstanceType

contextExecuteContext

optional

用于执行表达式的上下文。

返回

类型描述
Promise<ResultType>解析为评估表达式的值。

示例

html
// Asynchronous execution for one feature clicked in the view

const profile = {
  variables: [{
    name: "$feature",
    type: "feature"
  }, {
    name: "$layer",
    type: "featureSet"
  }]
};

// This expression executes on each feature click. It compares the % of the population
// not participating in the labor force with the same value of all features within
// one mile of the selected feature's location
const arcadeScript = `
  var featureNotLaborForce = Round((($feature.POP_16UP - $feature.EMP_CY)/$feature.POP_16UP)\*100);
  var id = $feature.OBJECTID;

  var neighbors = Filter( Intersects( $layer, BufferGeodetic($feature, 1, "mile") ), "OBJECTID <> @id" );
  if( Count(neighbors) == 0 ){
    return "No neighbors within 1 mile";
  }

  var neighborsNotLaborForceAverage = Average(neighbors, "( (POP_16UP - EMP_CY) / POP_16UP) \* 100");
  var difference = Round(featureNotLaborForce - neighborsNotLaborForceAverage);
  var differenceText = IIF(difference > 0, "+"+difference, Text(difference));
  return differenceText;
`;

const neighborhoodExecutor = await createArcadeExecutor(arcadeScript, profile);
// ensures data values from fields used in the expression are
// available when the expression executes.
layer.outFields = neighborhoodExecutor.fieldsUsed;

view.on("click", async (event) => {
  const hitResponse = await view.hitTest(event, include: { layer });
  const hitGraphic = hitResponse?.results[0].graphic;

  const scriptResult = await neighborhoodExecutor.executeAsync({
    "$feature": hitGraphic,
    "$layer": hitGraphic.layer
  }, {
    spatialReference: view.spatialReference
  });

  // display the value of scriptResult in a UI component or use it
  // in some form of client-side analysis
});

Profile

Profile

定义配置文件输入变量的定义。这包括一个对象数组,用于指定每个配置文件变量的名称及其 Arcade 数据类型。所有配置文件名称必须以 $ 字符开头。

属性

variablesProfileVariable[]

用作编译表达式输入的配置文件变量的 Arcade 类型定义。

示例

js
const profile = {
  variables: [{
    name: "$mapClick",
    type: "geometry"
  }, {
    name: "$threshold",
    type: "number"
  }, {
    name: "$feature",
    type: "feature"
  }, {
    name: "$map",
    type: "featureSetCollection"
  }]
};

ProfileVariable

ProfileVariable SimpleVariable|DictionaryVariable|ArrayVariable

配置文件变量的类型定义。有关更多信息和示例,请参阅各个配置文件变量类型。

ProfileVariableInstanceType

ProfileVariableInstanceType Graphic|Geometry|FeatureSet|FeatureLayer|Map|KnowledgeGraph|String|Number|Boolean|Date|Object|Array

使用 ExecuteFunctionExecuteFunctionAsync 评估编译表达式时,可以用作配置文件变量输入的 JavaScript 类型。请参阅下表,了解以下 JavaScript 类型的映射,这些类型可用于为相应的 Arcade 数据类型混合配置文件变量。

Arcade 类型JS 类型
NumberNumber
TextString
DateDate从 Arcade 表达式返回的日期不会保留 Arcade 日期值中包含的时区信息。由于本地 JS 日期对象不包含时区信息,因此它们将始终以执行表达式的客户端的本地时间或系统时间显示。要在 Arcade 返回的日期中保留时区信息,表达式作者应在表达式的返回语句中将日期转换为 Arcade 文本值。
DateOnlyString
TimeString
BooleanBoolean
DictionaryObject具有键/值对的对象,其中键由 DictionaryVariable 定义,其值必须是 ProfileVariableInstanceType 之一。
KnowledgeGraphKnowledgeGraph该值通常来自 KnowledgeGraphLayer.knowledgeGraph
ArrayArrayArcade 数组是不可变的,必须是单个 ProfileVariableInstanceType
GeometryGeometry
FeatureGraphic
FeatureSetFeatureLayerFeatureSet
FeatureSetCollectionMapString

ResultType

ResultType Number|String|Date|Boolean|Graphic|Geometry|Object|ResultType[]

从 Arcade 表达式返回的结果的 JavaScript 类型。

SimpleVariable

SimpleVariable

简单 Arcade 配置文件变量的类型定义。

属性

nameString

配置文件变量的名称。为遵循 Arcade 命名约定,这应以 $ 字符开头,除非该变量嵌套在 DictionaryVariable 中。

typeString

变量的 Arcade 数据类型。请参阅 ProfileVariableInstanceType 以查看 Arcade 类型到 JavaScript 类型的映射。

可能值:"feature"|"featureSet"|"featureSetCollection"|"geometry"|"number"|"text"|"date"|"dateOnly"|"time"|"boolean"|"knowledgeGraph"

示例

js
const profile = {
  variables: [{
    name: "$mapClick",
    type: "geometry"
  }, {
    name: "$threshold",
    type: "number"
  }, {
    name: "$feature",
    type: "feature"
  }, {
    name: "$map",
    type: "featureSetCollection"
  }]
};