Skip to content

Conversation

@ahzvenol
Copy link
Contributor

@ahzvenol ahzvenol commented Nov 1, 2025

通过添加GifResource实现了PIXI对.gif格式文件的支持

@gemini-code-assist
Copy link

Summary of Changes

Hello @ahzvenol, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

此拉取请求旨在扩展PIXI.js在webgal项目中的功能,使其能够直接加载和渲染GIF动画。通过引入一个专门的GifResource类,该变更实现了GIF文件的解析、帧管理和动画播放逻辑,从而提升了应用程序处理动态图像的能力。

Highlights

  • 新增GIF支持: 通过引入GifResource类,为PIXI.js渲染引擎添加了对.gif格式文件的原生支持。
  • GIF解析与播放: 利用gifuct-js库解析GIF文件,并实现了帧的预计算、动画播放控制(包括自动播放、循环、动画速度调整)以及资源清理。
  • PIXI集成: 将GifResource注册到PIXI的资源加载器中,使其能够自动识别和处理GIF文件。
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

这个 PR 通过 GifResource 为 PIXI 添加了对 .gif 格式文件的支持,实现相当完整,涵盖了 GIF 的加载、播放、停止和循环。代码整体结构清晰,但在一些细节上还有提升空间。例如,代码中残留了一些用于调试的 console.log 语句。为了增强代码的健壮性,建议使用显式 null 检查来代替非空断言。当前的实现会预先解码并缓存所有 GIF 帧,对于较大的 GIF 文件可能导致高内存占用。最后,为了更好的可维护性,建议使用 PIXI 公共的 extensions.add() API 来注册自定义资源,而不是直接操作其内部数组。

Comment on lines 83 to 85
const ctx = canvas.getContext('2d')!;
const patchCanvas = document.createElement('canvas');
const patchCtx = patchCanvas.getContext('2d')!;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

此处(第83和85行)使用了非空断言 ! 来获取 CanvasRenderingContext2D。虽然对于新创建的 canvas 元素,getContext('2d') 通常不会返回 null,但为了代码的健壮性,建议进行显式的 null 检查并抛出错误,以防在某些意外情况下(如浏览器不支持2D上下文)导致运行时错误。

Comment on lines +94 to +112
for (const frame of gifFrames) {
const { dims, delay = defaultDelay, disposalType = 2, patch } = frame;
const { width, height, left, top } = dims;

patchCanvas.width = width;
patchCanvas.height = height;
const patchData = new ImageData(new Uint8ClampedArray(patch), width, height);
patchCtx.putImageData(patchData, 0, 0);

ctx.drawImage(patchCanvas, left, top);
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);

this._frames.push({ start: time, end: (time += delay), imageData });

if (disposalType === 2) ctx.clearRect(0, 0, canvas.width, canvas.height);
else if (disposalType === 3 && prevFrame) ctx.putImageData(prevFrame, 0, 0);

prevFrame = imageData;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

当前的实现方式会将GIF的每一帧都解码为 ImageData 并存储在内存中。对于大型或长时长的GIF文件,这可能会导致非常高的内存占用。例如,一个800x600的30帧GIF可能会占用接近60MB的内存。建议考虑一种更节省内存的策略,比如只在需要渲染某一帧时才动态地生成该帧的 ImageData。这虽然会增加一些CPU开销,但可以显著降低内存峰值。

const frame = findFrame(this._frames, this._currentTime);

if (frame) {
this.source.getContext('2d')!.putImageData(frame.imageData, 0, 0);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

此处也使用了非空断言 !。建议进行显式的 null 检查,以确保在获取 2d 上下文失败时能够优雅地处理错误。

import { v4 as uuid } from 'uuid';
import { cloneDeep, isEqual } from 'lodash';
import * as PIXI from 'pixi.js';
import { INSTALLED } from 'pixi.js';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

为了使用 PIXI 的公共扩展 API,建议将此处的 INSTALLED 导入更改为 extensions。这将与 extensions.add(GifResource) 一起使用,以更稳健的方式注册自定义资源。

Suggested change
import { INSTALLED } from 'pixi.js';
import { extensions } from 'pixi.js';

// @ts-ignore
window.PIXI = PIXI;

INSTALLED.push(GifResource);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

此处直接操作了 PIXI 的内部 INSTALLED 数组来注册 GifResource。这依赖于 PIXI 的内部实现,可能在未来版本中失效。推荐使用 PIXI v6+ 的公共扩展 API extensions.add() 来注册资源。这需要对 GifResource.ts 做一些小的修改,以使其符合扩展的格式,从而提高代码的健壮性和可维护性。

建议在 GifResource.ts 中添加:

import { ExtensionType } from 'pixi.js';
// ...
public static readonly extension = {
  type: ExtensionType.Resource,
  priority: 2, // or other appropriate priority
};
Suggested change
INSTALLED.push(GifResource);
extensions.add(GifResource);

@HardyNLee
Copy link
Contributor

有一个小小的问题,WebGAL现在的资源加载方式,不太方便直接拿到资源并对其进行配置,如这里的animationSpeedloop等,这对于以后用 changeFigure 设置参数有所阻碍。
如果可能的话,是否可以将 GifResource 改造成 PIXI.Container 的形式。

Co-authored-by: HardyNLee <hardy--lee@outlook.com>
@ahzvenol
Copy link
Contributor Author

ahzvenol commented Nov 6, 2025

@HardyNLee 通过继承Sprite固定使用Gif资源,然后属性代理内部resource属性来实现?WebGAL这边状态管理有些复杂,也不知道具体怎么做合适,这个Pr我就不继续扩展下去了

Copy link
Contributor

@HardyNLee HardyNLee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

引入了 gifuct-js ,实现 GifResource 使 PIXI 支持 gif 格式。

  • 没有非兼容更改
  • 对已有代码改动较小,以增为主
  • 与 PIXI.Loader 工作得很好,立绘和背景都能用

有关但不紧要的点

  • 有调整 gif 选项的接口,但没有实现通过 webgal script 设置
    • 现在也是能用 gif 的,调整选项也许可以放到另外的 PR 实现
  • 由于资源是会被 WebGAL 复用的,因此可能有调整一个 gif,却影响了所有使用这个资源的场景对象的表现
    • 或许播放选项与更新逻辑应该从 gif 资源中抽离出来

综上所述,此 PR 很好的完成了 Pixi 对 gif 的支持,尽管暂时没有办法让用户调整播放选项,但功能上现在是可用的。

@MakinoharaShoko MakinoharaShoko merged commit a2109ba into OpenWebGAL:dev Nov 9, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants