概述
本文为注水文章,通过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)
}
网友评论