美文网首页GIS加油站
雷达扫描效果的实现

雷达扫描效果的实现

作者: 牛老师讲GIS | 来源:发表于2023-07-19 22:22 被阅读0次

概述

本文为注水文章,通过canvas实现雷达扫描的效果。

效果

map.gif

实现代码

1. 绘制并裁剪图片

// 绘制扇形区域
ctx.save()
ctx.globalAlpha = 0.15
ctx.arc(x, y, radius, 0, Math.PI * 2)
ctx.clip()
ctx.drawImage(image, 0, 0, width, height)
ctx.restore()
ctx.save()
ctx.globalAlpha = 0.65
// 绘制圆形区域
ctx.beginPath()
ctx.moveTo(x, y)
ctx.lineTo(x1, y1)
ctx.arc(x, y, radius, a, a1)
ctx.closePath()
ctx.clip()
ctx.drawImage(image, 0, 0, width, height)
ctx.restore()

2. 绘制圆

function drawCircle(radius, color = '#0eda29', startAngle = 0, lineWidth = 2, ruleNum = 120, ruleOffset = 15) {
    ctx.beginPath()
    ctx.strokeStyle = color
    ctx.lineWidth = lineWidth
    ctx.lineCap = 'round'
    // circle
    ctx.arc(x, y, radius, 0, Math.PI * 2)
    ctx.stroke()
    // rule
    drawRules(radius, startAngle, ruleNum, ruleOffset)
}

3. 绘制标尺与轴

function drawAxis() {
    const num = 4
    const delt = Math.PI / num
    for (let i = 0; i < num; i++) {
        const [x1, y1] = getXY([x, y], radius - 25, i *  delt)
        const [x2, y2] = getXY([x, y], radius - 25, i *  delt + Math.PI)
        ctx.beginPath()
        ctx.moveTo(x1, y1)
        ctx.lineTo(x2, y2)
        ctx.stroke()
    }
}
function drawRules(radius, startAngle = 0, ruleNum = 120, ruleOffset = 15) {
    const delt = Math.PI / (ruleNum / 2)
    for(let i = 0; i < ruleNum; i++) {
        const [x1, y1] = getXY([x, y], radius, i *  delt + startAngle)
        const [x2, y2] = getXY([x, y], radius - ruleOffset, i *  delt + startAngle)
        ctx.beginPath()
        ctx.moveTo(x1, y1)
        ctx.lineTo(x2, y2)
        ctx.stroke()
    }
}

4. 动画实现

通过requestAnimationFrame实现动画。

function animate() {
    ctx.clearRect(0, 0, width, height)
    const a = index *  interval, a1 = a + Math.PI / 4
    const [x1, y1] = getXY([x, y], radius, a)
    const [x2, y2] = getXY([x, y], radius, a1)
    ctx.save()
    ctx.globalAlpha = 0.15
    ctx.arc(x, y, radius, 0, Math.PI * 2)
    ctx.clip()
    ctx.drawImage(image, 0, 0, width, height)
    ctx.restore()
    ctx.save()
    ctx.globalAlpha = 0.65
    ctx.beginPath()
    ctx.moveTo(x, y)
    ctx.lineTo(x1, y1)
    ctx.arc(x, y, radius, a, a1)
    ctx.closePath()
    ctx.clip()
    ctx.drawImage(image, 0, 0, width, height)
    ctx.restore()
    // draw circle
    drawCircle(radius * 0.4, '#fc5a83', index * angle2, 2, 40, 6)
    drawCircle(radius * 0.7, '#2091f3', index * angle1, 2, 80, 8)
    drawCircle(radius)
    // draw axis
    drawAxis()
    // transparent arc
    const style = ctx.createLinearGradient(x1, y1, x2, y2)
    style.addColorStop(0,'rgba(0,255,255, 0)');
    style.addColorStop(1,'rgba(0,255,255, 0.2)');
    ctx.fillStyle = style
    ctx.strokeStyle = 'rgba(0,255,255, 0.2)'
    ctx.beginPath()
    ctx.moveTo(x, y)
    ctx.lineTo(x1, y1)
    ctx.arc(x, y, radius, a, a1)
    ctx.closePath()
    ctx.fill()
    ctx.stroke()
    const styleLine = ctx.createLinearGradient(x, y, x2, y2)
    styleLine.addColorStop(0,'rgba(0,255,255, 0.5)');
    styleLine.addColorStop(1,'rgba(0,255,255, 1)');
    ctx.fillStyle = styleLine
    const offset = Math.PI / 600
    const [x3, y3] = getXY([x, y], radius, a1 - offset)
    ctx.beginPath()
    ctx.moveTo(x, y)
    ctx.lineTo(x3, y3)
    ctx.arc(x, y, radius, a1 - offset, a1 + offset)
    ctx.closePath()
    ctx.fill()
    // center
    ctx.beginPath()
    ctx.arc(x, y, 6, 0, Math.PI * 2)
    ctx.fillStyle = '#0eda29'
    ctx.fill()
    index++
    if(index === 720) index = 0
    requestAnimationFrame(animate)
}

相关文章

网友评论

    本文标题:雷达扫描效果的实现

    本文链接:https://www.haomeiwen.com/subject/lbeaudtx.html