tips——canvas闪屏问题的处理(代码片段)

bbcfive bbcfive     2023-03-14     610

关键词:

一、问题描述

在画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();

 

小程序--------------处理canvas导出图片模糊问题-------------劉(代码片段)

一、业务需求:    使用canvas在前端生成海报,并在海报上添加上水印。最后导出图片并保存到本地。二、业务逻辑实现:  (1)创建canvas画布======》(2)在canvas上绘制海报========》(3)绘制水印===========》(4)绘制完... 查看详情

高清屏下canvas重置尺寸引发的问题(代码片段)

...“canvas.width=canvas.width”惹的祸。普通屏幕下面下不会有问题,但是如果屏幕是高清屏,就会出现问题。这是因为,高清屏下,我们为了处理绘制图形模糊的问题,通常会做如下处理:functionsetupCanvas(canvas)letwidth=canvas.width,height=can... 查看详情

常见的canvas优化——模糊问题旋转效果(代码片段)

canvas常见优化方案——模糊问题、旋转效果、离屏、自定义图片尺寸实践demo——“canvas离屏、旋转效果实践——旋转的雪花”2017-12-1816:27:35更新关于模糊问题前几天研究html2Canvas的时候刚好赶上作者发布新版本,发现新版本截屏... 查看详情

canvas应用——将方形图片处理为圆形(代码片段)

上段时间在项目中需要将方形图片处理为圆形图片,你可能会说直接用css设置border-radius:50%就可以了,但是项目中还要将此图片的圆形图片作为一部分利用canvas将其绘制到一张背景图上面,所以就有了为何要用canvas来处理了。代... 查看详情

iphone闪屏多任务处理

】iphone闪屏多任务处理【英文标题】:iphonesplashscreenmulti-tasking【发布时间】:2011-02-2210:53:33【问题描述】:我使用下面的代码向iPhone添加了一个褪色的闪屏UIImageView*splashView;......splashView=[[UIImageViewalloc]initWithFrame:CGRectMake(0,20,320,46... 查看详情

命令执行tips(代码片段)

...绍:命令执行漏洞概念:当应用需要调用一些外部程序去处理内容的情况下,就会用到一些执行系统命令的函数。如PHP中的system,exec,shell_exec等,当用户可以控制命令执行函数中的参数时,将可注入恶意系统命令到正常命令中... 查看详情

canvas.todataurl()报错(代码片段)

...RL‘on‘HTMLCanvasElement‘:Taintedcanvasesmaynotbeexported.  这个问题因为是基于file://进行调试的,而chrome做了安全相关的处理,主要是HTML5安全的CORS(跨域资源共享 查看详情

java解决游戏界面闪屏(代码片段)

...如,有时我们用普通的方法去绘制图形,会产生闪屏的现象,导致我们所做的游戏或者是别的项目效果非常差,这完全不是我们想要的结果。那么,有没有一种技术,实现不闪屏的效果,特别是在多线... 查看详情

缓存应用tips(代码片段)

...的,所以再进行写入操作的时候需要将数据写入数据库并处理缓存中的旧数据。为了保证数据库与缓存中的数据一致,更新的逻辑则较为 查看详情

vue打包问题:tip:builtfilesaremeanttobeservedoveranhttpserver.(代码片段)

npmrunbuild之后,出现提示:Tip:builtfilesaremeanttobeservedoveranHTTPserver.Openingindex.htmloverfile://won‘twork.npmrunbuild的时候 ,因为vue-cli的默认配置中,publishPath是用绝对目录,所以dist文件夹里的文件必须放在服务器的根目录,如果你想本地打... 查看详情

java的webview闪屏(代码片段)

查看详情

html5canvas内部元素添加事件处理(代码片段)

前言canvas没有提供为其内部元素添加事件监听的方法,因此如果要使canvas内的元素能够响应事件,需要自己动手实现。实现方法也很简单,首先获得鼠标在canvas上的坐标,计算当前坐标在哪些元素内部,然后... 查看详情

h5利用canvas实现海报功能(代码片段)

...思路虽然简单,但是在实现的过程中会遇到各种各样的小问题,现在就将遇到的问题进行一次总结。1、iphone以及部分android机型通过摄像头拍摄的照片被旋转了90度原因:由于目前的手机拍照基本都在2M以上 查看详情

wpfの命中测试(代码片段)

...该元素做出相应的控制?命中测试,可以很好地解决这个问题本文目的: 使用命中测试,选取Canvas中相应Element。正文: 可 查看详情

前端图像处理指南(代码片段)

计算机图像处理是一门很成熟的技术,任何一门可操作系统接口的语言都能很轻易的实现各种处理操作。但是前端限于浏览器环境和接口限制,处理起来会有诸多不便,这里所说的前端图像处理,是真的指不借助任何后端服务纯... 查看详情

html5画布canvas文本填充线段属性裁剪透明度与像素合并方式(代码片段)

tip:有问题或者需要大厂内推的+我脉脉哦:丛培森٩(‘ω’)وCSS3中的很多都可以类比与我们canvas的一些属性canvas中“画笔”环境对象的很多属性都可以类比CSS3中的属性我们不仅仅可以绘制图形,还可以向画布中添... 查看详情

webview在recyclerview中开启硬件加速闪屏问题解决(代码片段)

...eader加在Recyclerview中,开启硬件加速后,锤子手机闪屏严重,其他手机有闪屏,不算严重。但是关闭硬件加速网页会很卡,一直对于硬件加速闪屏问题不知怎么解决,尝试直接关闭Webview的硬件加速,但... 查看详情

canvas图片圆角问题(代码片段)

引子近期的工作中,是继canvas设置边框问题之后碰到的第4个问题。OriginMyGitHub图片圆角问题如果只是想要显示圆角的效果,设置border-radius就可以了,但如果要让canvas合成的图片显示为圆角,这种css方式不行。这是示例,扫描访... 查看详情