js canvas 画准星

admin 109 0
使用JavaScript Canvas API绘制准星,可通过获取Canvas上下文,结合绘图方法实现,首先创建Canvas元素并获取2D渲染上下文,设置准星样式(如颜色、线宽),利用moveTolineTo绘制十字准星(水平与垂直线段),或通过arc绘制圆环准星,结合鼠标移动事件监听,动态更新准星位置,实现跟随鼠标的瞄准效果,还可通过stroke方法描边,或填充中心圆点增强视觉效果,常用于游戏瞄准界面或交互式应用中提供精准定位参考。

使用JavaScript和Canvas绘制动态准星:从基础到实战

准星是射击类游戏、交互式可视化工具甚至某些创意设计中的常见元素,它不仅需要精准定位,还需要具备良好的视觉效果和交互体验,本文将详细介绍如何使用JavaScript和Canvas API绘制静态与动态准星,并逐步实现跟随鼠标、呼吸效果等交互功能,助你掌握Canvas绘图的核心技巧。

Canvas绘制准星:从零开始

Canvas是HTML5提供的强大绘图工具,通过JavaScript可以灵活绘制图形,准星的基本形态通常由"十字线"或"圆环+十字线"构成,我们先从最基础的十字准星入手。

准备Canvas环境

在HTML中创建一个Canvas元素,并设置其尺寸(建议与窗口尺寸一致,或根据需求固定):

<canvas id="crosshairCanvas" width="800" height="600"></canvas>

然后通过JavaScript获取Canvas的2D绘图上下文:

const canvas = document.getElementById('crosshairCanvas');
const ctx = canvas.getContext('2d');

补充说明:在实际项目中,建议设置Canvas的尺寸为窗口大小,并处理窗口大小变化的情况:

function resizeCanvas() {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
}
window.addEventListener('resize', resizeCanvas);
resizeCanvas();

绘制基础十字准星

十字准星由两条垂直的线段组成,交叉点即为准星中心,假设准星中心位于Canvas中心(canvas.width/2, canvas.height/2),代码如下:

function drawBasicCrosshair() {
    ctx.clearRect(0, 0, canvas.width, canvas.height); // 清空画布
    const centerX = canvas.width / 2;
    const centerY = canvas.height / 2;
    const lineLength = 20; // 准星线段长度
    const lineWidth = 2;   // 线段宽度
    const color = '#ffffff'; // 准星颜色(白色)
    ctx.strokeStyle = color;
    ctx.lineWidth = lineWidth;
    ctx.lineCap = 'round'; // 线段端点为圆形
    // 绘制水平线
    ctx.beginPath();
    ctx.moveTo(centerX - lineLength, centerY);
    ctx.lineTo(centerX + lineLength, centerY);
    ctx.stroke();
    // 绘制垂直线
    ctx.beginPath();
    ctx.moveTo(centerX, centerY - lineLength);
    ctx.lineTo(centerX, centerY + lineLength);
    ctx.stroke();
}
drawBasicCrosshair(); // 调用绘制函数

代码中,clearRect用于清空画布(避免残留图形),strokeStylelineWidth设置线条样式,lineCap让线段端点更圆润,运行后,Canvas中心会出现一个白色十字准星。

进阶技巧:可以添加准星中心点,增强视觉效果:

// 在drawBasicCrosshair函数中添加中心点
function drawBasicCrosshair() {
    // ...之前的代码...
    // 绘制中心点
    ctx.fillStyle = color;
    ctx.beginPath();
    ctx.arc(centerX, centerY, lineWidth, 0, Math.PI * 2);
    ctx.fill();
}

绘制圆环准星(进阶版)

圆环准星在十字基础上增加了一个外圆,常见于射击游戏,只需在十字准星基础上添加圆形绘制逻辑:

function drawRingCrosshair() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    const centerX = canvas.width / 2;
    const centerY = canvas.height / 2;
    const lineLength = 15;
    const lineWidth = 2;
    const color = '#00ff00'; // 绿色准星
    const ringRadius = 10;  // 圆环半径
    ctx.strokeStyle = color;
    ctx.lineWidth = lineWidth;
    // 绘制圆环
    ctx.beginPath();
    ctx.arc(centerX, centerY, ringRadius, 0, Math.PI * 2);
    ctx.stroke();
    // 绘制十字线
    ctx.beginPath();
    ctx.moveTo(centerX - lineLength, centerY);
    ctx.lineTo(centerX + lineLength, centerY);
    ctx.moveTo(centerX, centerY - lineLength);
    ctx.lineTo(centerX, centerY + lineLength);
    ctx.stroke();
}
drawRingCrosshair();

arc方法用于绘制圆弧,参数为中心坐标、半径、起始角度(0)和结束角度(2π,即完整圆)。

变体设计:可以添加内圆或分段圆环,创造独特效果:

// 绘制分段圆环
function drawSegmentedRing() {
    // ...之前的代码...
    const segments = 8; // 分段数量
    const segmentLength = Math.PI * 2 / segments;
    for (let i = 0; i < segments; i++) {
        ctx.beginPath();
        ctx.arc(centerX, centerY, ringRadius, 
                i * segmentLength, (i + 0.5) * segmentLength);
        ctx.stroke();
    }
}

动态准星:跟随鼠标与呼吸效果

静态准星无法满足交互需求,我们需要让准星跟随鼠标移动,并添加呼吸动画(周期性缩放),提升真实感。

让准星跟随鼠标移动

通过监听mousemove事件,获取鼠标坐标,并实时更新准星位置:

let mouseX = canvas.width / 2;
let mouseY = canvas.height / 2;
// 监听鼠标移动
canvas.addEventListener('mousemove', (e) => {
    const rect = canvas.getBoundingClientRect(); // 获取Canvas相对于视口的位置
    mouseX = e.clientX - rect.left; // 计算鼠标在Canvas内的X坐标
    mouseY = e.clientY - rect.top;  // 计算鼠标在Canvas内的Y坐标
});
// 动态绘制准星(跟随鼠标)
function drawDynamicCrosshair() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    const lineLength = 15;
    const lineWidth = 2;
    const color = '#ff0000'; // 红色准星
    ctx.strokeStyle = color;
    ctx.lineWidth = lineWidth;
    // 绘制十字线(以鼠标位置为中心)
    ctx.beginPath();
    ctx.moveTo(mouseX - lineLength, mouseY);
    ctx.lineTo(mouseX + lineLength, mouseY);
    ctx.moveTo(mouseX, mouseY - lineLength);
    ctx.lineTo(mouseX, mouseY + lineLength);
    ctx.stroke();
}
// 使用requestAnimationFrame实现动画循环
function animate() {
    drawDynamicCrosshair();
    requestAnimationFrame(animate);
}
animate(); // 启动动画

关键点:getBoundingClientRect()用于修正鼠标坐标(Canvas可能不在视口左上角),requestAnimationFrame确保流畅的动画效果(每秒60帧)。

边界处理:可以添加边界检测,防止准星超出Canvas范围:

// 在mousemove事件处理中添加边界检查
canvas.addEventListener('mousemove', (e) => {
    const rect = canvas.getBoundingClientRect();
    mouseX = Math.max(lineLength, Math.min(canvas.width - lineLength, 
               e.clientX - rect.left));
    mouseY = Math.max(lineLength, Math.min(canvas.height - lineLength, 
               e.clientY - rect.top));
});

添加呼吸效果(周期性缩放)

呼吸效果通过正弦函数(Math.sin)控制准星大小或透明度的周期性变化:

let breatheTime = 0; // 呼吸动画时间
function drawBreathingCrosshair() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);

标签: #js #准星