工件出现在 iOS 上动态生成的动画画布图像上

Posted

技术标签:

【中文标题】工件出现在 iOS 上动态生成的动画画布图像上【英文标题】:Artifacts appear on dynamically generated & animated canvas image on iOS 【发布时间】:2016-09-02 05:52:37 【问题描述】:

我正在为微信(iosandroid 类似)制作一个 html5 网络应用程序,使用纯 javascript(没有 jQuery 或任何其他第三方库)。我正在根据用户选择的图像元素在屏幕上生成具有艺术外观的动画。 JS 每一帧都在画布中绘制,效果出奇的好(iPhone 5 上的 fps 在 50 到 60 之间,Nexus 4 卡在 60fps)。

元素是使用 Canvas2D 转换绘制的。不幸的是,由于一些知识产权问题,我无法在此处发布确切的代码,所以我提供了一个有点剥离的版本:

画布初始化:

app.init = function()

    this.canvas = document.createElement("canvas");
    this.ctx = this.canvas.getContext("2d");
    this.ctx.canvas.width = 800;
    this.ctx.canvas.height = 800;

用于绘图的图像元素:

app.onResourcesLoaded = function()

    this.elements = new Array();
    this.elements.push( this.getImageByID("blue") );
    this.elements.push( this.getImageByID("green") );
    this.elements.push( this.getImageByID("red") );
    this.elements.push( this.getImageByID("yellow") );
    this.elemnum = this.elements.length;

app.getImageByID = function(id)

    // looks up into loaded images, find the one with provided id
    // and returns image object, or null if none found.
    // If found, returned value is object of following structure:
    var foundImage = 
        image: imageObject, 
        position:  x:0.0, y:0.0 ,
        rotation: 0.0,
        scale: 1.0,
        center:  x:0.5*imageObject.width, y:0.5*imageObject.height 
    ;
    return foundImage;

画布绘图:

// This function is executed using requestAnimationFrame or setInterval (if requestAnimationFrame is not available)
app.drawImage = function()

    var elapsedTime = this.calcElapsedTime(); // returns time between this and previous frame
    this.animateElementsTransformation( elapsedTime ); // goes through each of elements and updated position, rotation and scale data.

    // draws first background image as base
    this.ctx.drawImage( backgroundImage, 0, 0);
    for( var i = 0; i<this.elemnum; i++)
    
        var e = this.elements[i];
        this.ctx.save();
        
            this.ctx.translate( e.position.x, e.position.y );
            this.ctx.rotate( e.angle );
            this.ctx.scale( e.scale, e.scale );
            this.ctx.drawImage( e.image, -e.center.x, -e.center.y );
        
        this.ctx.restore();
    

在 Android 和 iOS 上都运行良好,性能出色。但是,在 iOS、微信或独立 Safari 中,偶尔(例如,几秒钟后)我可以看到一些黑色直线,大约 1 像素宽,出现在整个屏幕上(比如从一个边缘到另一个边缘)。我已经检查过了,这些线与元素的位置/方向/比例无关。它们总是出现在同一个位置,就好像整个画布实际上是由一些三角形组成的,浏览器无法刷新它们。它们不是很明显,并且在几秒钟内只出现一次。

有没有人遇到过这种情况?它是 Safari 中的错误,也许是 GPU 驱动程序错误?还是我做错了什么?

【问题讨论】:

为什么有人会拒绝这个问题而不至少留下解释为什么以及我应该做些什么来改进它?我真的很愿意改变问题的形式,或者在需要时添加更多细节...... 【参考方案1】:

我已经弄明白了:

我有“滚动”背景,它是通过两次绘制一张图像制成的,由绘制图像的宽度偏移。由于我使用翻译,并且翻译增量不是整数而是浮点数,由于图像过滤,有时,在两个绘制图像之间的连接边缘会看到背景 - 仅在 iOS Safari 上,而在 Android Chrome 上没有这个问题。

我已经通过转换为四舍五入的值来解决它。万一有人遇到同样的麻烦:-)

【讨论】:

以上是关于工件出现在 iOS 上动态生成的动画画布图像上的主要内容,如果未能解决你的问题,请参考以下文章

如何在动态创建的画布上使用 Paper.js?

在 iOS 中动态更改启动图像

动态壁纸水波纹效果

动态图像处理

UnityEngine.Videoplayer 不在 IOS 设备上渲染视频

动态图处理