Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] AVCanvas 支持自定义 UI 组件 #325

Open
hughfenghen opened this issue Nov 18, 2024 · 5 comments
Open

[RFC] AVCanvas 支持自定义 UI 组件 #325

hughfenghen opened this issue Nov 18, 2024 · 5 comments

Comments

@hughfenghen
Copy link
Member

hughfenghen commented Nov 18, 2024

时间:2024-11-16

背景/动机

@webav/av-cliper 提供了基础的视频处理能力,不需要 UI(如:自动化视频处理)或 UI 非常简单的产品可以直接基于 av-cliper 构建。

在需要用户介入视频编辑创作的众多场景中,如视频剪辑、直播推流、视频相册、视频模板等;

@webav/av-canvas 提供了画布与精灵(Sprite)等 API,且内置了最基础的 UI(移动、缩放、旋转),开发者可基于 av-canvas 快速构建相关产品。

@webav/av-canvas 内置的 UI 终究无法满足多样化的诉求;

av-canvas 定位是一个与 UI 框架无关的库,无法选择某个成熟框架在项目内部构建复杂 UI。

所以需要设计新的 API,允许开发者使用任意技术栈构建丰富或定制化 UI。

开放的 API 能满足:

  1. 与 UI 框架无关;开发者可以选择任意 UI 框架,如 React、Vue、Svelte 等
  2. 能实现已知场景的常见 UI 组件和功能,如
    • 右键菜单:锁定、删除、Sprite 层级调整
    • 裁剪素材,只保留素材的特定区域
  3. 能自定义内置 UI 组件的样式
    • 自定义 Sprite 的选中效果
    • 自定义 Sprite 的控制点
  4. 能复用社区中的 AVCanvas 自定义 UI 组件

相关 issue:#78, #224

详细设计

创建 AVCanvas 时可以传入 UI Plugin,插件行为将覆盖 AVCanvas 的默认实现。

目前仅支持覆盖选中 Sprite 的边框 和 缩放、旋转控制点的绘制效果。

image

new AVCanvas(attchEl, {
  uiPlugins: [customPlugin]
});

// customPlugin 的类型
type Plugin = (ctx: PluginContext) => {
  // AVCanvas 销毁时调用
 destroy: () => void
 // 自定义激活 sprite 的边框、控制点的样式
 acviteSpriteBoxRender: () => void
}

interface PluginContext {
  // 获取当前选中的 Sprite
  getActiveSprtie: () => VisibleSprite | null
  // 监听 Sprite 选中事件
  on: (evtType: 'ActiveSprite', (spr: VisibleSprite | null) => void) => void
  // 获取控制点的位置
  getCtrlsPosition: () => {}
}

示例:自定义边框、控制点的样式

const CustomSpriteBox = (ctx) => {
  return {
    acviteSpriteBoxRender(){
      // todo:初始化绘制 box 所需要的 dom 或 canvas
      // 监听 Sprite 选中或取消选中事件
      ctx.on('ActiveSprite', (spr) => {
        if (spr == null) return
        // todo:根据 spr 的状态(普通选中、锁定、裁剪)绘制特定效果
        // todo:将绘制的边框与 Sprite.rect 坐标
        // todo:将绘制的控制点与 ctx.getCtrlsPosition 进行同步
      })
    }
    destroy() {
      // todo:回收创建的 DOM 节点等
    }
  }
}

new AVCanvas(attchEl, {
  uiPlugins: [CustomSpriteBox]
});

这是内置的边框绘制源代码

可能存在问题

  1. 存在未考虑的场景, 以上设计的 API 难以实现。
  2. 插件开发成本;如果只需要修改一下边框颜色、控制点大小等小调整,相对来说成本较高
  3. 拖拽移动、缩放 Sprite 的逻辑目前无法自定义,如果以当前的 API 范式开放,实现自定义缩放、移动的难度较大

可替代的方案

  1. 直接通过 AVCanvas 暴露 PluginContext 的 API,不限制上层的实现方式;
    可能导致自定义混乱,无法复用
  2. 针对场景,开放更细粒度的 API,如选中 Sprite 的边框、控制点样式;
    降低了自定义成本,但牺牲了 API 通用性

未来的可能性

如果社区有诉求与足够的理由,可以考虑逐渐放开限制,允许覆盖 AVCanvas 内置的所有 UI,包括:

  1. 自定义选中 Sprite 逻辑
  2. 自定义缩放、移动 Sprite 的逻辑(但如上文描述有一定的实现成本
  3. 自定义光标(鼠标)的样式
  4. 自定义参考线及样式
@hughfenghen
Copy link
Member Author

有自定义 UI 诉求的同学,可以看看是否满足自己的场景,参与讨论。

@caohongz
Copy link

目前使用情况看,有一定的自定义需求,主要集中在自定义光标,控制点样式调整,未来可能会涉及到旋转中辅助线的展示。
缩放、移动的逻辑还是可以的,有些麻烦的就是没有缩放比例,需要在程序逻辑中存储原始宽高来计算缩放比例数值。
#78 中提到的问题我是通过修改VisibleSprite,添加一些裁切点属性,在canvas绘制时直接进行裁剪展示,我更希望通过这种方式实现裁剪,当然需要配合一个裁剪组件界面,在rect中通过控制点进行裁剪会跟原有功能产出冲突,造成用户体验混乱。

@hughfenghen
Copy link
Member Author

没有缩放比例

@caohongz 这句什么意思?

独立画布实现裁剪组件这个想法我是赞同的

  1. 保持独立互不干扰
  2. 技术实现会简单许多,不用考虑 Sprite 的旋转状态

@wendraw

@caohongz
Copy link

caohongz commented Nov 20, 2024

没有缩放比例

@caohongz 这句什么意思?

独立画布实现裁剪组件这个想法我是赞同的

  1. 保持独立互不干扰
  2. 技术实现会简单许多,不用考虑 Sprite 的旋转状态

@wendraw

有一种需求是需要按照缩放比例调整视频尺寸而不是通过拖拽,所以就需要保存一个比例参数,但应该不是av-canvas解决的问题,还是需要用户自己解决。

@caohongz
Copy link

有一个疑问,目前rect只能在av-canvas的容器内移动,容器外不展示也不可点选,这个有什么办法修改吗?目前移动是有一定安全边界的,但是会造成过小的素材无法移动到边缘位置,我觉得rect不可以完全移出容器是合理的做法。

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

No branches or pull requests

2 participants