ArcGIS JS API教程:基于GPS航向旋转Web样式符号

落敏姑娘_1011

落敏姑娘_1011

2025-12-04

754人浏览

原创

ArcGIS JS API教程:基于GPS航向旋转Web样式符号

本教程详细介绍了如何利用arcgis javascript api实现web样式符号的动态旋转。我们将聚焦于使用`simplerenderer`中的`rotation`视觉变量,根据要素的属性(如gps航向数据)来精确控制地图上符号的方向。文章将通过代码示例、实现步骤和注意事项,指导开发者构建能够响应数据变化的地图应用,使符号(如车辆图标)能实时反映其在现实世界中的朝向。

1. 引言

在地图应用中,动态展示移动对象的方向是一个常见需求,例如在实时车辆追踪系统中,车辆图标应根据其GPS航向数据进行旋转,以准确反映其行驶方向。ArcGIS JavaScript API提供了强大的渲染能力,通过视觉变量(Visual Variables)可以轻松实现这一目标。本教程将深入探讨如何结合Web样式符号和SimpleRenderer的rotation视觉变量,实现基于数据属性的符号动态旋转。

2. 核心概念:使用SimpleRenderer和rotation视觉变量

ArcGIS API for JavaScript中的Renderer负责定义要素在地图上的显示方式。对于需要根据属性值动态改变外观的场景,Renderer的visualVariables属性是关键。其中,rotation视觉变量专门用于控制符号的旋转角度。

  • SimpleRenderer: 最基础的渲染器,用于为图层中的所有要素应用相同的符号样式。
  • visualVariables: Renderer的一个属性,它是一个数组,允许根据要素的属性动态调整符号的视觉效果,如颜色、大小、透明度或旋转。
  • rotation视觉变量:
    • type: 必须设置为 "rotation"。
    • field 或 valueExpression: 指定用于驱动旋转的属性字段名或一个Arcade表达式。
      • field: 直接使用要素属性中的某个字段的值作为旋转角度。
      • valueExpression: 提供一个Arcade表达式,可以对一个或多个字段进行计算,然后返回旋转角度。例如,"$feature.heading" 表示使用要素的heading属性值。
    • rotationType: (可选)定义旋转的原点,例如"geographic"(正北向上,顺时针增加)或"arithmetic"(正东向上,逆时针增加)。默认通常是"arithmetic"。对于GPS航向,通常使用"geographic"。

3. 实现步骤

要实现基于GPS航向的Web样式符号旋转,主要步骤如下:

3.1 准备Web样式符号

首先,定义一个Web样式符号。Web样式符号是ArcGIS API提供的一种便捷方式,可以引用预定义的符号库中的符号,例如交通工具、建筑物等。

const carSymbol = {
  type: "web-style", // 指定符号类型为Web样式
  styleName: "EsriRealisticTransportationStyle", // 选择一个样式库
  name: "BMW_3-Series" // 指定样式库中的具体符号名称
};

3.2 创建要素图层和渲染器

为了应用rotation视觉变量,我们需要将符号应用于一个FeatureLayer,并通过SimpleRenderer来管理其渲染。

  1. 准备要素数据: 假设我们有一个包含longitude、latitude和heading(航向角度)的GPS数据点。

    Miller CSV TSV JSON 数据处理器
    Miller CSV TSV JSON 数据处理器

    Miller (mlr) 是一个命令行工具,用于查询、整形和重新格式化名称索引数据,如 CSV、TSV、JSON 和 JSON Lines。它将 awk、sed、cut、join 和 sort 的功能整合到一个专为结构化数据处理而构建的单一工具中。

    下载
    const gpsData = {
      longitude: -101.9498125,
      latitude: 41.2097775,
      heading: 45 // 假设初始航向为45度
    };
  2. 创建Graphic: 将GPS数据转换为ArcGIS Graphic对象。

    const carGraphic = new Graphic({
      geometry: {
        type: "point",
        x: gpsData.longitude,
        y: gpsData.latitude
      },
      attributes: {
        ObjectID: 1, // FeatureLayer需要ObjectID字段
        heading: gpsData.heading
      }
    });
  3. 定义SimpleRenderer并应用rotation视觉变量: 这是实现旋转的核心。

    const carRenderer = new SimpleRenderer({
      symbol: carSymbol, // 使用之前定义的Web样式符号
      visualVariables: [
        {
          type: "rotation",
          field: "heading", // 使用Graphic的heading属性作为旋转角度
          // 或者使用 valueExpression: "$feature.heading"
          rotationType: "geographic" // 如果航向是地理方向(正北0度,顺时针增加),则设置为geographic
        }
      ]
    });
  4. 创建FeatureLayer: 将Graphic和Renderer结合起来创建FeatureLayer。

    const carsLayer = new FeatureLayer({
      source: [carGraphic], // 图层数据源
      objectIdField: "ObjectID", // 必须指定ObjectID字段
      renderer: carRenderer // 应用渲染器
    });

3.3 将图层添加到地图

最后,将配置好的FeatureLayer添加到地图中。

require([
  "esri/Map",
  "esri/views/MapView",
  "esri/layers/FeatureLayer",
  "esri/Graphic",
  "esri/renderers/SimpleRenderer"
], (Map, MapView, FeatureLayer, Graphic, SimpleRenderer) => {

  const map = new Map({
    basemap: "satellite"
  });

  const view = new MapView({
    container: "viewDiv",
    map: map,
    zoom: 15,
    center: [-101.9498125, 41.2097775],
  });

  // 1. 准备Web样式符号
  const carSymbol = {
    type: "web-style",
    styleName: "EsriRealisticTransportationStyle",
    name: "BMW_3-Series"
  };

  // 2. 准备要素数据和Graphic
  const initialGpsData = {
    longitude: -101.9498125,
    latitude: 41.2097775,
    heading: 45 // 初始航向
  };

  const carGraphic = new Graphic({
    geometry: {
      type: "point",
      x: initialGpsData.longitude,
      y: initialGpsData.latitude
    },
    attributes: {
      ObjectID: 1,
      heading: initialGpsData.heading
    }
  });

  // 3. 定义SimpleRenderer并应用rotation视觉变量
  const carRenderer = new SimpleRenderer({
    symbol: carSymbol,
    visualVariables: [
      {
        type: "rotation",
        field: "heading", // 使用Graphic的heading属性
        rotationType: "geographic" // 假设航向是地理方向
      }
    ]
  });

  // 4. 创建FeatureLayer
  const carsLayer = new FeatureLayer({
    source: [carGraphic],
    objectIdField: "ObjectID",
    renderer: carRenderer
  });

  // 5. 将图层添加到地图
  map.add(carsLayer);

  // 示例:动态更新航向并刷新渲染
  let currentHeading = initialGpsData.heading;
  document.getElementById("rotatePlus45Button").addEventListener("click", () => {
    currentHeading = (currentHeading + 45) % 360; // 每次增加45度
    document.getElementById("rotationDisplay").innerHTML = currentHeading;

    // 更新Graphic的属性
    carGraphic.attributes.heading = currentHeading;

    // 重新设置渲染器,强制图层刷新以应用新的视觉变量
    // 注意:对于FeatureLayer,直接修改Graphic属性后,
    // 需要通过更新Renderer或重新设置图层数据来触发重绘。
    // 这里通过重新创建Renderer来强制刷新。
    carsLayer.renderer = new SimpleRenderer({
      symbol: carSymbol,
      visualVariables: [
        {
          type: "rotation",
          field: "heading",
          rotationType: "geographic"
        }
      ]
    });
  });

  document.getElementById("rotationDisplay").innerHTML = currentHeading;
});

3.4 完整的HTML示例



    <meta charset="utf-8"><meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no"><title>ArcGIS JS API教程:基于GPS航向旋转Web样式符号</title><style>
        html,
        body,
        #viewDiv {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
        }
        #controlPanel {
            position: absolute;
            top: 10px;
            left: 10px;
            background: rgba(255, 255, 255, 0.8);
            padding: 10px;
            border-radius: 5px;
            z-index: 10;
        }
    </style><link rel="stylesheet" href="https://js.arcgis.com/4.26/esri/themes/light/main.css"><script src="https://js.arcgis.com/4.26/"></script><div id="controlPanel">
        当前航向: <span id="rotationDisplay"></span> 度
        <button id="rotatePlus45Button">旋转 +45°</button>
    </div>
    <div id="viewDiv"></div>

    <script>
        require([
            "esri/Map",
            "esri/views/MapView",
            "esri/layers/FeatureLayer",
            "esri/Graphic",
            "esri/renderers/SimpleRenderer"
        ], (Map, MapView, FeatureLayer, Graphic, SimpleRenderer) => {

            const map = new Map({
                basemap: "satellite"
            });

            const view = new MapView({
                container: "viewDiv",
                map: map,
                zoom: 15,
                center: [-101.9498125, 41.2097775],
            });

            const carSymbol = {
                type: "web-style",
                styleName: "EsriRealisticTransportationStyle",
                name: "BMW_3-Series"
            };

            const initialGpsData = {
                longitude: -101.9498125,
                latitude: 41.2097775,
                heading: 45 // 初始航向
            };

            const carGraphic = new Graphic({
                geometry: {
                    type: "point",
                    x: initialGpsData.longitude,
                    y: initialGpsData.latitude
                },
                attributes: {
                    ObjectID: 1,
                    heading: initialGpsData.heading
                }
            });

            const carRenderer = new SimpleRenderer({
                symbol: carSymbol,
                visualVariables: [
                    {
                        type: "rotation",
                        field: "heading",
                        rotationType: "geographic"
                    }
                ]
            });

            const carsLayer = new FeatureLayer({
                source: [carGraphic],
                objectIdField: "ObjectID",
                renderer: carRenderer
            });

            map.add(carsLayer);

            let currentHeading = initialGpsData.heading;
            document.getElementById("rotatePlus45Button").addEventListener("click", () => {
                currentHeading = (currentHeading + 45) % 360;
                document.getElementById("rotationDisplay").innerHTML = currentHeading;

                // 更新Graphic的属性
                carGraphic.attributes.heading = currentHeading;

                // 为了让FeatureLayer重新渲染并应用新的属性,
                // 最直接的方法是重新设置其renderer。
                // 在实际应用中,如果数据源是动态更新的FeatureLayer,
                // 可能需要调用 layer.queryFeatures() 或 layer.refresh(),
                // 或者直接修改数据源(如FeatureTable)来触发更新。
                carsLayer.renderer = new SimpleRenderer({
                    symbol: carSymbol,
                    visualVariables: [
                        {
                            type: "rotation",
                            field: "heading",
                            rotationType: "geographic"
                        }
                    ]
                });
            });

            document.getElementById("rotationDisplay").innerHTML = currentHeading;
        });
    </script>

4. 注意事项

  1. visualVariables应用于Renderer: 关键点在于rotation视觉变量是Renderer的属性,而不是直接应用于单个Graphic的symbol。如果你直接创建Graphic并将其添加到GraphicsLayer,你需要手动修改Graphic.symbol.angle属性来实现旋转。但对于数据驱动的批量旋转,FeatureLayer与Renderer的组合更为高效和推荐。
  2. field vs valueExpression:
    • field: 当旋转角度直接存储在要素的一个属性字段中时使用。
    • valueExpression: 当旋转角度需要通过一个或多个字段计算得出时使用,或者当字段名可能不固定时,它提供了更大的灵活性。
  3. rotationType: 根据你的数据来源,选择正确的rotationType非常重要。
    • "geographic": 0度指向正北,顺时针方向增加。这通常与GPS航向数据(heading)一致。
    • "arithmetic": 0度指向正东,逆时针方向增加。
  4. 动态数据更新: 当底层数据(例如GPS航向)发生变化时,你需要确保地图能够重新渲染以反映这些变化。
    • 如果使用FeatureLayer,更新要素属性后,可能需要重新设置layer.renderer来强制刷新,或者如果你的FeatureLayer是连接到实时数据源,数据更新会自动触发重绘。
    • 对于更复杂的实时更新场景,可以考虑使用StreamLayer或结合WebSocket等技术,并在数据更新时调用layer.refresh()。
  5. 性能考虑: 如果地图上有大量需要实时旋转的要素,频繁地更新Renderer或FeatureLayer可能会影响性能。在这种情况下,优化数据处理和渲染策略(例如,只更新视口内的要素)变得很重要。

5. 总结

通过本教程,我们学习了如何利用ArcGIS JavaScript API中的SimpleRenderer和rotation视觉变量,实现Web样式符号基于数据属性的动态旋转。这种方法不仅能够让地图上的符号更加生动地反映现实世界的状态,也为开发复杂的实时地理空间应用提供了强大的工具。掌握这一技术,将使你的地图应用在展示移动对象时更具表现力和实用性。

大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

2023.06.20

3696

8

js获取当前时间
js获取当前时间

JS全称JavaScript,是一种具有函数优先的轻量级,解释型或即时编译型的编程语言;它是一种属于网络的高级脚本语言,主要用于Web,常用来为网页添加各式各样的动态功能。js怎么获取当前时间呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.07.28

1175

5

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.03

1518

5

js是什么意思
js是什么意思

JS是JavaScript的缩写,它是一种广泛应用于网页开发的脚本语言。JavaScript是一种解释性的、基于对象和事件驱动的编程语言,通常用于为网页增加交互性和动态性。它可以在网页上实现复杂的功能和效果,如表单验证、页面元素操作、动画效果、数据交互等。

2023.08.17

9143

11

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

2023.09.01

820

4

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.04

2164

5

Js中concat和push的区别
Js中concat和push的区别

Js中concat和push的区别:1、concat用于将两个或多个数组合并成一个新数组,并返回这个新数组,而push用于向数组的末尾添加一个或多个元素,并返回修改后的数组的新长度;2、concat不会修改原始数组,是创建新的数组,而push会修改原数组,将新元素添加到原数组的末尾等等。本专题为大家提供concat和push相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.14

1409

5

js截取字符串的方法介绍
js截取字符串的方法介绍

JavaScript字符串截取方法,包括substring、slice、substr、charAt和split方法。这些方法可以根据具体需求,灵活地截取字符串的不同部分。在实际开发中,根据具体情况选择合适的方法进行字符串截取,能够提高代码的效率和可读性 。

2023.09.21

3629

3

js生成随机数方法
js生成随机数方法

JavaScript生成随机数的方法,包括使用Math.random()方法生成指定范围内的随机整数、生成随机字符串和生成随机颜色。根据具体需求,可以选择适合的方法来生成随机数,以实现各种功能 。

2023.09.25

1995

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 1.4万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 5.5万人学习

CSS教程
CSS教程

共754课时 | 93.1万人学习