- 一看就会,十分钟看完。后边用到不挠头发。
- 这个其实没什么难点,在地图上动效不是很常见,最主要的是我在搜索
高德地图雷达扫描, 地图雷达扫描得到的并没有直接能用的。某篇文章的评论下一位老哥评论说
我是很能理解这种心情的,搜索发现有案例,然后发现案例需要加好友获取🤬
开始
- 实例中使用
vue + 高德jsApi + canvas实现。其实就是把canvas画好的雷达扫描添加到地图上。 - 目前支持添加
canvas的地图有四维图新,高德,百度等,当然除了这几家可能还有其他的地图也支持,但是我不知道,所以就不列举了。 - 雷达扫描效果,是从这篇文章借鉴过来的,做了一点点改动
地图上加载canvas
- 注意:文中使用的api版本为 2.0
- 高德地图的加载,初始化这里就不再叙述了,官网文档写的很清晰此处丢个链接
地图上如何加载canvas
- 首先还是要先看下官方文档,在图层-》自有数据图层下有一个canvas图层的示例就是我们要找的链接在此,主要就是这段代码
// 创建一个 canvas图层
// canvas 的创建的 canvas 元素
// bounds 界限 canvas元素展示范围的大小及在地图的那个点展示(个人理解)
var CanvasLayer = new AMap.CanvasLayer({
canvas: canvas,
bounds: new AMap.Bounds(
[116.328911, 39.937229],
[116.342659, 39.946275]
),
zooms: [3, 18],
});
// 添加到地图
map.addLayer(CanvasLayer);
- 现在我们,有了canvas绘制的雷达扫描图以及加载到地图的上的方法。那么就可以开始组合代码了
将雷达扫描图加载到地图上
- 看似代码很长,主要是创建雷达扫描图的函数比较长,但是无需关心。三个函数
initMap初始化地图 加载完成后执行加载canvas图层的操作。initMyCanvas创建雷达扫描addTestCanvas创建canvas图层并将canvas雷达扫描加载到地图
<template>
<div class="mapbox">
<!-- 地图加载容器 -->
<div id="map"></div>
<!-- canvas 雷达扫描图容器 -->
<canvas id="canvas" width="300" height="300"></canvas>
</div>
</template>
<script>
export default {
name: "GDMap",
data () {
return {
mapObj: null
}
},
mounted() {
// 初始化 高德地图
this.initMap()
},
methods: {
// 地图初始化函数
initMap() {
this.mapObj = new AMap.Map('map', {
viewMode:"3D",
center: [116.335183, 39.941735],
zoom: 14
})
// 保存this
let self = this
// 地图图块加载完成后触发
this.mapObj.on('complete', function(){
self.addTestCanvas()
});
},
// 创建 雷达扫描图 https://wjoan.github.io/2017/06/15/canvas/ 由此借鉴
initMyCanvas(canvas) {
const c = document.getElementById(canvas);
let animID = null
// 未能找到该DOM对象
if (!c) {
console.log("[error] can not find id '" + canvas + "'");
return null;
}
// 引用了错误的DOM对象
if (!c.getContext) {
console.log("[error] getContext is undefined");
return null;
}
const ctx = c.getContext("2d");
// 画布的宽高
const cWidth = c.width;
const cHeight = c.height;
// 中心点
const centerX = c.width / 2;
const centerY = c.height / 2;
// 半径
const radius = centerX * 0.9;
const drawPoint = function (x, y, n) {
ctx.lineWidth = 1;
for (let i = n; i > 0; i--) {
ctx.beginPath();
ctx.arc(x, y, n - i, 0, 2 * Math.PI);
ctx.strokeStyle = "rgba(42,195,39," + i / n + ")";
ctx.stroke();
}
};
const drawCircle = function (r, lineWidth = 1, color = "#090") {
ctx.beginPath();
ctx.setLineDash([]);
ctx.arc(centerX, centerY, r, 0, 2 * Math.PI);
ctx.lineWidth = lineWidth;
ctx.strokeStyle = color;
ctx.stroke();
};
const drawSector = function (sAngle, eAngle) {
let blob = 50;
let increase = 0;
if (sAngle < eAngle) {
increase = (eAngle - sAngle) / blob;
} else if (sAngle > eAngle) {
increase = (Math.PI * 2 - sAngle + eAngle) / blob;
} else {
return;
}
let angle1 = sAngle;
let angle2 = sAngle + increase;
for (let i = 0; i < blob; i++) {
ctx.beginPath();
ctx.moveTo(centerX, centerY);
ctx.arc(centerX, centerY, radius, angle1, angle2);
ctx.fillStyle = "rgba(42,195,39," + i / blob + ")";
ctx.fill();
angle1 = angle2;
angle2 = angle1 + increase;
if (angle2 >= Math.PI * 2) {
ctx.beginPath();
ctx.moveTo(centerX, centerY);
ctx.arc(centerX, centerY, radius, angle1, Math.PI * 2);
ctx.fillStyle = "rgba(42,195,39," + i / blob + ")";
ctx.fill();
angle1 = 0;
angle2 = angle1 + increase;
}
}
};
const Line = function (x, y, lineDash = [], color = "#396a00", lineWidth = 1) {
ctx.beginPath();
ctx.setLineDash(lineDash);
ctx.moveTo(centerX, centerY);
ctx.lineTo(x, y);
ctx.lineWidth = lineWidth;
ctx.strokeStyle = color;
ctx.stroke();
};
const init = function () {
// 背景上填充为黑色
ctx.fillStyle = "transparent";
ctx.fillRect(0, 0, cWidth, cHeight);
for (let i = 1; i <= 8; i++) {
Line(centerX + Math.sin(Math.PI * i / 4) * radius,
centerY + Math.cos(Math.PI * i / 4) * radius,
[5, 3], "#396a00");
}
for (let i = 1; i <= 15;) {
Line(centerX + Math.sin(Math.PI * i / 8) * radius,
centerY + Math.cos(Math.PI * i / 8) * radius,
[], "#062807");
i += 2;
}
drawCircle(0.9 * centerY, 2.5);
drawCircle(0.8 * centerY, 2.5, "#042906");
drawCircle(0.6 * centerY);
drawCircle(0.3 * centerY);
};
return {
animID: undefined,
points: [
[cWidth / 3, cHeight * 3 / 7],
[cWidth * 4 / 5, cHeight * 6 / 9]
],
addPoints(x, y) {
this.points.push([x, y]);
},
clear() {
cancelAnimationFrame(animID); // 停止动画
ctx.clearRect(0, 0, cWidth, cHeight); // 清除画布
this.points = [[cWidth / 3, cHeight * 3 / 7], [cWidth * 4 / 5, cHeight * 6 / 9]]; // 重置默认点
},
scan() {
let angle = Math.PI / 4;
let scanBegin = 0;
let scanEnd = angle;
let pointRadius = 1;
// 绘制雷达扫描
let move = () => {
ctx.clearRect(0, 0, cWidth, cHeight); // 清除画布
init(); // 重绘背景
drawSector(scanBegin, scanEnd); // 绘制扇形扫描区域
// drawPoint(cWidth/3, cHeight*3/7, pointRadius); // 绘制发光点
// drawPoint(cWidth*4/5, cHeight*6/9, pointRadius);
for (let p of this.points) {
drawPoint(p[0], p[1], pointRadius);
}
// 改变点的半径以及扇形的角度
pointRadius += 0.08;
scanBegin += angle / 25;
scanEnd = scanBegin + angle;
// 超过阈值变为初始值
if (scanBegin >= Math.PI * 2) {
scanBegin = 0;
scanEnd = scanBegin + angle;
}
if (pointRadius >= 7) pointRadius = 0;
// 再次绘制
animID = window.requestAnimFrame(move);
}
window.requestAnimFrame = (function () {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
animID = window.requestAnimFrame(move);
},
stopScan() {
cancelAnimationFrame(animID);
}
}
},
// 创建canvas图层,并把雷达扫描图加载到地图中
addTestCanvas() {
// 创建图层
const CanvasLayer = new AMap.CanvasLayer({
canvas: document.getElementById('canvas'),
bounds: new AMap.Bounds(
[116.328911, 39.937229],
[116.362659, 39.966275]
),
zooms: [3, 18],
});
// 将图层加载到地图
this.mapObj.addLayer(CanvasLayer);
// 异步加载 其实延迟一秒更好,通过js创建canvas元素则不需要。
this.$nextTick(() => {
// 创建雷达扫描图 并开始动画
this.initMyCanvas('canvas').scan()
})
}
},
beforeDestroy() {
// 当地图存在 销毁地图
if (this.mapObj) {
this.mapObj.destroy( );
}
}
}
</script>
<style lang="stylus" scoped>
.mapbox{
width 100%
height 100%
#map{
width 100%
height 100%
}
}
</style>
其他地图加载canvas
- 其实都差不多,具体看官网示例,食材都给你了,还能饿着自己?
百度
- 覆盖物-》叠加层-》地面canvas叠加层 我是官网链接
四维图新
- 图层-》特殊图层-》canvas source图层 我是官网链接
- 这个地图估计也没有太高的知名度, 具体的可以百度下, 还有个超图 他俩挺像🤔
文章就到结束了,觉得还行的点个赞啊。
- 欢迎讨论。