详解使用双缓存解决Canvas clearRect引起的闪屏问题


Posted in HTML / CSS onApril 29, 2019

前言

今天用 canvas 做 H5 的时候遇到了闪屏问题。闪烁效果如下图:

详解使用双缓存解决Canvas clearRect引起的闪屏问题 

问题简介

功能简介

H5 该部分的功能为:通过点击二级菜单,切换图片的遮罩或者更换背景。

因为功能简单,所以用了原生 canvas 实现这个功能。但在使用 clearRect 清除画布的时候会出现闪烁的情况。

代码实现(问题代码)

以下代码即为出现闪屏的关键代码,省略了图片的定义与 onload:

// 点击二级菜单后,触发该函数更新画布
updateCanvas(){
    const canvas = document.getElementById('canvas'); // 获取画布
    const ctx = canvas.getContext('2d');
    ctx.clearRect(0,0,1448,750); // 清空画布
    // 开始重绘
    ctx.drawImage(bg,0,0); // 背景
    ... // 省略其他绘制过程
}

问题分析

经过简单分析,得出闪屏的原因是 clearRect 清除画布后,绘制的时间较长导致出现闪屏的现象。

什么是双缓存

来看一下microsoft 网站中双缓冲图形 这篇文章对双缓存的解释:

对图形进行编程时出现闪烁是一个常见问题。 需要多个复杂画图操作的图形操作可导致呈现的图像出现闪烁或具有不可接受的外观。 为解决这些问题,.NET Framework 提供了双缓冲功能。

双缓冲使用内容缓冲来解决与多个画图操作相关的闪烁问题。 启用双缓冲后,所有画图操作会首先呈现到内存缓冲而不是屏幕上的绘图图面。 所有画图操作完成后,内存缓冲会直接复制到与之关联的绘图图面。 由于屏幕上仅执行一个图形操作,因此与复杂画图操作相关的图像闪烁可得以消除。

使用双缓存解决问题

以上引用,简单来说,主要问题就是绘制时间较长导致了闪屏,解决方法就是新建一个 canvas 作为 缓存 canvas ,通过 缓存 canvas 完成绘制过程,绘制完成后,直接将 缓存 canvas 复制到原来的 canvas,这样就可以解决绘制时间过长导致的闪屏问题。

代码实现

以下代码即为关键代码,省略了图片的定义与 onload:

updateCanvas(){
    const canvas = document.getElementById('canvas'); // 获取页面中的 canvas
    const ctx = canvas.getContext('2d');
    
    const tempCanvas = document.createElement('canvas'); // 新建一个 canvas 作为缓存 canvas
    const tempCtx = tempCanvas.getContext('2d');
    tempCanvas.width = 1448; tempCanvas.height = 750; // 设置宽高

    // 开始绘制
    tempCtx.drawImage(bg,0,0); // 背景
    ... // 省略其他绘制过程
    
    // 缓存 canvas 绘制完成
    
    ctx.clearRect(0,0,1448,750); // 清空旧 canvas
    ctx.drawImage(tempCanvas,0,0); // 将缓存 canvas 复制到旧的 canvas
}

效果验收

可以很明显的看到闪屏问题解决了!

详解使用双缓存解决Canvas clearRect引起的闪屏问题 

总结

重绘画布的时候,我们需要使用 clearRect 来清空画布,此时的画布是空的,开始重绘后,如果内容较多,时间也就相应的增加,因此视觉出现了空档期,我们就看到了闪屏的情况;

解决闪屏,其实就是怎么解决绘制时间较长的问题;

这里参考了图形图象处理编程中 双缓存 的概念,将绘制过程交给了 缓存 canvas ,这样页面中的 canvas 就省去了绘制过程,而 缓存 canvas 并没有添加到页面,所以我们就看不到绘制过程,也就解决了闪屏的问题。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

HTML / CSS 相关文章推荐
推荐一些比较有用的css3新属性
Nov 11 HTML / CSS
CSS3的column-fill属性对齐列内容高度的用法详解
Jul 01 HTML / CSS
CSS3 仿微信聊天小气泡实例代码
Apr 05 HTML / CSS
css3旋转木马_动力节点Java学院整理
Jul 12 HTML / CSS
详解Sticky Footer 绝对底部的两种套路
Nov 03 HTML / CSS
CSS3之transition实现下划线的示例代码
May 30 HTML / CSS
详解CSS3中的box-sizing(content-box与border-box)
Apr 19 HTML / CSS
HTML5 用动画的表现形式装载图像
Mar 08 HTML / CSS
canvas三角函数模拟水波效果的示例代码
Jul 03 HTML / CSS
HTML5之HTML元素扩展(上)—新增加的元素及使用概述
Jan 31 HTML / CSS
详解CSS中的特指度和层叠问题
Jul 15 HTML / CSS
POST提交数据常见的四种方式
Jan 18 HTML / CSS
浅谈HTML5新增和废弃的标签
Apr 28 #HTML / CSS
Canvas实现贝赛尔曲线轨迹动画的示例代码
Apr 25 #HTML / CSS
可能这些是你想要的H5软键盘兼容方案(小结)
Apr 23 #HTML / CSS
详解三种方式实现平滑滚动页面到顶部的功能
Apr 23 #HTML / CSS
小程序canvas中文字设置居中锚点
Apr 16 #HTML / CSS
用canvas做一个DVD待机动画的实现代码
Apr 12 #HTML / CSS
Html5适配iphoneX刘海屏的简单实现
Apr 09 #HTML / CSS
You might like
php实现微信模拟登陆、获取用户列表及群发消息功能示例
2017/06/28 PHP
javascript函数中的arguments参数
2010/08/01 Javascript
javascript 另一种图片滚动切换效果思路
2012/04/20 Javascript
探讨JavaScript语句的执行过程
2016/01/28 Javascript
源码分析Vue.js的监听实现教程
2017/04/23 Javascript
删除table表格行的实例讲解
2017/09/21 Javascript
Vue三种常用传值示例(父传子、子传父、非父子)
2018/07/24 Javascript
详解Vue CLI3配置解析之css.extract
2018/09/14 Javascript
vue实现多个元素或多个组件之间动画效果
2018/09/25 Javascript
node学习笔记之读写文件与开启第一个web服务器操作示例
2019/05/29 Javascript
JS实现水平遍历和嵌套递归操作示例
2019/08/15 Javascript
vue实现五子棋游戏
2020/05/28 Javascript
教你如何在Django 1.6中正确使用 Signal
2014/06/22 Python
Python扫描IP段查看指定端口是否开放的方法
2015/06/09 Python
windows上安装Anaconda和python的教程详解
2017/03/28 Python
详解python中executemany和序列的使用方法
2017/08/12 Python
Python内建函数之raw_input()与input()代码解析
2017/10/26 Python
python3.6 实现AES加密的示例(pyCryptodome)
2018/01/10 Python
对python numpy.array插入一行或一列的方法详解
2019/01/29 Python
pygame实现俄罗斯方块游戏(AI篇2)
2019/10/29 Python
使用Tkinter制作信息提示框
2020/02/18 Python
Python自定义sorted排序实现方法详解
2020/09/18 Python
Python中Selenium模块的使用详解
2020/10/09 Python
pycharm 如何取消连按两下shift出现的全局搜索
2021/01/15 Python
Python环境搭建过程从安装到Hello World
2021/02/05 Python
文明礼仪演讲稿
2014/05/12 职场文书
销售顾问工作计划书
2014/08/15 职场文书
党员评议个人总结
2014/10/20 职场文书
Python中使用Lambda函数的5种用法
2021/04/01 Python
mysql多表查询-笔记七
2021/04/05 MySQL
MongoDB balancer的使用详解
2021/04/30 MongoDB
windows下快速安装nginx并配置开机自启动的方法
2021/05/11 Servers
Python实现socket库网络通信套接字
2021/06/04 Python
关于@OnetoMany关系映射的排序问题,使用注解@OrderBy
2021/12/06 Java/Android
【海涛解说】pis亲自推荐,其实你从来不会玩NW
2022/04/01 DOTA
win10频率超出范围怎么办?win10老显示超出工作频率范围的解决方法
2022/07/07 数码科技