最近在做有关地图的工作,使用的技术栈是谷歌地图,先说一下需求吧。
需求背景:
现在地图上有marker,我要在marker上面添加一层扩散波的波纹效果;
整体思路:
首先要考虑,实现扩散波的起点,或者说入口,就是谷歌地图的maps对象里的Circle方法。实现扩散其实就是需要在marker上使用circle画一些圆,然后让圆圈以一定的速度改变半径、透明度等要素;
下面开始上代码啦:
function DiffusionWave(radius, level, point, color, zoom, map) {
this.radius = radius // 半径
this.google = window.google
this.level = level // 扩散波数量
this.point = point // 添加扩散波的位置
this.zoom = zoom // 地图层级
this.map = map // 谷歌地图实例
this.color = color // circle配置对象,主要是fillColor,fillOpacity等,根据业务需求可以自己添加其他属性
// 我自己的代码在这里由于需求,有一部分限制扩散波范围的逻辑,就是一些简单的判断,需要的朋友自己加一下,我就不写了。
this.endOpacity = 0.5
this.speedOpacity = (this.color.fillOpacity - this.endOpacity) / this.radius
// 这里是计算了每一次变化透明度的变化速度
this.circles = []
for (let i = 1; i < this.level; i++) {
const circle = new this.google.maps.Circle({
strokeColor: color.strokeColor,
strokeOpacity: 0.8,
strokeWeight: 1,
fillColor: color.fillColor,
fillOpacity: 0.35,
map: this.map,
center: this.point
radius: 100
})
this.circles.push(circle)
}
this.clock = new Array(this.level)
}
DiffusionWave.prototype.start = function (delay, speed) {
const that = this
function animateStart (startTime, circle, index) {
const time = new Date.getTime() - startTime
if (time < 0) {
circle.setOptions({
strokeColor: that.color.strokeColor,
strokeOpacity: 0.8,
strokeWeight: 1,
fillColor: that.color.fillColor,
fillOpacity: 0.35,
map: that.map,
center: that.point,
radius: 0
})
//这里的window方法的使用,详见https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestAnimationFrame
that.clock[index] = window.requestAnimationFrame(animateStart.bind(null, startTime, circle, index))
return
}
const r = Math.floor(that.radius * (2 * time / speed - time * time / speed / speed))
if (time >= speed) {
circle.setOptions({
strokeColor: that.color.strokeColor,
strokeOpacity: 0.8,
strokeWeight: 1,
fillColor: that.color.fillColor,
fillOpacity: 0.35,
map: that.map,
center: that.point,
radius: 0
})
startTime = new Date().getTime() + delay
that.clock[index] = window.requestAnimationFrame(animateStart.bind(null, startTime, circle, index))
} else {
const opacity = that.color.fillOpacity - Number.parseFloat((that.speedOpacity * r).toFixed(5))
circle.setOptions({
strokeColor: that.color.strokeColor,
strokeOpacity: opacity,
strokeWeight: 1,
fillColor: that.color.fillColor,
fillOpacity: opacity,
map: that.map,
center: that.point,
radius: r
})
that.clock[index] = window.requestAnimationFrame(animateStart.bind(null, startTime, circle, index))
}
}
for (const [index, circle] of this.circles.entries()) {
animateStart(new Date().getTime() + index * delay, circle, index)
}
}
DiffusionWave.prototype.remove = function () {
for(const caf of clock) {
window.cancelAnimationFrame(caf)
}
for (const circle of this.circles) {
circle.setMap(null)
}
}
代码到这里就结束了,因为内网开发,这些代码都是手打的,可能会有错误的地方,欢迎指正。
这里呢,其实这种方法也不是我自己想到的,借鉴了网友的案例,然后根据我自己的需求进行了改造,基本上实现了我这边的需求,在此非常感谢各位网友,帮助我成长了不少。
学习这些代码让我感触最深的就是两点,第一是实现一个需求或者功能,的一种思路,尽管很多官方已经给我们提供了非常方便的API,但是有时候项目需要更’酷炫’的效果,就需要我们自己封装了。第二是以前没关注过requestAnimationFrame这个API,哈哈,这次也了解了一些。