6

APNG在线制作、兼容、播放和暂停

 2 years ago
source link: https://www.zhangxinxu.com/wordpress/2021/09/apng-maker-pause-play-ie/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

APNG在线制作、兼容、播放和暂停

这篇文章发布于 2021年09月12日,星期日,17:12,归类于 Design相关。 阅读 760 次, 今日 45 次 没有评论

by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=10100 鑫空间-鑫生活
本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。

APNG占位图

CSS动画 + background-position 定位也能实现PNG图片序列帧的动画播放效果,但是,这种技术实现不太适合变成一次性的解决方案,也就是,如果设计师下次提供另外尺寸和大小的图片序列,之前的代码就不能复用了。

此时,APNG动图会是更好的选择,大小、播放时机等都是可以自如控制,图像资源本身的速率、尺寸交给设计师控制,使得一套代码应付所有的动图场景成为了可能。

关于APNG图片的基本知识可以参考多年前我写的这篇文章“APNG历史、特性简介”,这里再介绍一些在实际开发中可能需要用到的知识与实现。

一、APNG在线制作

日常开发,APNG多是偶然使用使用,下载个软件再去进行APNG制作,就显得比较麻烦了。

因此,我上周花了2个晚上时间做了个免费在线合成APNG动图的在线工具,导入图片序列就可以在线生成,支持设置每一帧的时间间隔和播放次数。

你可以狠狠地点击这里:APNG免费在线合成下载工具

支持拖拽改变图片系列顺序,使用截图画面如下所示:

apng制作工具截图示意

注意,由于目前常规的图像预览软件没有增加对APNG的支持,因此,打开后并不会动,显示的是APNG图片的第一帧,此时需要拖到浏览器中进行预览,Chrome或者Firefox浏览器都是可以的。

二、IE兼容APNG

APNG IE浏览器是不支持的,具体见下面的兼容性表:

APNG兼容性

如果浏览器不支持APNG,会以普通的PNG图片显示,因此,并不会影响功能的实现。

但是,如果遇到挑剔的产品经理,或者遇到挑剔的设计师,非要让你让IE/Edge浏览器也是动画播放,则可以试试 apng-canvas 这个项目:https://github.com/davidmz/apng-canvas

使用非常简单,假设页面中有个 <img> 元素:

<img id="chip" src="./chip.png">

是需要引入对应的 JS 文件,然后执行执行下面的代码就可以让其在IE浏览器下播放:

<script src="./apng-canvas.min.js"></script>
<script>
APNG.ifNeeded().then(function() {
    APNG.animateImage(chip);
});
</script>

眼见为实,您可以狠狠地点击这里:APNG动图在IE浏览器播放demo

在IE11下的效果截图就是这样的:

IE11下的效果截图

如果浏览器本身支持APNG,则上面的代码并不会执行,因为 APNG.ifNeeded() 方法判断了是否需要使用 canvas 播放APNG。

但是,有时候,就算浏览器支持 APNG,我们也希望使用 canvas 播放,例如 Safari 浏览器下,如果APNG 制作的时候设置了播放 1 次,可能会播放 2 次,此时,要想在所有浏览器下保持一致,也需要使用canvas模拟播放效果。

此时,直接使用下面的代码即可:

APNG.animateImage(chip);

对了,apng-canvas是IE10以上浏览器才支持,IE9并不支持。

三、APNG的播放与暂停

使用 APNG 模拟某些动效的时候,可能需要手动设置暂停与播放,这个也是可以实现的,使用apng-js这个项目:https://github.com/davidmz/apng-js

和 apng-canvas 是同一个作者。

demo演示

此项目在 ReadMe 中的示例不太友好,对于新人而言,可能不知道说的什么意思,可能这个原因,所以 Star 数不是很高吧。

我研究了下,apng-js 也是支持直接在 Web 页面中直连使用的,然后我就做了个demo,您可以狠狠地点击这里:APNG动图播放与暂停控制demo

点击按钮可以播放与暂停 APNG,还可以控制播放的速率。

APNG 暂停示意

如何使用?

播放与暂停功能的实现要比兼容IE麻烦些。

下面代码是官方的示意:

import parseAPNG from 'apng-js';

const apng = parseAPNG(buffer);

这里例子演示的是在工程开发环境中的使用,如果直接在浏览器中使用,则需要这么处理:

  1. 引入对应的 JS 文件,例如:
    <script src="./apng-js/index.js"></script>

    此JS项目资源中没有,需要执行npm install apng-js找到此文件。

  2. 执行下面的代码,此时 apng 就是关键执行对象。
    var parseAPNG = window["apng-js"].default;
    const apng = parseAPNG(buffer);

apng其实是个类,包括下面这些属性和方法:

class APNG {
    width: number 
    height: number 
    numPlays: number  // 循环次数,0表示无限循环
    playTime: number  // 一次执行的总毫秒数
    frames: Frame[]   // 每帧的数据

    // 方法
    createImages(): Promise // 为所有帧创建图像元素
    getPlayer(context: CanvasRenderingContext2D, autoPlay: boolean = false): Promise.<Player>
        // 创建播放器
}

在控制播放与暂停这个需求上,我们需要的是 getPlayer() 方法。

我们创建一个 canvas 元素,其上下文作为参数传递给 getPlayer() 方法,此时就获得了一个播放控制器,调用控制器上的play()pause()方法,就可以控制APNG的播放与暂停了,例如,我做的这个demo页面的实现就是这样的:

var parseAPNG = window["apng-js"].default;
// 播放器
var player = null;
// 播放速率
var playbackRate = 1;
// 获取图片资源
fetch(chip.src).then(function(response) {
    response.arrayBuffer().then(function(buffer) {
        var apng = parseAPNG(buffer);
        // img 替换成 canvas
        var canvas = document.createElement('canvas');
        canvas.width = apng.width;
        canvas.height = apng.height;
        chip.after(canvas);
        chip.remove();
        // 执行播放
        apng.getPlayer(canvas.getContext('2d')).then(function (p) {
            player = p;
            player.playbackRate = playbackRate;
            // 开始播放
            player.play();
        });
    });
});

其中的 player 就可以控制播放与暂停,暴露的属性和方法如下所示。

class Player {
    context: CanvasRenderingContext2D
    playbackRate: number = 1.0 
           
    currFrameNumber: number
    currFrame: Frame
    paused: boolean  
    ended: boolean

    // 方法
    play()
    pause()
    stop()
    
    renderNextFrame()
}

因此,暂停动画只需要设置 player.pause(),设置播放速率使用 player.playbackRate,更完整的代码大家可以访问demo页面

apng-js还有很多其他的能力,包括执行事件的回调,例如,我们可以设置 APNG 只播放一次,apng-js只有能力知道什么时候动画播放结束的,此时,我们就可以做其他一些事情。

每一帧的播放同样有对应的事件接口,可以让我们对每一帧进行处理。

本文就不展开了,大家有兴趣,可以自行研究一番。

四、结束碎碎念

上一篇文章到现在接近20天,快要破了我无更新日期记录了,在干嘛呢,忙着写小说。

小说截图

每天更新一章,4月份写到现在,已经快50万字了。

说实话,已经影响一些更重要的事情了,例如新书的宣传啊,文章的更新啊,网站的建设啊,但是,要是不做,心里难受,所以,继续坚持吧。

小说进度大约60%的样子,所以,完结大概还需要4个月,明年春节结束,没有签约,版权还在自己手上。

希望明年再回过头看,会是一段不错的路程。

扯远了,感谢大家的阅读,如果您觉得内容还不错,欢迎分享到朋友圈,或者转发到微博。

2764.svg

(本篇完)1f44d.svg 是不是学到了很多?可以分享到微信
1f44a.svg 有话要说?点击这里

本文为原创文章,欢迎分享,勿全文转载,如果实在喜欢,可收藏,永不过期,且会及时更新知识点及修正错误,阅读体验也更好。
本文地址:https://www.zhangxinxu.com/wordpress/?p=10100


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK