百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT知识 > 正文

canvas基础及图片缩放的实现 canvas缩放后拖动

liuian 2024-12-18 15:37 63 浏览

基础部分

坐标系

画布坐标、屏幕坐标的概念

    • 屏幕坐标,绝对坐标,类似于css中的绝对定位
    • 画布坐标,类似于css中的相对定位,还要考虑缩放

几何变换:平移、缩放、旋转

    • 平移,位置移动,形状、相对位置不变
    • 缩放,位置(相对屏幕坐标)和大小都发生变化
    • 旋转,位置旋转,形状、相对位置不变

Canvas 中的所有几何变换针对的不是绘制的图形,而是针对画布本身,也就是说,当移动、缩放、旋转画布之后,新的坐标系只对新的操作生效

参考:

  • Canvas 几何变换 - Canvas 基础教程 - 简单教程,简单编程
    • Canvas 平移 translate() - Canvas 基础教程 - 简单教程,简单编程
    • Canvas 缩放 scale() - Canvas 基础教程 - 简单教程,简单编程
    • Canvas 旋转 rotate() - Canvas 基础教程 - 简单教程,简单编程

绘图步骤

基础绘图三步法

  1. 获取canvas对象
  2. 获取上下文环境对象context
  3. 开始绘制图形。

示例代码

const canvas = document.getElementById("canvas");
const context = convas.getContext("2d");
context.fillRect(100, 100, 50, 50);

通用绘图步骤

  1. 保存画布(状态),context.save();
  2. 画布操作,context.transform(叠加) 或者 context.setTransform(不叠加)
  3. 设置样式,绘制图形
  4. 恢复画布(状态),context.restore();

图形变换基本操作

  1. 清空画布,context.clearRect
  2. 保存状态,context.save
  3. 画布操作,doTransform
  4. getShapeList and forEach
  5. 恢复状态,context.restore


Canvas性能

Canvas的绘制和html的绘制是不一样的,html的绘制是增量的,当变化时,只会重新绘制变化的部分,没有变化的部分是不会重新绘制的,但是canvas不一样,每次都是全量绘制的,如果一个canvas里有很多图形,当改变一个图形时,需要重新绘制所有图形才可以(当然,可以用clearRect擦除部分区域,但一般很少这么用)。

了解canvas的绘制规则之后,就很容易发现性能问题,如果canvas上绘制了大量的图形(成千上万个),每次重绘就需要很长的时间,如果重绘的频率很高,那么就会有性能问题



那么如何解决这个问题呢,目前有以下几种方案

  1. 使用图层
  2. 使用临时图层
  3. 使用webworker或wasm
  4. 使用webgl

使用图层

图层的概念来自于PS,每一个图层都是一个canvas,既然在一个canvas上绘制太多图形会有性能问题,那么就分几个图层,每次仅重新绘制其中一个图层,每个图层的图形都不会很多,那么即使重绘的频率很高,也不会有性能问题。图层的概念图如下:

代码实现

用一个父元素作为容器,把所有的元素设置成一样的宽高并放在里面重叠。

<div class="container">
    <canvas width="500" height="500"></canvas>
    <canvas width="500" height="500"></canvas>
    <canvas width="500" height="500"></canvas>
    <canvas width="500" height="500"></canvas>
    <canvas width="500" height="500"></canvas>
</div>


使用临时图层

绘制是很耗性能的,如果每次都清空画布然后重新画一次,那么性能会消耗很大(即使分了几个图层),我们应区分“变”与“不变”的部分,只对“变”的部分重新渲染,“不变”的部分不渲染,将经常变化的部分抽离到临时图层,这样仅需要渲染临时图层,临时图层有几种实现思路,一种是使用操作图层(俗称高性能图层),一种是使用隐藏图层(不绘制到界面上的)


高性能图层

一般高频(实时响应鼠标、键盘等事件)的操作会放在高性能图层,等操作完成之后,再将最终结果保存到其它图层,比如绘制、拖拽、缩放一个(或一批)shape

隐藏图层

有些图层是不用给用户看的,这些canvas仅存在于内存中,不会插入html的dom中,用完就销毁,比如常见的canvas to image。

还有一种实现方式是离屏渲染(OffscreenCanvas),先在一个offCanvas操作,然后再将结果渲染到界面上(有点像虚拟dom操作),一般会结合webworker或webassembly


const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
// 绘制图片,或其它操作
context.drawImage();
// 转成base64图片
convas.toDataUrl();

使用webworker或wasm

影响canvas性能的除了绘制频率,还有一个重要的是像素点操作,一般图像处理会涉及到大量的像素点操作,如果放在主线程计算,那么会卡住其它操作,造成页面卡顿,特别影响用户体验,这些涉及大量计算的一般会单独开个线程来操作,而在浏览器中有这个能力的就只有webworker了。


有了webworker可能还不够,因为始终是在js上执行,js执行效率天生就比其它语言慢,所以一般的会使用webassembly,执行效率比js快很多,而且还能用到更丰富的图像处理库

使用webgl

如果还有更高的性能要求,那么普通的2d canvas可能就无法满足了,这个时候可以使用webgl,性能更高(当然学习成本也更高),再结合wasm,就可以有无限想象力了,鼎鼎大名的figma就是用webgl + wasm(rust)实现的,另外google doc在线文档也使用了webgl,飞书文档将来也会替换成wegbl,基于浏览器的渲染始终有诸多限制,一般有能力的都会实现自己的渲染引擎。

业务中图片缩放的实现设计

假设canvas大小为(867,350)

图片的大小为(768,576)

将上面这张图片放到canvas中,图片贴边处理,也即图片太大就缩小,图片太小就放大。那么我们如何实现这种效果呢?


总结一下,总共分为几步:

  1. 计算画布大小和图片大小
  2. 计算如果将图片以原图大小放入画布中心,左上角的坐标
  3. 将画布坐标移动到图片中心点
  4. 将画布放大或缩小(scale=Math.min(画布宽度/图片宽度,画布高度/图片高度))
  5. 重新移动画布坐标到左上角
  6. 绘制图片(或图形)

canvas的执行细节如下:

相关推荐

360无法卸载怎么办(360卸载不了最简单三个步骤)

开启了自我保护,关闭即可。解决方法如下:准备材料:360安全卫士、电脑1、在电脑上打开安全卫士,进去之后,点击右上方的列表图标,选择设置,2、进去安全卫士设置界面之后,点击安全防护中心,3、进去安全防...

戴尔笔记本电脑没有声音怎么解决

右击“我的电脑”----“属性”---“硬件”----“设备管理器”,打开“声音、视频和游戏控制器”有无问题,即看前面有没有出现黄色的小图标,如有,重新安装这个设备的驱动程序进行解决。加强麦克风:右...

如何给无线路由器设置密码(如何给无线路由器设置密码教程)

1、使用路由器的管理界面,找到密码设置选项,输入想要设置的新密码。   2、再次输入新密码,以便确认输入的密码正确无误。   3、保...

windows7旗舰版激活序列号(win7旗舰 激活码)

一、Windows7旗舰版激活密钥零售版:Windows7UltimateRetail永久序列号【尝试联网激活,如果不能激活,可电话激活】[Key]:RHTBY-VWY6D-QJRJ9-JGQ...

联想电脑如何重置系统(联想电脑 重置系统)

联想进入bios界面重置系统方法:1、将电脑关机,按下一键恢复按钮(需确保笔记本屏盖在打开状态),不同的联想笔记本机型按钮位置不同,操作也不一样1)如果是此按钮,按住5秒钟等待出现还原界面2)针孔式按...

电脑加密文件夹怎么弄(电脑加密文件夹怎么弄出来)

要在电脑中加密文件夹,可以使用加密软件或操作系统提供的加密功能。使用加密软件,你可以选择文件夹并设置密码来保护其内容。这样,只有输入正确密码的人才能访问文件夹中的文件。另外,某些操作系统也提供了加密文...

win11打游戏现在稳定吗(win11玩游戏流畅吗)

win11适合打游戏的。主要原因如下:1、win11的升级并不会丢失原本系统中的文件和软件,因此用户可以在升级后直接玩原本的游戏。2、win11虽然是一款新系统,但是在游戏性能的表现上已经有着非常好的...

无法连接到共享打印机(无法连接到共享打印机是啥情况)

这个有多种原因,主要是要启动来宾guest帐户,装好驱动,设置同一工作组,在同一局域网条件下,重新添加打印机就可以了。1、依次展开“计算机管理(本地)—系统工具—本地用户和组—用户”,找到G...

注册qq号免费立即申请不用手机号

1、先在网页上搜索安装谷歌浏览器2、安装完成后,不要在电脑上登录任何一个QQ,打开QQ登录的界面,点击注册账号。3、在注册账号的页面,填上相应要求的信息,手机号码的部分先不要填。4、点击谷歌浏览器右上...

office2016破解版安装教程(office2016下载破解版)

microsoftoffice2016激活与破解的区别是版本不同。①尽量使用官方的原版程序、原版软件,避免使用来路不明的"XX"版。②若程序对非正版授权用户有功能或使用期限制,但仍能满...

tenda登录密码(tenda登录入口密码)

腾达路由器登录的密码和用户名为ADMIN。老版的兴化的都使用的是这一个用户名和密码新出的版本,登录的地址和用户名密码都在路由器背面,标签上的是随机产生的,没有规律,只需查看按照地址输入用户名和密码,就...

android系统更新(android系统更新opengl版本)

1.1、打开手机页面,点击进入oppo的官网;2、进入页面后,点击下载系统包的按钮,系统自动升级。2.1、持手机卡去oppo手机专卖店;2、刷卡在专卖店里直接升级。3.1、打开电脑,开机进入页面;2、...

tplink路由器登录名和密码(tp link无线路由器用户名和密码)

1、tp-link无线路由器,上网账号就是宽带账号,口令就是宽带密码,设置方法如下:一、接线方法,外网进线接入路由器wan口,路由器lan口接线到电脑网线接口。二、路由器设置,打开浏览器http://...

win10硬盘格式mbr还是guid(won10硬盘格式)

作为人类的我回答你的问题。在选择WIN10分区类型时,我建议使用GUID分区表(GPT)。原因如下:1.GPT支持更大容量的硬盘,可以处理大型数据存储需求,而MBR分区表限制了最大可用空间为2TB。...

台式电脑网线怎么插(台式电脑网线插在猫上还是路由器上)
台式电脑网线怎么插(台式电脑网线插在猫上还是路由器上)

1、如果你家里没有用路由器,那么电脑主机上的网线,需要插在猫的网口/LAN口。温馨提示:没有用路由器的情况下,电脑要上网的话,你需要打开电脑中的“宽带连接”程序,然后填写你家的宽带账号、宽带密码,就能连接上网了。如果你不知道如何用“宽带连...

2025-11-08 03:05 liuian