Tips——canvas闪屏问题的处理
一、问题描述
在画canvas时,遇到屏幕瞬间空白的情况(大约1~2帧),造成用户体验不好。
二、原因
canvas的绘图过程是:先擦出整个画布;然后浏览器到达重绘时间点后,在空白的canvas上作画;xx毫秒后,这一帧动画上的所有元件完成绘画。
那么,当采用setTimeout或setInterval等与浏览器重绘频率不同步的计时器对画布进行绘图时,很可能上一帧的元件内容还没被完全画出来时,不精准的计时器已经驱动着擦除画布开始下一帧绘画;以及这一帧绘画已经结束,但不精准的计时器还没到指定刷新时间,所以此时会出现明显空白,也即“闪屏”。
三、解决
双缓冲理论:闪烁是图形编程的一个常见问题。需要多重复杂绘制操作的图形操作会导致呈现的图像闪烁或具有其他不可接受的外观。双缓冲的使用解决这些问题。双缓冲使用内存缓冲区来解决由多重绘制操作造成的闪烁问题。当启用双缓冲时,所有绘制操作首先呈现到内存缓冲区,而不是屏幕上的绘图图面。所有绘制操作完成后,内存缓冲区直接复制到与其关联的绘图图面。因为在屏幕上只执行一个图形操作,所以消除了由复杂绘制操作造成的图像闪烁。
即,先创建一个cacheCanvas执行计算绘制的操作,当下一帧刷新时,直接将cacheCanvas的内容drawImage到真正的canvas上,这么做既能有效规避闪屏,又能减缓卡顿情况。
示例代码:
var testBox = function(){
var canvas = document.getElementById("cas"),
ctx = canvas.getContext('2d'),
borderWidth = 2,
Balls = [];
var ball = function(x , y , vx , vy , useCache){
this.x = x;
this.y = y;
this.vx = vx;
this.vy = vy;
this.r = getZ(getRandom(20,40));
this.color = [];
this.cacheCanvas = document.createElement("canvas");
this.cacheCtx = this.cacheCanvas.getContext("2d");
this.cacheCanvas.width = 2*this.r;
this.cacheCanvas.height = 2*this.r;
var num = getZ(this.r/borderWidth);
for(var j=0;j<num;j++){
this.color.push("rgba("+getZ(getRandom(0,255))+","+getZ(getRandom(0,255))+","+getZ(getRandom(0,255))+",1)");
}
this.useCache = useCache;
if(useCache){
this.cache();
}
}
function getZ(num){
var rounded;
rounded = (0.5 + num) | 0;
// A double bitwise not.
rounded = ~~ (0.5 + num);
// Finally, a left bitwise shift.
rounded = (0.5 + num) << 0;
return rounded;
}
ball.prototype = {
paint:function(ctx){
if(!this.useCache){
ctx.save();
var j=0;
ctx.lineWidth = borderWidth;
for(var i=1;i<this.r;i+=borderWidth){
ctx.beginPath();
ctx.strokeStyle = this.color[j];
ctx.arc(this.x , this.y , i , 0 , 2*Math.PI);
ctx.stroke();
j++;
}
ctx.restore();
} else{
ctx.drawImage(this.cacheCanvas , this.x-this.r , this.y-this.r);
}
},
cache:function(){
this.cacheCtx.save();
var j=0;
this.cacheCtx.lineWidth = borderWidth;
for(var i=1;i<this.r;i+=borderWidth){
this.cacheCtx.beginPath();
this.cacheCtx.strokeStyle = this.color[j];
this.cacheCtx.arc(this.r , this.r , i , 0 , 2*Math.PI);
this.cacheCtx.stroke();
j++;
}
this.cacheCtx.restore();
},
move:function(){
this.x += this.vx;
this.y += this.vy;
if(this.x>(canvas.width-this.r)||this.x<this.r){
this.x=this.x<this.r?this.r:(canvas.width-this.r);
this.vx = -this.vx;
}
if(this.y>(canvas.height-this.r)||this.y<this.r){
this.y=this.y<this.r?this.r:(canvas.height-this.r);
this.vy = -this.vy;
}
this.paint(ctx);
}
}
var Game = {
init:function(){
for(var i=0;i<1000;i++){
var b = new ball(getRandom(0,canvas.width) , getRandom(0,canvas.height) , getRandom(-10 , 10) , getRandom(-10 , 10) , true)
Balls.push(b);
}
},
update:function(){
ctx.clearRect(0,0,canvas.width,canvas.height);
for(var i=0;i<Balls.length;i++){
Balls[i].move();
}
},
loop:function(){
var _this = this;
this.update();
RAF(function(){
_this.loop();
})
},
start:function(){
this.init();
this.loop();
}
}
window.RAF = (function(){
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) {window.setTimeout(callback, 1000 / 60); };
})();
return Game;
}();
function getRandom(a , b){
return Math.random()*(b-a)+a;
}
window.onload = function(){
testBox.start();
}
Tips——canvas闪屏问题的处理的更多相关文章
- ios transition translate 闪屏问题总结
webkit在绘制页面时会将结构分为各种层,当层足够大时就会变成很大的平铺层.这样一来webkit在每次页面结构发生变化时不需要都渲染整个页面而是渲染对应层了,这对渲染速度来说相当的重要.webkit ...
- iostransitiontranslate闪屏问题总结
webkit在绘制页面时会将结构分为各种层,当层足够大时就会变成很大的平铺层.这样一来webkit在每次页面结构发生变化时不需要都渲染整个页面而是渲染对应层了,这对渲染速度来说相当的重要.webkit ...
- vue cavnas绘制矩形,并解决由clearRec带来的闪屏问题
起因:在cavnas绘制矩形时 鼠标移动一直在监测中,所以鼠标移动的轨迹会留下一个个的矩形框, 要想清除矩形框官方给出了ctx.clearRect() 但是这样是把整个画布给清空了,因此需要不断 向画 ...
- 在DevExpress程序中使用SplashScreenManager控件实现启动闪屏和等待信息窗口
在我很早的WInform随笔<WinForm界面开发之"SplashScreen控件">有介绍如何使用闪屏的处理操作,不过那种是普通WInform和DevExpress ...
- html5 canvas首屏自适应背景动画循环效果代码
模板描述:html5 canvas首屏自适应背景动画循环效果代码 由于动态图太大,怕以后服务器受不了,所以现在都改为静态图了,大家点击演示地址一样的,希望大家喜欢,你们的支持就是小海的动力!! 欢迎大 ...
- IOS客户端UIwebview下web页面闪屏问题
基于ios客户端uiwebview下的web页面,在其内容高度大于视窗高度时,如果点击超过视窗下文档的底部按钮,收缩内容高度,会发生闪屏问题. 外因是由文档的高度大于视窗的高度所致,本质原因未知. 解 ...
- 设置 phoneGap/Cordova 3.4 应用程序启动动画闪屏 SplashScreen
当Cordova 程序打包并安装到手机中后,我们会发现启动程序时,会有数秒的黑屏现象,常见的解决方法则是设置闪屏后面. 这里以 Android 程序为例,介绍Cordova设置启动画面的方法. 1. ...
- android 的闪屏效果
android的闪屏效果,就是我们刚开始启动应用的时候弹出的界面或者动画,过2秒之后自动的跳转到主界面. 其实,实现这个效果很简单,使用Handler对象的postDelayed方法就可以实现.在这个 ...
- Android如何避免切换至SurfaceView时闪屏(黑屏闪一下)以及黑屏移动问题
1.最近的项目中,有一个Activity用到Fragment+ViewPager,其中一个fragment中实现了视频播放的功能,包含有SurfaceView.结果,每次打开程序第一次进入到该Acti ...
随机推荐
- Vue.js系列之三模板语法
Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据.所有 Vue.js 的模板都是合法的 HTML ,所以能被遵循规范的浏览器和 HTML 解 ...
- 部分替换mysql表中某列的字段
UPDATE `table_name` SET `field_name` = replace (`field_name`,'from_str','to_str') WHERE `field_name` ...
- Pl/SQl 安装和配置Oracle 数据库连接
在进行企业开发时,数据库(oracle)一般在我们本地安装的:另外,oracle数据库比较大,在本地安装,会拖慢电脑的速度.我们可以通过oracle客户端,远程连接数据库.下面介绍自己的安装方式 1. ...
- Flow类注释解读
参考: (1)https://docs.oracle.com/javase/specs/jls/se7/html/jls-16.html (2)https://docs.oracle.com/java ...
- Elasticsearch入门(一)
索引(index) -- 存储关联数据的地方.实际上,索引只是一个逻辑命名空间(logical namespace),它指向一个或多个分片(shards). 分片(shard) 是 工作单元(work ...
- 酷派大神F2使用QPST进行nv备份恢复,解决无信号问题
测试机器: 大神F2联通版 8675_W00 系统COOLUI55 写贴原因: 自己无意间刷错了包,结果手机无信号,进入工程模式怎么设置都没有用.尝试过系统还原(备份过).刷新的ROM.线刷, ...
- svn 服务器搭建 ,采用http的方式加密用户。
1.1安装svn 1.环境 centos6.5 本地ip:192.168.2.154 2.安装 yum install subversion 查看版本 svnserve --version 3.创建版 ...
- solr 7.6 安装部署与遇到的问题
目录 安装 solr 配置solr 到tomcat(关键) 配置依赖包 创建tomcat solr 的 classes 文件 创建 solr 的core 的主目录(也就是存放core的位置) 修改配置 ...
- 使用httpClient处理get请求或post请求
另外一个版本: http://www.cnblogs.com/wenbronk/p/6671928.html 在java代码中调用http请求, 并将返回的参数进行处理 get请求: public s ...
- Linux-(ps,grep)
grep命令 1.命令格式: grep [option] pattern file 2.命令功能: 用于过滤/搜索的特定字符.可使用正则表达式能多种命令配合使用,使用上十分灵活. Linux系统中gr ...