Canvas滚轮缩放和拖动画布【2023年度总结:一个疲惫的程序员】

Canvas滚轮缩放和拖动画布

2023年度总结:一个疲惫的程序员

2023,留给这一年的时间不多了,总结一下吧。

从前我是一名WebGL动效工程师,在公司负责可视化大屏动效的开发。从年初开始就被迫转岗,调到普通的前端开发岗位,从此开始了一段!愉快的经历

项目样式调整和切图变成了我的主要工作。项目是从AngularJS开始写的,那是一个古老的框架,然后慢慢的迭代,一直到现在的Angular12版本。项目经过N多人的手,里面的样式文件几十个,静态以及npm包依赖上百个,各种奇奇怪怪的隐藏问题,各种奇奇怪怪的需求,各种奇奇怪怪的问题都在里面。有的时候,提一个样式修改的需求,代码一行没写,测试就已经提出一堆的bug了。有时候,一个小小的需求,需要改动几十个文件,几百行代码。有时候,一个小小样式变更,就影响了整个项目的布局,而且还不知道影响范围有多大。工作真的挺有意思的,我很喜欢,总结起来就是非常的疲惫。

我把关键词告诉AI:

一个疲惫不堪的程序员,漫画风格,男,秃头。

很快啊,它给了我一张照片,我觉得很满意,因为它忽视了秃头关键字。而是用大肚腩来代替,还有那布满血丝的大眼睛,疲惫值直接拉满!满桌子的TODO便签很是刺眼。

开始今天的正题,用canvas来实现画布的缩放和拖动吧。

在Canvas中实现鼠标缩放和移动画布的功能

Canvas是一个HTML5元素,可以通过JavaScript绘制2D图形。本文将介绍如何在Canvas中实现鼠标缩放和移动画布的功能。

首先,我们需要一个Canvas元素和一个2D绘图上下文。可以通过以下代码获取Canvas元素并获取上下文:

javascript 复制代码
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

在这里,我们给Canvas元素添加了一个ID为canvas,以便获取它。然后,我们使用getContext('2d')方法获取了2D绘图上下文。

接下来,我们加载一张图片到Canvas中,并在加载完成后调用draw函数绘制图片:

javascript 复制代码
const img = new Image();
img.src = './疲惫的程序员.png';
img.onload = function () {
    draw(0, 0, 0.5);
};

draw函数中,我们使用ctx.save()ctx.restore()方法来保存和恢复绘图状态。然后,我们使用ctx.translate()方法来移动Canvas中绘制的内容,以实现Canvas的移动效果。在我们的示例中,Canvas通过鼠标拖拽移动。

javascript 复制代码
let isDrag = false;
let lastX = 0, _lastX = 0;
let lastY = 0, _lastY = 0;

canvas.addEventListener('mousedown', function (e) {
    isDrag = true;
    lastX = e.clientX - _lastX;
    lastY = e.clientY - _lastY;
});

canvas.addEventListener('mousemove', function (e) {
    if (isDrag) {
        const x = e.clientX;
        const y = e.clientY;
        const dx = x - lastX;
        const dy = y - lastY;
        _lastX = dx;
        _lastY = dy;
        draw(dx, dy, scale);
    }
});

canvas.addEventListener('mouseup', function (e) {
    isDrag = false;
});

在代码中,我们使用鼠标事件监听器来获取鼠标的位置,并计算鼠标移动的距离。然后,我们通过调用draw函数来绘制Canvas的内容,并传递移动的距离作为参数。

除了移动Canvas之外,我们还可以通过鼠标滚轮来缩放Canvas中的内容。在代码中,我们使用canvas.onmousewheel监听鼠标滚轮事件,并通过ctx.scale()方法来实现缩放效果。

javascript 复制代码
let scale = 0.5;

canvas.onmousewheel = function (e) {
    e.preventDefault();
    const delta = e.wheelDelta / 1800;
    scale += delta;
    scale = Math.max(0.1, scale);
    scale = Math.min(scale, 4);
    draw(_dx, _dy, scale);
};

在代码中,我们首先阻止了鼠标滚轮的默认行为,然后根据鼠标滚轮的滚动方向和滚动速度来计算缩放的变化量delta。我们将变化量累加到缩放比例scale上,并限制缩放比例在0.1到4之间。最后,我们调用draw函数来重新绘制Canvas的内容,并传递缩放比例作为参数。

draw函数中,我们首先清除Canvas上的内容,然后进行绘制操作。

javascript 复制代码
function draw(dx, dy, scale) {
    // 清除Canvas上的内容
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // 保存当前绘图状态
    ctx.save();

    // 移动Canvas的绘制内容
    ctx.translate(x + dx, y + dy);

    // 缩放Canvas的绘制内容
    ctx.scale(scale, scale);

    // 绘制图片
    ctx.drawImage(img, -img.width / 2, -img.height / 2, img.width, img.height);

    // 进行其他绘制操作,如绘制矩形边框、文字等

    // 恢复绘图状态
    ctx.restore();
}

在绘制之前,我们首先保存了当前的绘图状态,包括平移、缩放等变换。然后,我们使用ctx.translate()方法移动Canvas的绘制内容,以实现Canvas的拖拽效果。接着,我们使用ctx.scale()方法缩放Canvas的绘制内容,根据传入的缩放比例。最后,我们绘制图片、矩形边框、文字等其他内容。

通过以上代码,我们实现了在Canvas中通过鼠标缩放和移动画布的功能。用户可以通过鼠标滚轮来缩放画布的内容,通过鼠标拖拽来移动画布的内容。同时,我们在draw函数中可以进行其他绘制操作,如绘制图片、矩形边框和文字等。

眼球太红,就用疲惫两个字遮挡一下吧。

移动的时候 图片会变成随机的偏红色,那是我添加的一个警告,警告生命是自己的,不要被别人的所束缚,不要被别人所影响,不要被别人所左右,不要被别人所控制,不要被别人所伤害,不要被别人所限制,不要被别人所压迫。

实现方式如下:

js 复制代码
if (Math.random() > 0.5) {
    // 获取图片的像素数据
    const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    const idata = imageData.data;
    // 通过遍历data数组,修改rgba的值,实现红移效果 
    let k = Math.random();
    for (let i = 0; i < idata.length; i += 4) {
        idata[i] = idata[i] * 1.5 * k;
        idata[i + 1] = idata[i + 1] * 0.7 * k;
        idata[i + 2] = idata[i + 2] * 0.7 * k;
    }
    ctx.putImageData(imageData, 0, 0);
}

夜已深:快一点了,睡吧。最近一年每天睡眠时间很少很少。2023年最后一更。

相关推荐
一起养小猫几秒前
Flutter for OpenHarmony 实战:打造功能完整的记账助手应用
android·前端·flutter·游戏·harmonyos
hbstream海之滨视频网络技术3 分钟前
Google正式上线Gemini In Chrome,国内环境怎样开启。
前端·chrome
Lisson 34 分钟前
VF01修改实际开票数量增强
java·服务器·前端·abap
红色的小鳄鱼13 分钟前
Vue 教程 自定义指令 + 生命周期全解析
开发语言·前端·javascript·vue.js·前端框架·html
coloma201215 分钟前
COCOS代码动态增加刚体和碰撞体的方法
前端·uv
想逃离铁厂的老铁19 分钟前
Day60 >> 94、城市间货物运输1️⃣ + 95、城市间货物运输 2️⃣ + 96、城市间货物运输 3️⃣
java·服务器·前端
GISer_Jing1 小时前
WebGL跨端兼容实战:移动端适配全攻略
前端·aigc·webgl
迦南giser1 小时前
前端性能——传输优化
前端
小白_ysf1 小时前
Vue 中常见的加密方法(对称、非对称、杂凑算法)
前端·vue.js·算法
人工智能训练8 小时前
【极速部署】Ubuntu24.04+CUDA13.0 玩转 VLLM 0.15.0:预编译 Wheel 包 GPU 版安装全攻略
运维·前端·人工智能·python·ai编程·cuda·vllm