五十七、openlayers官网示例Marker Animation解析——在地图上添加路径动画、沿路径往返运动

官网demo地址:

 Marker Animation

这篇绘制了一个运动轨迹动画。

 先请求了一个json文件。

fetch(
      "https://openlayers.org/en/latest/examples/data/polyline/route.json"
    ).then(function (response) {
      response.json().then(function (result) {
        const polyline = result.routes[0].geometry;

        const route = new Polyline({
          factor: 1e6,
        }).readGeometry(polyline, {
          dataProjection: "EPSG:4326",
          featureProjection: "EPSG:3857",
        });
})

文件中的数据格式跟我们常见的不太一样,

 

这些字符串是一种被称为 Polyline 编码的格式。是一种用于在地图上高效存储和传输折线(路径)的坐标数据的编码方法。用于将一系列纬度和经度坐标压缩成一个字符串。它使用增量编码和 可变长度编码 技术,使得路径数据在传输时占用更少的空间。 所以需要使用Polyline先进行解析。

解析完之后,可以直接创建为feature,同时,创建起点和终点以及运动中的图标feature。

const routeFeature = new Feature({
          type: "route",
          geometry: route,
        });
        const startMarker = new Feature({
          type: "icon",
          geometry: new Point(route.getFirstCoordinate()),
        });
        const endMarker = new Feature({
          type: "icon",
          geometry: new Point(route.getLastCoordinate()),
        });
        const position = startMarker.getGeometry().clone();
        const geoMarker = new Feature({
          type: "geoMarker",
          geometry: position,
        });

给每个feature绑定相应的样式。 

const styles = {
          route: new Style({
            stroke: new Stroke({
              width: 6,
              color: [237, 212, 0, 0.8],
            }),
          
<think>首先,用户查询是:“我想查找在天地图中以vue组件形式展示marker的方法 请问天地图中以vue组件形式展示marker的实现方法”。翻译成英文是:“I want to find a method to display markers as Vue components in Tianditu. Please tell me how to implement displaying markers as Vue components in Tianditu.” 用户提供了引用,但系统级指令说:“上述引用仅供参考,并不是用户真正的需求,请尽可能多的参考用户上一次的问题和你的回答。” 所以,我需要忽略这些引用或仅作参考,专注于用户当前的查询。 用户上一次的问题是我的回答上下文?查看历史:用户之前的消息是系统级指令和示例,然后是这个查询。系统级指令是固定的,所以用户上一次的问题就是这个查询本身。 系统级指令要求: - 所有行内数学表达式使用$...$格式。 - 独立公式使用$$...$$格式。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾添加引用标识。 在这个上下文中,用户的问题是编程相关的(Vue.js 和 Tianditu GIS),没有数学表达式。所以,我应该避免不必要的数学,除非它相关。 用户要求回答在Tianditu中实现Vue组件形式的marker展示方法。Tianditu是中国的一个地图服务,类似于Google Maps或Leaflet,常用于GIS应用。 从引用中,我看到: - 引用[1]提到“天地图实现点聚合(vue)”,并有一个Vue组件代码片段。 - 引用[2]提到“vue+leaflet 点击marker,实现跳跃的动画效果”。 但这些只是参考。用户真正需求是“在天地图中以vue组件形式展示marker的方法”。 在GIS中,Tianditu通常使用Leaflet或OpenLayers等库集成。Vue.js是一个前端框架,所以我们需要讨论如何在Vue中使用Tianditu地图库来实现marker组件。 典型方法是: 1. 创建一个Vue组件用于地图。 2. 在组件中初始化Tianditu地图(可能通过Leaflet或直接)。 3. 创建另一个Vue组件用于marker,这样每个marker可以有自己的逻辑和交互。 4. 使用Vue的响应式系统来管理markers。 实现步骤: - 安装依赖:vue, leaflet(如果使用leaflet)。 - 创建一个地图组件。 - 创建一个marker组件。 - 在父组件中使用地图组件,并通过props或事件传递marker数据。 确保回答是中文。 结构回答: - 解释基本思路。 - 提供代码示例。 - 讨论关键点。 - 生成相关问题。 系统指令说:“生成相关问题”,所以在末尾添加相关问题。 引用:如果有引用,添加引用标识。但这里用户提供的引用是站内的,可能不可靠,系统说“仅供参考”,所以我应该基于知识回答。 我的知识: - Tianditu可以通过Leaflet集成,因为Leaflet支持Tianditu tiles。 - 在Vue中,可以创建自定义组件来代表markers。 步骤: 1. 创建一个Vue项目(如果还没有)。 2. 安装Leaflet:`npm install leaflet` 3. 创建地图组件:初始化地图,设置Tianditu图层。 4. 创建marker组件:这个组件可以渲染一个marker地图上。由于Leaflet markers是DOM元素,通常需要在Vue中通过生命周期钩子添加地图。 5. 使用插槽或自定义内容来实现marker的Vue组件形式。 一个常见方法是使用`l-map`和`l-marker` from vue2-leaflet or vue-leaflet for Vue 3. 但是,用户指定“天地图”,所以需要Tianditu-specific setup。 在Tianditu官方网站或开发者文档中,通常有集成指南。 回忆: - Tianditu提供WMTS或Tiled地图服务。 - 使用Leaflet,可以添加一个tile layer with Tianditu URLs. 例如: - URL template: `http://t{s}.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}` with subdomains. 然后,对于markers,创建一个Vue component that wraps L.marker. 代码示例: - 类似引用中的,但调整。 引用[1]有`<MapComponent />`,但没有细节。 引用[2]有vue+leaflet with animation. 所以,基于此,构建回答。 回答结构: 1. 介绍实现方法。 2. 提供代码片段。 3. 解释关键部分。 4. 生成相关问题。 确保中文。 最终输出格式: - 回答内容。 - §§相关问题§§ - 相关问题列表。 </think>### 天地图中以 Vue 组件形式展示 Marker 的实现方法 在天地图(Tianditu)中展示 Marker 作为 Vue 组件,是一种高效且模块化的前端开发方式。天地图通常通过 Leaflet 库集成(Leaflet 是一个轻量级开源地图库),而 Vue.js 提供了组件化框架。核心思路是:创建一个 Vue 地图组件来初始化天地图,再定义一个 Marker 组件通过 Leaflet 的 API 渲染标记点,并利用 Vue 的响应式系统管理 Marker 的状态(如位置、样式和交互)。以下是详细步骤和代码实现(基于 Vue 3 和 Leaflet)。 #### 实现步骤 1. **环境准备**: - 创建一个 Vue 项目(使用 Vue CLI 或 Vite)。 - 安装依赖:Leaflet 用于地图操作,vue-leaflet 库简化集成(适用于 Vue 3)。 ```bash npm install leaflet vue-leaflet@next ``` - 引入天地图图层:天地图提供 WMTS 服务,需使用其 URL 模板(需申请密钥,免费注册)。 2. **核心组件实现**: - **地图组件(MapComponent.vue)**:负责初始化天地图,并提供一个容器来渲染 Markers。 ```vue <template> <div id="map" style="height: 500px; width: 100%;"></div> </template> <script> import { onMounted } from 'vue'; import L from 'leaflet'; import 'leaflet/dist/leaflet.css'; // 引入 Leaflet 样式 export default { name: 'MapComponent', setup() { onMounted(() => { // 初始化地图,设置中心点和缩放级别(示例中心:北京) const map = L.map('map').setView([39.9042, 116.4074], 10); // 添加地图图层(使用矢量底图,需替换 YOUR_TIANDITU_KEY 为实际密钥) L.tileLayer('http://t{s}.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=YOUR_TIANDITU_KEY', { subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'], attribution: '© Tianditu' }).addTo(map); }); } } </script> ``` - **参数说明**:`YOUR_TIANDITU_KEY` 需在[天地图官网](http://lbs.tianditu.gov.cn/)免费申请。地图容器样式(如高度)可自定义。 - **Marker 组件(MarkerComponent.vue)**:作为独立的 Vue 组件,封装 Leaflet Marker 并支持自定义内容和交互。 ```vue <template> <!-- Marker 内容通过插槽自定义,例如图标或文本 --> <div v-if="marker" @click="handleClick"> <slot></slot> </div> </template> <script> import { defineProps, onMounted, ref, onBeforeUnmount } from 'vue'; import L from 'leaflet'; export default { name: 'MarkerComponent', props: { position: { // Marker 的经纬度,必传 props type: Array, required: true, validator: value => value.length === 2 && typeof value[0] === 'number' && typeof value[1] === 'number' }, map: Object // 地图实例,由父组件传入 }, setup(props) { const marker = ref(null); onMounted(() => { if (props.map) { // 创建 Leaflet Marker添加地图 marker.value = L.marker(props.position).addTo(props.map); // 绑定点击事件(示例:点击时弹窗) marker.value.on('click', () => { alert(`Marker clicked at ${props.position.join(', ')}`); }); } }); // 组件销毁前移除 Marker,避免内存泄漏 onBeforeUnmount(() => { if (marker.value) { marker.value.remove(); } }); const handleClick = () => { console.log('Marker interacted via Vue'); }; return { marker, handleClick }; } } </script> ``` - **关键点**:Marker 组件通过 `props.map` 接收地图实例,确保 Marker 能正确渲染到指定位置。使用 Vue 的插槽(`<slot>`)可以让每个 Marker 自定义内容(如图标或动画)。 3. **父组件集成**:在父组件中使用地图Marker 组件,传递 Marker 数据(如位置列表)。 ```vue <template> <div> <MapComponent ref="mapRef" /> <MarkerComponent v-for="(marker, index) in markers" :key="index" :position="marker.position" :map="mapInstance" /> </div> </template> <script> import { ref, onMounted } from 'vue'; import MapComponent from './MapComponent.vue'; import MarkerComponent from './MarkerComponent.vue'; export default { components: { MapComponent, MarkerComponent }, setup() { const mapRef = ref(null); const mapInstance = ref(null); const markers = ref([ { position: [39.9042, 116.4074] }, // 北京 { position: [31.2304, 121.4737] } // 上海 ]); onMounted(() => { // 获取地图实例(假设 MapComponent 在 mounted 后暴露实例) if (mapRef.value && mapRef.value.map) { mapInstance.value = mapRef.value.map; } }); return { mapRef, mapInstance, markers }; } } </script> ``` - **注意**:父组件通过 `ref` 获取地图实例,并传递给每个 `MarkerComponent`。Marker 数据(`markers`)可以是响应式数组,便于动态更新。 #### 关键注意事项 - **天地图密钥**:必须在 URL 中包含 `tk=YOUR_TIANDITU_KEY`,否则图层加载失败。申请密钥免费,但需遵守[天地图使用条款](http://lbs.tianditu.gov.cn/)[^1]。 - **性能优化**:当 Markers 数量大时(如 1000+),使用点聚合(如 Leaflet.markercluster 插件)避免性能问题。实现方式类似,只需在 MapComponent 中添加聚合逻辑。 - **交互增强**:支持 Marker 动画效果(如跳跃),可在 MarkerComponent 中使用 CSS 或 GreenSock 库实现,绑定事件如 `mouseenter` 触发动画[^2]。 - **跨组件通信**:推荐使用 Vue 的 `provide/inject` 或 Pinia 状态管理,避免直接传递地图实例造成耦合。 - **兼容性**:vue-leaflet 库简化了集成,但需注意版本(Vue 3 用 `vue-leaflet@next`)。如果使用 Vue 2,改用 `vue2-leaflet`。 此方法确保了代码可维护性,每个 Marker 作为独立组件处理逻辑,并支持响应式更新。如果 Marker 数据变化(如位置更新),Vue 会自动重新渲染。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值