43.在 Vue 3 中使用 OpenLayers 利用 Canvas Clip 实现上卷帘功能
前言
在地图应用中,我们时常会需要展示一些动态的视觉效果,例如通过滑动控制地图的部分显示,或者实现类似“卷帘”效果。今天,我们将探索如何使用 Vue 3 和 OpenLayers 来实现一个基于 Canvas 的“上卷帘”效果。通过滑动条的控制,用户可以看到地图上方的部分逐渐被裁切,形成类似卷帘的效果。
项目背景
OpenLayers 是一个强大的开源 JavaScript 库,用于构建交互式地图应用。它支持多种地图来源,如 OpenStreetMap、Stamen 等,并且具有强大的地图渲染能力。为了实现上卷帘效果,我们将使用 OpenLayers 中的 Canvas 渲染功能,通过动态剪切地图显示的区域,从而实现逐渐露出地图的效果。
目标
通过本教程,你将学会如何使用 OpenLayers 与 Vue 3 相结合,利用 Canvas 的 clip
方法在地图上实现上卷帘效果。通过滑动条,用户可以控制剪切区域的高度,从而实现动态的视觉效果。
项目准备
安装 Vue 3 和依赖
首先,你需要一个 Vue 3 项目。如果你还没有创建项目,可以使用 Vue CLI 创建一个新的项目:
vue create vue-openlayers
选择默认配置(或者你可以自定义配置),然后进入项目目录:
cd vue-openlayers
接下来,我们需要安装 OpenLayers 和 Element Plus(用于提供滑动条组件):
npm install ol element-plus
代码实现
实现 MapComponent.vue
在 MapComponent.vue
中,我们将实现地图的渲染,并添加 Canvas clip
操作。以下是完整的代码:
<!--
* @Author: 彭麒
* @Date: 2024/12/24
* @Email: 1062470959@qq.com
* @Description: 此源码版权归吉檀迦俐所有,可供学习和借鉴或商用。
-->
<template>
<div class="container">
<div class="font-bold text-[24px]">在vue3中使用OpenLayers利用canvas clip 实现上卷帘功能</div>
<h4>
<el-slider style="width: 500px; margin:0 auto;" v-model="swipeValue"></el-slider>
</h4>
<div id="vue-openlayers"></div>
</div>
</template>
<script setup>
// 引入 OpenLayers 的样式文件
import 'ol/ol.css';
// 引入 Vue 的 ref、watch 和 onMounted 函数
import { ref, watch, onMounted } from 'vue';
// 引入 OpenLayers 的 Map 类
import Map from 'ol/Map';
// 引入 OpenLayers 的 TileLayer 类
import TileLayer from 'ol/layer/Tile';
// 引入 OpenLayers 的 View 类
import View from 'ol/View';
// 引入 OpenLayers 的 OSM 数据源
import OSM from 'ol/source/OSM';
// 引入 OpenLayers 的 XYZ 数据源
import XYZ from 'ol/source/XYZ';
// 引入 OpenLayers 的 getRenderPixel 函数
import { getRenderPixel } from 'ol/render';
// 声明响应式变量 swipeValue,用于存储滑动条的值
const swipeValue = ref(50);
// 声明响应式变量 map,用于存储地图实例
const map = ref(null);
// 监听 swipeValue 的变化,重新渲染地图
watch(swipeValue, (newVal, oldVal) => {
if (oldVal !== newVal) {
map.value.render();
}
});
// 初始化地图
const initMap = () => {
// 创建 OSM 图层
const OSM_Layer = new TileLayer({
source: new OSM(),
});
// 创建 Stamen 图层,使用 XYZ 数据源
const StamenMap = new TileLayer({
source: new XYZ({
url: 'http://wprd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scl=1&style=6',
}),
});
// 创建地图实例
map.value = new Map({
target: 'vue-openlayers', // 设置地图容器的 id
layers: [OSM_Layer, StamenMap], // 添加图层
view: new View({
projection: 'EPSG:4326', // 设置投影坐标系
center: [116, 39], // 设置地图中心点
zoom: 4, // 设置缩放级别
}),
});
// 在渲染之前设置剪切区域
StamenMap.on('prerender', (event) => {
const ctx = event.context; // 获取渲染上下文
const mapSize = map.value.getSize(); // 获取地图大小
const height = mapSize[1] * (swipeValue.value / 100); // 计算剪切区域的高度
const tl = getRenderPixel(event, [0, height]); // 获取左上角像素
const tr = getRenderPixel(event, [mapSize[0], height]); // 获取右上角像素
const bl = getRenderPixel(event, [0, mapSize[1]]); // 获取左下角像素
const br = getRenderPixel(event, mapSize); // ��取右下角像素
ctx.save(); // 保存当前绘图状态
ctx.beginPath(); // 开始路径
ctx.moveTo(tl[0], tl[1]); // 移动到左上角
ctx.lineTo(bl[0], bl[1]); // 画线到左下角
ctx.lineTo(br[0], br[1]); // 画线到右下角
ctx.lineTo(tr[0], tr[1]); // 画线到右上角
ctx.closePath(); // 闭合路径
ctx.clip(); // 剪切路径
});
// 渲染后恢复绘图上下文
StamenMap.on('postrender', (event) => {
const ctx = event.context; // 获取渲染上下文
ctx.restore(); // 恢复绘图状态
});
};
// 在组件挂载后初始化地图
onMounted(() => {
initMap();
});
</script>
<style scoped>
.container {
width: 840px;
height: 590px;
margin: 50px auto;
border: 1px solid #42B983;
}
#vue-openlayers {
width: 800px;
height: 400px;
margin: 0 auto;
border: 1px solid #42B983;
position: relative;
}
</style>
代码解释
-
Canvas
clip
操作: 通过prerender
事件,我们可以获得地图的渲染上下文,并在渲染之前使用clip()
方法设置裁切区域,形成上卷帘的效果。clip()
方法使得只有指定区域内的地图内容会被绘制,其他部分会被裁切掉。 -
滑动条控制: 通过 Element Plus 的
el-slider
组件,我们提供了一个滑动条,用户可以控制swipeValue
的值,进而动态改变剪切区域的高度。滑动条的值决定了上卷帘的高度,值越大,显示的区域越多。 -
地图初始化: 使用 OpenLayers 创建了一个地图实例,并添加了 OSM 和 Stamen 的图层。地图中心设置在 [116, 39](中国的中心),并且设置了一个初始的缩放级别。
结果展示
当用户拖动滑动条时,地图会动态地裁切上方的部分,随着滑动条的变化,更多或更少的地图内容会被展示出来,形成一个类似“卷帘”效果的动态展示。
总结
通过 OpenLayers 和 Vue 3 的组合,我们成功实现了基于 Canvas 的上卷帘效果。借助 OpenLayers 强大的地图渲染功能和 Vue 3 的响应式系统,我们能够轻松地实现这种动态的视觉效果,并且通过简单的滑动条组件控制其变化。这种效果可以广泛应用于地图应用中,增加交互性和用户体验。
参考链接
- OpenLayers 官方文档
- Vue 3 官方文档