{"version":3,"file":"av-canvas.umd.cjs","sources":["../src/types.ts","../src/utils.ts","../src/sprites/sprite-manager.ts","../src/sprites/render-ctrl.ts","../src/sprites/sprite-op.ts","../src/av-canvas.ts"],"sourcesContent":["import { Rect } from '@webav/av-cliper';\n\n/**\n * 二维坐标系中的点\n */\nexport interface IPoint {\n  x: number;\n  y: number;\n}\n\n/**\n * 分辨率（尺寸）\n */\nexport interface IResolution {\n  width: number;\n  height: number;\n}\n\n/**\n * 画布分辨率与实际宽高的比例\n */\nexport interface ICvsRatio {\n  w: number;\n  h: number;\n}\n\n/**\n * 控制点：上、下、左、右，左上、左下、右上、右下、旋转\n * 当 Rect 只允许等比例缩放时（{@link Rect.fixedAspectRatio} = true），缺少 t、b、l、r 四个控制点\n */\nexport type RectCtrls = Partial<Record<'t' | 'b' | 'l' | 'r', Rect>> &\n  Record<'lt' | 'lb' | 'rt' | 'rb' | 'rotate', Rect>;\n\nexport const CTRL_KEYS = [\n  't',\n  'b',\n  'l',\n  'r',\n  'lt',\n  'lb',\n  'rt',\n  'rb',\n  'rotate',\n] as const;\n\nexport type TCtrlKey = (typeof CTRL_KEYS)[number];\n","import { Rect } from '@webav/av-cliper';\nimport { ICvsRatio, RectCtrls } from './types';\n\nexport function createEl(tagName: string): HTMLElement {\n  return document.createElement(tagName);\n}\n\nconst rectGetterCache = new WeakMap<\n  HTMLCanvasElement,\n  (rect: Rect) => RectCtrls\n>();\n/**\n * 根据 canvas 创建该画布上的 Sprite 控制点生成器\n * 因为控制点的大小需要根据画布的大小动态调整\n */\nexport function getRectCtrls(cvsEl: HTMLCanvasElement, rect: Rect) {\n  if (rectGetterCache.has(cvsEl)) {\n    return rectGetterCache.get(cvsEl)!(rect);\n  }\n\n  let ctrlSize = 10;\n  const cvsResizeOb = new ResizeObserver((entries) => {\n    const fisrtEntry = entries[0];\n    if (fisrtEntry == null) return;\n    ctrlSize = 10 / (fisrtEntry.contentRect.width / cvsEl.width);\n  });\n  cvsResizeOb.observe(cvsEl);\n  function rectCtrlsGetter(rect: Rect): RectCtrls {\n    const { w, h } = rect;\n    // 控制点元素大小, 以 分辨率 为基准\n    const sz = ctrlSize;\n    // half size\n    const hfSz = sz / 2;\n    const hfW = w / 2;\n    const hfH = h / 2;\n    // rotate size\n    const rtSz = sz * 1.5;\n    const hfRtSz = rtSz / 2;\n    // ctrl 坐标是相对于 sprite 中心点\n    const tblr = rect.fixedAspectRatio\n      ? {}\n      : {\n          t: new Rect(-hfSz, -hfH - hfSz, sz, sz, rect),\n          b: new Rect(-hfSz, hfH - hfSz, sz, sz, rect),\n          l: new Rect(-hfW - hfSz, -hfSz, sz, sz, rect),\n          r: new Rect(hfW - hfSz, -hfSz, sz, sz, rect),\n        };\n    return {\n      ...tblr,\n      lt: new Rect(-hfW - hfSz, -hfH - hfSz, sz, sz, rect),\n      lb: new Rect(-hfW - hfSz, hfH - hfSz, sz, sz, rect),\n      rt: new Rect(hfW - hfSz, -hfH - hfSz, sz, sz, rect),\n      rb: new Rect(hfW - hfSz, hfH - hfSz, sz, sz, rect),\n      rotate: new Rect(-hfRtSz, -hfH - sz * 2 - hfRtSz, rtSz, rtSz, rect),\n    };\n  }\n  rectGetterCache.set(cvsEl, rectCtrlsGetter);\n  return rectCtrlsGetter(rect);\n}\n\n// 复用 canvas 比例的获取，避免重复 observer\nconst cvsRatioCache = new WeakMap<HTMLCanvasElement, ICvsRatio>();\nexport function getCvsRatio(cvsEl: HTMLCanvasElement): ICvsRatio {\n  if (cvsRatioCache.has(cvsEl)) {\n    return cvsRatioCache.get(cvsEl)!;\n  }\n\n  const cvsRatio = {\n    w: cvsEl.clientWidth / cvsEl.width,\n    h: cvsEl.clientHeight / cvsEl.height,\n  };\n  const observer = new ResizeObserver(() => {\n    cvsRatio.w = cvsEl.clientWidth / cvsEl.width;\n    cvsRatio.h = cvsEl.clientHeight / cvsEl.height;\n  });\n  observer.observe(cvsEl);\n  cvsRatioCache.set(cvsEl, cvsRatio);\n  return cvsRatio;\n}\n","import { VisibleSprite } from '@webav/av-cliper';\nimport { EventTool } from '@webav/internal-utils';\n\nexport enum ESpriteManagerEvt {\n  ActiveSpriteChange = 'activeSpriteChange',\n  AddSprite = 'addSprite',\n}\n\nexport class SpriteManager {\n  #sprites: VisibleSprite[] = [];\n\n  #activeSprite: VisibleSprite | null = null;\n\n  #evtTool = new EventTool<{\n    [ESpriteManagerEvt.AddSprite]: (s: VisibleSprite) => void;\n    [ESpriteManagerEvt.ActiveSpriteChange]: (s: VisibleSprite | null) => void;\n  }>();\n\n  on = this.#evtTool.on;\n\n  get activeSprite(): VisibleSprite | null {\n    return this.#activeSprite;\n  }\n  set activeSprite(s: VisibleSprite | null) {\n    if (s === this.#activeSprite || s?.interactable === 'disabled') return;\n    this.#activeSprite = s;\n    this.#evtTool.emit(ESpriteManagerEvt.ActiveSpriteChange, s);\n  }\n\n  activeSpriteByCoord(x: number, y: number): void {\n    this.activeSprite =\n      this.getSprites()\n        // 排在后面的层级更高\n        .reverse()\n        .find(\n          (s) =>\n            s.visible && s.interactable !== 'disabled' && s.rect.checkHit(x, y),\n        ) ?? null;\n  }\n\n  async addSprite(vs: VisibleSprite): Promise<void> {\n    await vs.ready;\n    this.#sprites.push(vs);\n    this.#sprites = this.#sprites.sort((a, b) => a.zIndex - b.zIndex);\n    vs.on('propsChange', (props) => {\n      if (props.zIndex == null) return;\n      this.#sprites = this.#sprites.sort((a, b) => a.zIndex - b.zIndex);\n    });\n\n    this.#evtTool.emit(ESpriteManagerEvt.AddSprite, vs);\n  }\n\n  removeSprite(spr: VisibleSprite): void {\n    if (this.#activeSprite === spr) this.activeSprite = null;\n    this.#sprites = this.#sprites.filter((s) => s !== spr);\n    spr.destroy();\n  }\n\n  getSprites(filter: { time: boolean } = { time: true }): VisibleSprite[] {\n    return this.#sprites.filter(\n      (s) =>\n        s.visible &&\n        (filter.time\n          ? this.#renderTime >= s.time.offset &&\n            this.#renderTime <= s.time.offset + s.time.duration\n          : true),\n    );\n  }\n\n  #renderTime = 0;\n  updateRenderTime(time: number) {\n    this.#renderTime = time;\n\n    // 避免素材不可见，但渲染了素材边框控制点\n    const as = this.activeSprite;\n    if (\n      as != null &&\n      (time < as.time.offset || time > as.time.offset + as.time.duration)\n    ) {\n      this.activeSprite = null;\n    }\n  }\n\n  destroy(): void {\n    this.#evtTool.destroy();\n    this.#sprites.forEach((s) => s.destroy());\n    this.#sprites = [];\n  }\n}\n","import { VisibleSprite } from '@webav/av-cliper';\nimport { CTRL_KEYS, TCtrlKey } from '../types';\nimport { createEl, getCvsRatio, getRectCtrls } from '../utils';\nimport { ESpriteManagerEvt, SpriteManager } from './sprite-manager';\n\nconst CloseSvg = `\n<svg t=\"1756779136804\" class=\"icon\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" p-id=\"1456\" width=\"16\" height=\"16\">\n<path d=\"M1022.793875 170.063604L852.730271 0 511.396938 341.333333 170.063604 0 0 170.063604l341.333333 341.333334L0 852.730271l170.063604 170.063604 341.333334-340.127208 341.333333 340.127208 170.063604-170.063604-340.127208-341.333333 340.127208-341.333334z\" fill=\"#bfbfbf\" p-id=\"1457\"></path>\n</svg>\n`;\n\nexport function renderCtrls(\n  container: HTMLElement,\n  cvsEl: HTMLCanvasElement,\n  sprMng: SpriteManager,\n): () => void {\n  const cvsRatio = getCvsRatio(cvsEl);\n  const observer = new ResizeObserver(() => {\n    if (sprMng.activeSprite == null) return;\n    syncCtrlElPos(sprMng.activeSprite, cvsEl, rectEl, ctrlsEl);\n  });\n  observer.observe(cvsEl);\n\n  let lastActSprEvtClear = () => {};\n  const { rectEl, ctrlsEl } = createRectAndCtrlEl(container);\n\n  // 添加点击事件处理\n  rectEl.addEventListener('pointerdown', (evt) => {\n    // 如果点击的是控制点，不处理点击穿透\n    if (Object.values(ctrlsEl).includes(evt.target as HTMLElement)) {\n      return;\n    }\n\n    // 获取相对于 canvas 的坐标，可能需要激活更上层的 sprite\n    const cvsRect = cvsEl.getBoundingClientRect();\n    const x = (evt.clientX - cvsRect.left) / cvsRatio.w;\n    const y = (evt.clientY - cvsRect.top) / cvsRatio.h;\n    sprMng.activeSpriteByCoord(x, y);\n  });\n\n  const offSprChange = sprMng.on(ESpriteManagerEvt.ActiveSpriteChange, (s) => {\n    // 每次变更，需要清理上一个事件监听器\n    lastActSprEvtClear();\n    if (s == null) {\n      rectEl.style.display = 'none';\n      return;\n    }\n    syncCtrlElPos(s, cvsEl, rectEl, ctrlsEl);\n    lastActSprEvtClear = s.on('propsChange', () => {\n      syncCtrlElPos(s, cvsEl, rectEl, ctrlsEl);\n    });\n  });\n\n  return () => {\n    observer.disconnect();\n    offSprChange();\n    rectEl.remove();\n    lastActSprEvtClear();\n  };\n}\n\nfunction createRectAndCtrlEl(container: HTMLElement): {\n  rectEl: HTMLElement;\n  ctrlsEl: Record<TCtrlKey, HTMLElement>;\n} {\n  const rectEl = createEl('div');\n  rectEl.classList.add('sprite-rect');\n  rectEl.style.cssText = `\n    position: absolute;\n    z-index: 3;\n    pointer-events: auto;\n    border: 1px solid #eee;\n    box-sizing: border-box;\n    display: none;\n    cursor: move;\n  `;\n  const ctrlsEl = Object.fromEntries(\n    CTRL_KEYS.map((k) => {\n      const d = createEl('div');\n      d.classList.add(`ctrl-key-${k}`);\n      d.style.cssText = `\n        display: none;\n        position: absolute;\n        border: 1px solid #3ee;\n        border-radius: 50%;\n        box-sizing: border-box;\n        background-color: #fff;\n        pointer-events: auto;\n        cursor: ${k === 'rotate' ? 'crosshair' : 'default'};\n        user-select: none;\n      `;\n      return [k, d];\n    }),\n  ) as Record<TCtrlKey, HTMLElement>;\n\n  Object.values(ctrlsEl).forEach((d) => rectEl.appendChild(d));\n  container.appendChild(rectEl);\n  return {\n    rectEl,\n    ctrlsEl,\n  };\n}\n\nfunction syncCtrlElPos(\n  s: VisibleSprite,\n  cvsEl: HTMLCanvasElement,\n  rectEl: HTMLElement,\n  ctrlsEl: Record<TCtrlKey, HTMLElement>,\n): void {\n  if (s.interactable === 'disabled') {\n    rectEl.style.display = 'none';\n    return;\n  }\n  rectEl.style.display = '';\n\n  const cvsRatio = getCvsRatio(cvsEl);\n  const { x, y, w, h, angle } = s.rect;\n\n  Object.assign(rectEl.style, {\n    left: `${x * cvsRatio.w}px`,\n    top: `${y * cvsRatio.h}px`,\n    width: `${w * cvsRatio.w}px`,\n    height: `${h * cvsRatio.h}px`,\n    transform: `rotate(${angle}rad)`,\n  });\n\n  const ctrlPosMap = getRectCtrls(cvsEl, s.rect);\n\n  for (const k in ctrlsEl) {\n    const key = k as TCtrlKey;\n    const el = ctrlsEl[key];\n    const pos = ctrlPosMap[key];\n\n    if (pos == null) {\n      el.style.display = 'none';\n      continue;\n    }\n\n    const baseStyle: Record<string, string> = {\n      width: `${pos.w * cvsRatio.w}px`,\n      height: `${pos.h * cvsRatio.h}px`,\n      transform: `translate(${pos.x * cvsRatio.w}px, ${pos.y * cvsRatio.h}px)`,\n      left: '50%',\n      top: '50%',\n    };\n\n    let customStyle: Record<string, string> = { display: 'none' };\n    el.innerHTML = '';\n\n    switch (s.interactable) {\n      case 'interactive':\n        customStyle = {\n          display: 'block',\n          backgroundColor: '#fff',\n          border: '1px solid #3ee',\n        };\n        break;\n      case 'selectable':\n        if (key !== 'rotate') {\n          customStyle = {\n            display: 'flex',\n            justifyContent: 'center',\n            alignItems: 'center',\n            backgroundColor: 'transparent',\n            border: 'none',\n          };\n          el.innerHTML = CloseSvg;\n        }\n        break;\n    }\n\n    Object.assign(el.style, baseStyle, customStyle);\n  }\n}\n","import { Rect } from '@webav/av-cliper';\nimport { debounce } from '@webav/internal-utils';\nimport { CTRL_KEYS, ICvsRatio, IPoint, TCtrlKey } from '../types';\nimport { createEl, getCvsRatio } from '../utils';\nimport { ESpriteManagerEvt, SpriteManager } from './sprite-manager';\n\n/**\n * 鼠标点击，激活 sprite\n */\nexport function activeSprite(\n  cvsEl: HTMLCanvasElement,\n  sprMng: SpriteManager,\n): () => void {\n  const onCvsMouseDown = (evt: MouseEvent): void => {\n    if (evt.button !== 0) return;\n    // 如果点击的是控制元素，不处理选择逻辑\n    if ((evt.target as HTMLElement) !== cvsEl) return;\n\n    const cvsRatio = getCvsRatio(cvsEl);\n    const { offsetX, offsetY } = evt;\n    const ofx = offsetX / cvsRatio.w;\n    const ofy = offsetY / cvsRatio.h;\n\n    sprMng.activeSpriteByCoord(ofx, ofy);\n  };\n\n  cvsEl.addEventListener('pointerdown', onCvsMouseDown);\n\n  return () => {\n    cvsEl.removeEventListener('pointerdown', onCvsMouseDown);\n  };\n}\n\n/**\n * 让sprite可以被拖拽移动、缩放和旋转\n */\nexport function draggabelSprite(\n  cvsEl: HTMLCanvasElement,\n  sprMng: SpriteManager,\n  container: HTMLElement,\n): () => void {\n  let startX = 0;\n  let startY = 0;\n  let startRect: Rect | null = null;\n\n  const refline = createRefline(cvsEl, container);\n\n  // 查找控制 sprite 的 DOM 元素，在 renderCtrls 中创建并添加到 container 中\n  const rectEl = container.querySelector('.sprite-rect') as HTMLElement;\n  if (!rectEl) throw Error('sprite-rect DOM Node not found');\n\n  // 移动sprite的处理函数\n  const onRectMouseDown = (evt: MouseEvent): void => {\n    const hitSpr = sprMng.activeSprite;\n    if (\n      evt.button !== 0 ||\n      hitSpr == null ||\n      hitSpr.interactable !== 'interactive'\n    )\n      return;\n\n    const { clientX, clientY } = evt;\n\n    startRect = hitSpr.rect.clone();\n    refline.magneticEffect(hitSpr.rect.x, hitSpr.rect.y, hitSpr.rect);\n\n    startX = clientX;\n    startY = clientY;\n    window.addEventListener('pointermove', onMouseMove);\n    window.addEventListener('pointerup', clearWindowEvt);\n\n    evt.stopPropagation();\n  };\n\n  const cvsRatio = getCvsRatio(cvsEl);\n  const onMouseMove = (evt: MouseEvent): void => {\n    const hitSpr = sprMng.activeSprite;\n    if (\n      hitSpr == null ||\n      hitSpr.interactable !== 'interactive' ||\n      startRect == null\n    )\n      return;\n\n    const { clientX, clientY } = evt;\n    let expectX = startRect.x + (clientX - startX) / cvsRatio.w;\n    let expectY = startRect.y + (clientY - startY) / cvsRatio.h;\n\n    updateRectWithSafeMargin(\n      hitSpr.rect,\n      cvsEl,\n      refline.magneticEffect(expectX, expectY, hitSpr.rect),\n    );\n  };\n\n  const clearWindowEvt = (): void => {\n    refline.hide();\n    window.removeEventListener('pointermove', onMouseMove);\n    window.removeEventListener('pointerup', clearWindowEvt);\n  };\n\n  // 初始设置\n  rectEl.addEventListener('pointerdown', onRectMouseDown);\n  cvsEl.addEventListener('pointerdown', onRectMouseDown);\n  const offCtrlEvt = setupCtrlEvents(cvsEl, rectEl, sprMng);\n\n  return () => {\n    refline.destroy();\n    clearWindowEvt();\n    rectEl.removeEventListener('pointerdown', onRectMouseDown);\n    cvsEl.removeEventListener('pointerdown', onRectMouseDown);\n    offCtrlEvt();\n  };\n}\n\n// 为控制点添加事件处理\nfunction setupCtrlEvents(\n  cvsEl: HTMLCanvasElement,\n  rectEl: HTMLElement,\n  sprMng: SpriteManager,\n) {\n  // 获取所有控制点元素\n  const ctrlElements = Array.from(rectEl.children) as HTMLElement[];\n\n  const cvsRatio = getCvsRatio(cvsEl);\n  // 鼠标按下对应的节点，进行对应的操作（旋转、缩放）\n  ctrlElements.forEach((ctrlEl, index) => {\n    const ctrlKey = CTRL_KEYS[index];\n    ctrlEl.addEventListener('pointerdown', (evt: MouseEvent) => {\n      const hitSpr = sprMng.activeSprite;\n      if (\n        evt.button !== 0 ||\n        hitSpr == null ||\n        hitSpr.interactable !== 'interactive'\n      )\n        return;\n\n      const { clientX, clientY } = evt;\n\n      if (ctrlKey === 'rotate') {\n        rotateRect(\n          hitSpr.rect,\n          cntMap2Outer(hitSpr.rect.center, cvsRatio, cvsEl),\n        );\n      } else {\n        scaleRect({\n          sprRect: hitSpr.rect,\n          ctrlKey,\n          startX: clientX,\n          startY: clientY,\n          cvsRatio,\n          cvsEl,\n        });\n      }\n\n      evt.stopPropagation();\n    });\n  });\n\n  ctrlElements[CTRL_KEYS.indexOf('rotate')].style.cursor = 'crosshair';\n\n  // 根据角度，动态调整每个控制节点的鼠标样式\n  const curStyles = [\n    'ns-resize',\n    'nesw-resize',\n    'ew-resize',\n    'nwse-resize',\n    'ns-resize',\n    'nesw-resize',\n    'ew-resize',\n    'nwse-resize',\n  ];\n  const curInitIdx = {\n    t: 0,\n    rt: 1,\n    r: 2,\n    rb: 3,\n    b: 4,\n    lb: 5,\n    l: 6,\n    lt: 7,\n  };\n\n  let offPropsEvt = () => {};\n  const offActSprEvt = sprMng.on(ESpriteManagerEvt.ActiveSpriteChange, (s) => {\n    offPropsEvt();\n    if (s == null) return;\n\n    const updateCursorStyle = debounce(function () {\n      const { angle } = s.rect;\n      const oa = angle < 0 ? angle + 2 * Math.PI : angle;\n\n      ctrlElements.forEach((ctrlEl, index) => {\n        const ctrlKey = CTRL_KEYS[index];\n        if (ctrlKey === 'rotate') return;\n        // 每个控制点的初始样式（idx） + 旋转角度导致的偏移，即为新鼠标样式\n        // 每旋转45°，偏移+1，以此在curStyles中循环\n        const idx =\n          (curInitIdx[ctrlKey] +\n            Math.floor((oa + Math.PI / 8) / (Math.PI / 4))) %\n          8;\n        ctrlEl.style.cursor = curStyles[idx];\n      });\n    }, 300);\n\n    offPropsEvt = s.on('propsChange', (props) => {\n      if (props.rect?.angle == null) return;\n      updateCursorStyle();\n    });\n\n    updateCursorStyle();\n  });\n  return () => {\n    offPropsEvt();\n    offActSprEvt();\n  };\n}\n\n/**\n * 缩放 sprite\n */\nfunction scaleRect({\n  sprRect,\n  startX,\n  startY,\n  ctrlKey,\n  cvsRatio,\n  cvsEl,\n}: {\n  sprRect: Rect;\n  startX: number;\n  startY: number;\n  ctrlKey: TCtrlKey;\n  cvsRatio: ICvsRatio;\n  cvsEl: HTMLCanvasElement;\n}): void {\n  const startRect = sprRect.clone();\n\n  const onMouseMove = (evt: MouseEvent): void => {\n    const { clientX, clientY } = evt;\n    const deltaX = (clientX - startX) / cvsRatio.w;\n    const deltaY = (clientY - startY) / cvsRatio.h;\n\n    // 对角线上的点是等比例缩放，key 的长度为 2\n    const scaler = ctrlKey.length === 1 ? stretchScale : fixedRatioScale;\n    const { x, y, w, h } = startRect;\n    // rect 对角线角度\n    const diagonalAngle = Math.atan2(h, w);\n    const { incW, incH, incS, rotateAngle } = scaler({\n      deltaX,\n      deltaY,\n      angle: sprRect.angle,\n      ctrlKey,\n      diagonalAngle,\n    });\n\n    // 最小宽高缩放限定\n    const minSize = 10;\n    let newW = w;\n    let newH = h;\n    // 中心点缩放时，宽高增量是原来的两倍\n    let newIncW = startRect.fixedScaleCenter ? incW * 2 : incW;\n    let newIncH = startRect.fixedScaleCenter ? incH * 2 : incH;\n    // 最小长度缩放限定\n    let newIncS = incS;\n    // 起始对角线长度\n    const startS = Math.sqrt(h ** 2 + w ** 2);\n    // 最小对角线长度\n    const minS = Math.sqrt((minSize * (h / w)) ** 2 + minSize ** 2);\n    switch (ctrlKey) {\n      // 非等比例缩放时，变化的增量范围 由原宽高跟 minSize 的差值决定\n      // 非等比例缩放时，根据ctrlKey的不同，固定宽高中的一个，另一个根据增量计算，并考虑最小值限定\n      case 'l':\n        newW = Math.max(w + newIncW, minSize);\n        newIncS = Math.min(incS, w - minSize);\n        break;\n      case 'r':\n        newW = Math.max(w + newIncW, minSize);\n        newIncS = Math.max(incS, minSize - w);\n        break;\n      case 'b':\n        newH = Math.max(h + newIncH, minSize);\n        newIncS = Math.min(incS, h - minSize);\n        break;\n      case 't':\n        newH = Math.max(h + newIncH, minSize);\n        newIncS = Math.max(incS, minSize - h);\n        break;\n      // 等比例缩放时，变化（对角线长度）的增量范围由原对角线长度跟 minSize 对角线的差值决定\n      // 等比例缩放时，某一边达到最小值时保持宽高比例不变\n      case 'lt':\n      case 'lb':\n        newW = Math.max(w + newIncW, minSize);\n        newH = newW === minSize ? (h / w) * newW : h + newIncH;\n        newIncS = Math.min(incS, startS - minS);\n        break;\n      case 'rt':\n      case 'rb':\n        newW = Math.max(w + newIncW, minSize);\n        newH = newW === minSize ? (h / w) * newW : h + newIncH;\n        newIncS = Math.max(incS, minS - startS);\n        break;\n    }\n    let newX = x;\n    let newY = y;\n    if (startRect.fixedScaleCenter) {\n      newX = x + w / 2 - newW / 2;\n      newY = y + h / 2 - newH / 2;\n    } else {\n      const newCenterX = (newIncS / 2) * Math.cos(rotateAngle) + x + w / 2;\n      const newCenterY = (newIncS / 2) * Math.sin(rotateAngle) + y + h / 2;\n      newX = newCenterX - newW / 2;\n      newY = newCenterY - newH / 2;\n    }\n\n    updateRectWithSafeMargin(sprRect, cvsEl, {\n      x: newX,\n      y: newY,\n      w: newW,\n      h: newH,\n    });\n  };\n\n  const clearWindowEvt = (): void => {\n    window.removeEventListener('pointermove', onMouseMove);\n    window.removeEventListener('pointerup', clearWindowEvt);\n  };\n  window.addEventListener('pointermove', onMouseMove);\n  window.addEventListener('pointerup', clearWindowEvt);\n}\n\n/**\n * 拉伸缩放, 上t 下b 左l 右r\n */\nfunction stretchScale({\n  deltaX,\n  deltaY,\n  angle,\n  ctrlKey,\n}: {\n  deltaX: number;\n  deltaY: number;\n  angle: number;\n  ctrlKey: TCtrlKey;\n}): {\n  incW: number;\n  incH: number;\n  incS: number;\n  rotateAngle: number;\n} {\n  // 计算矩形增加的宽度\n  let incS = 0;\n  let incW = 0;\n  let incH = 0;\n  let rotateAngle = angle;\n  if (ctrlKey === 'l' || ctrlKey === 'r') {\n    incS = deltaX * Math.cos(angle) + deltaY * Math.sin(angle);\n    // l 缩放是反向的\n    incW = incS * (ctrlKey === 'l' ? -1 : 1);\n  } else if (ctrlKey === 't' || ctrlKey === 'b') {\n    // 计算矩形增加的宽度，旋转坐标系让x轴与角度重合，鼠标位置在x轴的投影（x值）即为增加的高度\n    rotateAngle = angle - Math.PI / 2;\n    incS = deltaX * Math.cos(rotateAngle) + deltaY * Math.sin(rotateAngle);\n    incH = incS * (ctrlKey === 'b' ? -1 : 1);\n  }\n\n  return { incW, incH, incS, rotateAngle };\n}\n\n/**\n * 等比例缩放\n */\nfunction fixedRatioScale({\n  deltaX,\n  deltaY,\n  angle,\n  ctrlKey,\n  diagonalAngle,\n}: {\n  deltaX: number;\n  deltaY: number;\n  angle: number;\n  ctrlKey: TCtrlKey;\n  diagonalAngle: number;\n}): {\n  incW: number;\n  incH: number;\n  incS: number;\n  rotateAngle: number;\n} {\n  // 坐标系旋转角度， lb->rt的对角线的初始角度为负数，所以需要乘以-1\n  const rotateAngle =\n    (ctrlKey === 'lt' || ctrlKey === 'rb' ? 1 : -1) * diagonalAngle + angle;\n  // 旋转坐标系让x轴与对角线重合，鼠标位置在x轴的投影（x值）即为增加的长度\n  const incS = deltaX * Math.cos(rotateAngle) + deltaY * Math.sin(rotateAngle);\n  // lb lt 缩放值是反向\n  const coefficient = ctrlKey === 'lt' || ctrlKey === 'lb' ? -1 : 1;\n  // 等比例缩放，增加宽高等于长度乘以对应的角度函数\n  // 因为等比例缩放，中心及被拖拽的点，一定在对角线上\n  const incW = incS * Math.cos(diagonalAngle) * coefficient;\n  const incH = incS * Math.sin(diagonalAngle) * coefficient;\n\n  return { incW, incH, incS, rotateAngle };\n}\n\n/**\n * 监听拖拽事件，将鼠标坐标转换为旋转角度\n * 旋转时，rect的坐标不变\n */\nfunction rotateRect(rect: Rect, outCnt: IPoint): void {\n  const onMove = ({ clientX, clientY }: MouseEvent): void => {\n    // 映射为 中心点坐标系\n    const x = clientX - outCnt.x;\n    const y = clientY - outCnt.y;\n    // 旋转控制点在正上方，与 x 轴是 -90°， 所以需要加上 Math.PI / 2\n    const angle = Math.atan2(y, x) + Math.PI / 2;\n    rect.angle = angle;\n  };\n  const clear = (): void => {\n    window.removeEventListener('pointermove', onMove);\n    window.removeEventListener('pointerup', clear);\n  };\n  window.addEventListener('pointermove', onMove);\n  window.addEventListener('pointerup', clear);\n}\n\n/**\n * canvas 内部（resolution）坐标映射成外部（DOM）坐标\n */\nfunction cntMap2Outer(\n  cnt: IPoint,\n  cvsRatio: ICvsRatio,\n  cvsEl: HTMLElement,\n): IPoint {\n  const x = cnt.x * cvsRatio.w;\n  const y = cnt.y * cvsRatio.h;\n\n  const { left, top } = cvsEl.getBoundingClientRect();\n  return {\n    x: x + left,\n    y: y + top,\n  };\n}\n\n/**\n * 限制安全范围，避免 sprite 完全超出边界\n */\nfunction updateRectWithSafeMargin(\n  rect: Rect,\n  cvsEl: HTMLCanvasElement,\n  value: Partial<Pick<Rect, 'x' | 'y' | 'w' | 'h'>>,\n) {\n  const newState = { x: rect.x, y: rect.y, w: rect.w, h: rect.h, ...value };\n  const safeWidth = cvsEl.width * 0.05;\n  const safeHeight = cvsEl.height * 0.05;\n  if (newState.x < -newState.w + safeWidth) {\n    newState.x = -newState.w + safeWidth;\n  } else if (newState.x > cvsEl.width - safeWidth) {\n    newState.x = cvsEl.width - safeWidth;\n  }\n  if (newState.y < -newState.h + safeHeight) {\n    newState.y = -newState.h + safeHeight;\n  } else if (newState.y > cvsEl.height - safeHeight) {\n    newState.y = cvsEl.height - safeHeight;\n  }\n  rect.x = newState.x;\n  rect.y = newState.y;\n  rect.w = newState.w;\n  rect.h = newState.h;\n}\n\n/**\n * 创建四周+中线参考线, 靠近具有磁吸效果\n */\nfunction createRefline(cvsEl: HTMLCanvasElement, container: HTMLElement) {\n  const reflineBaseCSS = `display: none; position: absolute;`;\n  const baseSettings = { w: 0, h: 0, x: 0, y: 0 } as const;\n  const reflineSettings: Record<\n    'top' | 'bottom' | 'left' | 'right' | 'vertMiddle' | 'horMiddle',\n    {\n      // 四周加中线参考线，它们的坐标、宽高只能是 0 ｜ 50 ｜ 100\n      w: 0 | 50 | 100;\n      h: 0 | 50 | 100;\n      x: 0 | 50 | 100;\n      y: 0 | 50 | 100;\n      ref: { prop: 'x' | 'y'; val: (rect: Rect) => number };\n    }\n  > = {\n    vertMiddle: {\n      ...baseSettings,\n      h: 100,\n      x: 50,\n      ref: { prop: 'x', val: ({ w }) => (cvsEl.width - w) / 2 },\n    },\n    horMiddle: {\n      ...baseSettings,\n      w: 100,\n      y: 50,\n      ref: { prop: 'y', val: ({ h }) => (cvsEl.height - h) / 2 },\n    },\n    top: {\n      ...baseSettings,\n      w: 100,\n      ref: { prop: 'y', val: () => 0 },\n    },\n    bottom: {\n      ...baseSettings,\n      w: 100,\n      y: 100,\n      ref: { prop: 'y', val: ({ h }) => cvsEl.height - h },\n    },\n    left: {\n      ...baseSettings,\n      h: 100,\n      ref: { prop: 'x', val: () => 0 },\n    },\n    right: {\n      ...baseSettings,\n      h: 100,\n      x: 100,\n      ref: { prop: 'x', val: ({ w }) => cvsEl.width - w },\n    },\n  } as const;\n\n  const lineWrap = createEl('div');\n  lineWrap.style.cssText = `\n    position: absolute;\n    z-index: 4;\n    top: 0; left: 0;\n    width: 100%; height: 100%;\n    pointer-events: none;\n    box-sizing: border-box;\n  `;\n  const reflineEls = Object.fromEntries(\n    Object.entries(reflineSettings).map(([key, { w, h, x, y }]) => {\n      const lineEl = createEl('div');\n      lineEl.style.cssText = `\n        ${reflineBaseCSS}\n        border-${w > 0 ? 'top' : 'left'}: 1px solid #3ee;\n        top: ${y}%; left: ${x}%;\n        ${x === 100 ? 'margin-left: -1px' : ''};\n        ${y === 100 ? 'margin-top: -1px' : ''};\n        width: ${w}%; height: ${h}%;\n      `;\n      lineWrap.appendChild(lineEl);\n      return [key, lineEl];\n    }),\n  ) as Record<keyof typeof reflineSettings, HTMLDivElement>;\n  container.appendChild(lineWrap);\n\n  const magneticDistance = 6 / (900 / cvsEl.width);\n  return {\n    magneticEffect(expectX: number, expectY: number, rect: Rect) {\n      const retVal = { x: expectX, y: expectY };\n\n      // 记录每个维度(x,y)的最小距离和对应的参考线\n      const minDist = { x: magneticDistance, y: magneticDistance };\n\n      type RefLineKey = keyof typeof reflineEls;\n      const activeReflines = { x: '', y: '' } as {\n        x: RefLineKey | '';\n        y: RefLineKey | '';\n      };\n\n      // 隐藏所有参考线，稍后会显示激活的参考线\n      Object.values(reflineEls).forEach((el) => (el.style.display = 'none'));\n\n      // 遍历所有参考线\n      for (const reflineKey in reflineSettings) {\n        const { prop, val } =\n          reflineSettings[reflineKey as keyof typeof reflineSettings].ref;\n        const refVal = val(rect);\n        const currentVal = prop === 'x' ? expectX : expectY;\n\n        // 计算与参考线的距离\n        const dist = Math.abs(currentVal - refVal);\n\n        // 在磁吸范围内，且比当前记录的最小距离更近\n        if (dist <= magneticDistance && dist < minDist[prop]) {\n          minDist[prop] = dist;\n          retVal[prop] = refVal;\n          activeReflines[prop] = reflineKey as RefLineKey;\n        }\n      }\n\n      // 显示激活的参考线\n      if (activeReflines.x) {\n        reflineEls[activeReflines.x].style.display = 'block';\n      }\n      if (activeReflines.y) {\n        reflineEls[activeReflines.y].style.display = 'block';\n      }\n\n      return retVal;\n    },\n    hide() {\n      Object.values(reflineEls).forEach((el) => (el.style.display = 'none'));\n    },\n    destroy() {\n      lineWrap.remove();\n    },\n  };\n}\n","import {\n  Combinator,\n  ICombinatorOpts,\n  Log,\n  MediaStreamClip,\n  OffscreenSprite,\n  Rect,\n  VisibleSprite,\n} from '@webav/av-cliper';\nimport { EventTool, throttle, workerTimer } from '@webav/internal-utils';\nimport { renderCtrls } from './sprites/render-ctrl';\nimport { ESpriteManagerEvt, SpriteManager } from './sprites/sprite-manager';\nimport { activeSprite, draggabelSprite } from './sprites/sprite-op';\nimport { IResolution } from './types';\nimport { createEl, getRectCtrls } from './utils';\n\n/**\n * 默认的音频设置，⚠️ 不要变更它的值 ⚠️\n */\nconst DEFAULT_AUDIO_CONF = {\n  sampleRate: 48000,\n  channelCount: 2,\n  codec: 'mp4a.40.2',\n} as const;\n\nfunction createInitCvsEl(resolution: IResolution): HTMLCanvasElement {\n  const cvsEl = createEl('canvas') as HTMLCanvasElement;\n  cvsEl.style.cssText = `\n    width: 100%;\n    height: 100%;\n    display: block;\n    touch-action: none;\n  `;\n  cvsEl.width = resolution.width;\n  cvsEl.height = resolution.height;\n\n  return cvsEl;\n}\n\n/**\n *\n * 一个可交互的画布，让用户添加各种素材，支持基础交互（拖拽、缩放、旋转、时间偏移）\n *\n * 用于在 Web 环境中实现视频剪辑、直播推流工作台功能\n *\n * @description\n *\n  - 添加/删除素材（视频、音频、图片、文字）\n  - 分割（裁剪）素材\n  - 控制素材在视频中的空间属性（坐标、旋转、缩放）\n  - 控制素材在视频中的时间属性（偏移、时长）\n  - 实时预览播放\n  - 纯浏览器环境生成视频\n\n * @see [直播录制](https://webav-tech.github.io/WebAV/demo/4_2-recorder-avcanvas)\n * @see [视频剪辑](https://webav-tech.github.io/WebAV/demo/6_4-video-editor)\n * @example\n * const avCvs = new AVCanvas(document.querySelector('#app'), {\n *   bgColor: '#333',\n *   width: 1920,\n *   height: 1080,\n * });\n *\n */\nexport class AVCanvas {\n  #cvsEl: HTMLCanvasElement;\n\n  #spriteManager: SpriteManager;\n\n  #cvsCtx: CanvasRenderingContext2D;\n\n  #destroyed = false;\n\n  #clears: Array<() => void> = [];\n  #stopRender: () => void;\n\n  #evtTool = new EventTool<{\n    timeupdate: (time: number) => void;\n    paused: () => void;\n    playing: () => void;\n    activeSpriteChange: (sprite: VisibleSprite | null) => void;\n  }>();\n  on = this.#evtTool.on;\n\n  #opts;\n  /**\n   * 预览帧生成中\n   */\n  #waitingPreviewFrame = false;\n\n  /**\n   * 创建 `AVCanvas` 类的实例。\n   * @param attchEl - 要添加画布的元素。\n   * @param opts - 画布的选项\n   * @param opts.bgColor - 画布的背景颜色。\n   * @param opts.width - 画布的宽度。\n   * @param opts.height - 画布的高度。\n   */\n  constructor(\n    attchEl: HTMLElement,\n    opts: {\n      bgColor: string;\n    } & IResolution,\n  ) {\n    this.#opts = opts;\n    this.#cvsEl = createInitCvsEl(opts);\n    const ctx = this.#cvsEl.getContext('2d', { alpha: false });\n    if (ctx == null) throw Error('canvas context is null');\n    this.#cvsCtx = ctx;\n    const container = createEl('div');\n    container.style.cssText = 'width: 100%; height: 100%; position: relative;';\n    container.appendChild(this.#cvsEl);\n    attchEl.appendChild(container);\n\n    createEmptyOscillatorNode(this.#audioCtx).connect(this.#captureAudioDest);\n\n    // 创建 this.#cvsEl 时自动设置 ctrlSize 初始值\n    // 避免首次渲染时 ctrls 节点大小不符合期望，所以这里不需要它的返回值\n    getRectCtrls(this.#cvsEl, { x: 0, y: 0, w: 0, h: 0 } as Rect);\n\n    this.#spriteManager = new SpriteManager();\n\n    this.#clears.push(\n      // 鼠标样式、控制 sprite 依赖 activeSprite，\n      // activeSprite 需要在他们之前监听到 mousedown 事件 (代码顺序需要靠前)\n      activeSprite(this.#cvsEl, this.#spriteManager),\n      renderCtrls(container, this.#cvsEl, this.#spriteManager),\n      draggabelSprite(this.#cvsEl, this.#spriteManager, container),\n      this.#spriteManager.on(ESpriteManagerEvt.AddSprite, (s) => {\n        const { rect } = s;\n        // 默认居中\n        if (rect.x === 0 && rect.y === 0) {\n          rect.x = (this.#cvsEl.width - rect.w) / 2;\n          rect.y = (this.#cvsEl.height - rect.h) / 2;\n        }\n      }),\n      EventTool.forwardEvent(this.#spriteManager, this.#evtTool, [\n        ESpriteManagerEvt.ActiveSpriteChange,\n      ]),\n    );\n\n    let lastRenderTime = this.#renderTime;\n    let start = performance.now();\n    let runCnt = 0;\n    const expectFrameTime = 1000 / 30;\n    this.#stopRender = workerTimer(() => {\n      // workerTimer 会略快于真实时钟，使用真实时间（performance.now）作为基准\n      // 跳过部分运行帧修正时间，避免导致音画不同步\n      if ((performance.now() - start) / (expectFrameTime * runCnt) < 1) {\n        return;\n      }\n      // 如果正在准备下一次预览画面，则暂时跳过渲染；避免多个素材之间来回 seek 导致闪烁\n      if (this.#waitingPreviewFrame) return;\n\n      runCnt += 1;\n      this.#cvsCtx.fillStyle = opts.bgColor;\n      this.#cvsCtx.fillRect(0, 0, this.#cvsEl.width, this.#cvsEl.height);\n      this.#render();\n\n      if (lastRenderTime !== this.#renderTime) {\n        lastRenderTime = this.#renderTime;\n        this.#evtTool.emit('timeupdate', Math.round(lastRenderTime));\n      }\n    }, expectFrameTime);\n\n    // ;(window as any).cvsEl = this.#cvsEl\n  }\n\n  #renderTime = 0e6;\n  #updateRenderTime(time: number) {\n    this.#renderTime = time;\n    this.#spriteManager.updateRenderTime(time);\n    this.#autoPreFrame.updateTime(time);\n  }\n\n  #pause() {\n    if (this.#playState.step === 0) return;\n    this.#playState.step = 0;\n    this.#evtTool.emit('paused');\n    this.#audioCtx.suspend();\n    for (const asn of this.#playingAudioCache) {\n      asn.stop();\n      asn.disconnect();\n    }\n    this.#playingAudioCache.clear();\n    this.#autoPreFrame.reset();\n  }\n\n  #audioCtx = new AudioContext();\n  #captureAudioDest = this.#audioCtx.createMediaStreamDestination();\n\n  #playingAudioCache: Set<AudioBufferSourceNode> = new Set();\n  #render() {\n    const cvsCtx = this.#cvsCtx;\n    let ts = this.#renderTime;\n    const { start, end, step, audioPlayAt } = this.#playState;\n    ts += step;\n    if (step !== 0 && ts >= start && ts < end) {\n      this.#updateRenderTime(ts);\n    } else {\n      this.#pause();\n    }\n\n    const ctxDestAudioData: Float32Array[][] = [];\n    for (const s of this.#spriteManager.getSprites()) {\n      cvsCtx.save();\n      const { audio } = s.render(cvsCtx, ts - s.time.offset);\n      cvsCtx.restore();\n\n      ctxDestAudioData.push(audio);\n    }\n    cvsCtx.resetTransform();\n\n    if (step !== 0) {\n      const curAudioTime = Math.max(this.#audioCtx.currentTime, audioPlayAt);\n      const audioSourceArr = convertPCM2AudioSource(\n        ctxDestAudioData,\n        this.#audioCtx,\n      );\n\n      let addTime = 0;\n      for (const ads of audioSourceArr) {\n        ads.start(curAudioTime);\n        ads.connect(this.#audioCtx.destination);\n        ads.connect(this.#captureAudioDest);\n\n        this.#playingAudioCache.add(ads);\n        ads.onended = () => {\n          ads.disconnect();\n          this.#playingAudioCache.delete(ads);\n        };\n        addTime = Math.max(addTime, ads.buffer?.duration ?? 0);\n      }\n      this.#playState.audioPlayAt = curAudioTime + addTime;\n    }\n  }\n\n  #playState = {\n    start: 0,\n    end: 0,\n    // paused state when step equal 0\n    step: 0,\n    // step: (1000 / 30) * 1000,\n    audioPlayAt: 0,\n  };\n  /**\n   * 每 33ms 更新一次画布，绘制已添加的 Sprite\n   * @param opts - 播放选项\n   * @param opts.start - 开始播放的时间（单位：微秒）\n   * @param [opts.end] - 结束播放的时间（单位：微秒）。如果未指定，则播放到最后一个 Sprite 的结束时间\n   * @param [opts.playbackRate] - 播放速率。1 表示正常速度，2 表示两倍速度，0.5 表示半速等。如果未指定，则默认为 1\n   * @throws 如果开始时间大于等于结束时间或小于 0，则抛出错误\n   */\n  play(opts: { start: number; end?: number; playbackRate?: number }) {\n    const spriteTimes = this.#spriteManager\n      .getSprites({ time: false })\n      .map((s) => s.time.offset + s.time.duration);\n    const end =\n      opts.end ??\n      (spriteTimes.length > 0 ? Math.max(...spriteTimes) : Infinity);\n\n    if (opts.start >= end || opts.start < 0) {\n      throw Error(\n        `Invalid time parameter, ${JSON.stringify({ start: opts.start, end })}`,\n      );\n    }\n\n    this.#updateRenderTime(opts.start);\n    this.#autoPreFrame.reset();\n\n    this.#playState.start = opts.start;\n    this.#playState.end = end;\n    // AVCanvas 30FPS，将播放速率转换成步长\n    this.#playState.step = (opts.playbackRate ?? 1) * (1000 / 30) * 1000;\n    this.#audioCtx.resume();\n    this.#playState.audioPlayAt = 0;\n\n    this.#evtTool.emit('playing');\n    Log.info('AVCanvs play by:', this.#playState);\n  }\n\n  #autoPreFrame = (() => {\n    const readyVS = new Set<VisibleSprite>();\n    return {\n      reset() {\n        readyVS.clear();\n      },\n      updateTime: throttle((curTime: number) => {\n        const sprs = this.#spriteManager.getSprites({ time: false });\n        // 匹配接下来 1s 内即将要播放的 Sprite\n        const matchPreSprs = sprs.filter((vs) => {\n          const { offset } = vs.time;\n          return offset > curTime && offset - 1e6 <= curTime;\n        });\n        for (const vs of matchPreSprs) {\n          if (!readyVS.has(vs)) vs.preFrame(0);\n          readyVS.add(vs);\n        }\n      }, 500),\n    };\n  })();\n\n  /**\n   * 暂停播放，画布内容不再更新\n   */\n  pause() {\n    this.#pause();\n  }\n\n  /**\n   * 预览 `AVCanvas` 指定时间的图像帧\n   */\n  async previewFrame(time: number) {\n    this.#pause();\n    this.#updateRenderTime(time);\n    this.#waitingPreviewFrame = true;\n    try {\n      await Promise.all(\n        this.#spriteManager.getSprites({ time: false }).map((vs) => {\n          if (\n            time >= vs.time.offset &&\n            time <= vs.time.offset + vs.time.duration\n          ) {\n            return vs.preFrame(time - vs.time.offset);\n          }\n          return null;\n        }),\n      );\n    } finally {\n      this.#waitingPreviewFrame = false;\n    }\n  }\n\n  /**\n   * 获取当前帧的截图图像 返回的是一个base64\n   */\n  captureImage(): string {\n    return this.#cvsEl.toDataURL();\n  }\n\n  get activeSprite() {\n    return this.#spriteManager.activeSprite;\n  }\n  set activeSprite(s: VisibleSprite | null) {\n    this.#spriteManager.activeSprite = s;\n  }\n\n  #sprMapAudioNode = new WeakMap<VisibleSprite, AudioNode>();\n  /**\n   * 添加 {@link VisibleSprite}\n   * @param args {@link VisibleSprite}\n   * @example\n   * const sprite = new VisibleSprite(\n   *   new ImgClip({\n   *     type: 'image/gif',\n   *     stream: (await fetch('https://xx.gif')).body!,\n   *   }),\n   * );\n   */\n  addSprite: SpriteManager['addSprite'] = async (vs) => {\n    if (this.#audioCtx.state === 'suspended')\n      this.#audioCtx.resume().catch(Log.error);\n\n    const clip = vs.getClip();\n    if (clip instanceof MediaStreamClip && clip.audioTrack != null) {\n      const audioNode = this.#audioCtx.createMediaStreamSource(\n        new MediaStream([clip.audioTrack]),\n      );\n      audioNode.connect(this.#captureAudioDest);\n      this.#sprMapAudioNode.set(vs, audioNode);\n    }\n    await this.#spriteManager.addSprite(vs);\n  };\n  /**\n   * 删除 {@link VisibleSprite}\n   * @param args\n   * @returns\n   * @example\n   * const sprite = new VisibleSprite();\n   * avCvs.removeSprite(sprite);\n   */\n  removeSprite: SpriteManager['removeSprite'] = (vs) => {\n    this.#sprMapAudioNode.get(vs)?.disconnect();\n    this.#spriteManager.removeSprite(vs);\n  };\n\n  /**\n   * 销毁实例\n   */\n  destroy(): void {\n    if (this.#destroyed) return;\n    this.#destroyed = true;\n\n    this.#audioCtx.close();\n    this.#captureAudioDest.disconnect();\n    this.#evtTool.destroy();\n    this.#stopRender();\n    this.#cvsEl.parentElement?.remove();\n    this.#clears.forEach((fn) => fn());\n    this.#playingAudioCache.clear();\n    this.#spriteManager.destroy();\n  }\n\n  /**\n   * 合成所有素材的图像与音频，返回实时媒体流 `MediaStream`\n   *\n   * 可用于 WebRTC 推流，或由 {@link [AVRecorder](../../av-recorder/classes/AVRecorder.html)} 录制生成视频文件\n   *\n   * @see [直播录制](https://webav-tech.github.io/WebAV/demo/4_2-recorder-avcanvas)\n   *\n   */\n  captureStream(): MediaStream {\n    if (this.#audioCtx.state === 'suspended') {\n      this.#audioCtx.resume().catch(Log.error);\n    }\n\n    const ms = new MediaStream(\n      this.#cvsEl\n        .captureStream()\n        .getTracks()\n        .concat(this.#captureAudioDest.stream.getTracks()),\n    );\n    Log.info(\n      'AVCanvas.captureStream, tracks:',\n      ms.getTracks().map((t) => t.kind),\n    );\n    return ms;\n  }\n\n  /**\n   * 创建一个视频合成器 {@link [Combinator](../../av-cliper/classes/Combinator.html)} 实例，用于将当前画布添加的 Sprite 导出为视频文件流\n   *\n   * @param opts - 创建 Combinator 的可选参数\n   * @throws 如果没有添加素材，会抛出错误\n   *\n   * @example\n   * avCvs.createCombinator().output() // => ReadableStream\n   *\n   * @see [视频剪辑](https://webav-tech.github.io/WebAV/demo/6_4-video-editor)\n   */\n  async createCombinator(opts: ICombinatorOpts = {}) {\n    Log.info('AVCanvas.createCombinator, opts:', opts);\n\n    const com = new Combinator({ ...this.#opts, ...opts });\n    const sprites = this.#spriteManager.getSprites({ time: false });\n    if (sprites.length === 0) throw Error('No sprite added');\n\n    for (const vs of sprites) {\n      const os = new OffscreenSprite(vs.getClip());\n      os.time = { ...vs.time };\n      vs.copyStateTo(os);\n      await com.addSprite(os);\n    }\n    return com;\n  }\n}\n\nfunction convertPCM2AudioSource(pcmData: Float32Array[][], ctx: AudioContext) {\n  const asArr: AudioBufferSourceNode[] = [];\n  if (pcmData.length === 0) return asArr;\n\n  for (const [chan0Buf, chan1Buf] of pcmData) {\n    if (chan0Buf == null) continue;\n    if (chan0Buf.length <= 0) continue;\n\n    const buf = ctx.createBuffer(\n      2,\n      chan0Buf.length,\n      DEFAULT_AUDIO_CONF.sampleRate,\n    );\n    buf.copyToChannel(chan0Buf, 0);\n    buf.copyToChannel(chan1Buf ?? chan0Buf, 1);\n    const audioSource = ctx.createBufferSource();\n    audioSource.buffer = buf;\n    asArr.push(audioSource);\n  }\n  return asArr;\n}\n\n/**\n * 空背景音，让 dest 能持续收到音频数据，否则时间会异常偏移\n */\nfunction createEmptyOscillatorNode(ctx: AudioContext) {\n  const osc = ctx.createOscillator();\n  const real = new Float32Array([0, 0]);\n  const imag = new Float32Array([0, 0]);\n  const wave = ctx.createPeriodicWave(real, imag, {\n    disableNormalization: true,\n  });\n  osc.setPeriodicWave(wave);\n  osc.start();\n  return osc;\n}\n"],"names":["CTRL_KEYS","createEl","tagName","rectGetterCache","getRectCtrls","cvsEl","rect","ctrlSize","entries","fisrtEntry","rectCtrlsGetter","w","sz","hfSz","hfW","hfH","rtSz","hfRtSz","Rect","cvsRatioCache","getCvsRatio","cvsRatio","ESpriteManagerEvt","SpriteManager","#sprites","#activeSprite","#evtTool","EventTool","s","x","y","vs","a","b","props","spr","filter","#renderTime","time","as","CloseSvg","renderCtrls","container","sprMng","observer","syncCtrlElPos","rectEl","ctrlsEl","lastActSprEvtClear","createRectAndCtrlEl","evt","cvsRect","offSprChange","k","d","h","angle","ctrlPosMap","key","el","pos","baseStyle","customStyle","activeSprite","onCvsMouseDown","offsetX","offsetY","ofx","ofy","draggabelSprite","startX","startY","startRect","refline","createRefline","onRectMouseDown","hitSpr","clientX","clientY","onMouseMove","clearWindowEvt","expectX","expectY","updateRectWithSafeMargin","offCtrlEvt","setupCtrlEvents","ctrlElements","ctrlEl","index","ctrlKey","rotateRect","cntMap2Outer","scaleRect","curStyles","curInitIdx","offPropsEvt","offActSprEvt","updateCursorStyle","debounce","oa","idx","sprRect","deltaX","deltaY","scaler","stretchScale","fixedRatioScale","diagonalAngle","incW","incH","incS","rotateAngle","minSize","newW","newH","newIncW","newIncH","newIncS","startS","minS","newX","newY","newCenterX","newCenterY","coefficient","outCnt","onMove","clear","cnt","left","top","value","newState","safeWidth","safeHeight","reflineBaseCSS","baseSettings","reflineSettings","lineWrap","reflineEls","lineEl","magneticDistance","retVal","minDist","activeReflines","reflineKey","prop","val","refVal","dist","DEFAULT_AUDIO_CONF","createInitCvsEl","resolution","AVCanvas","#cvsEl","#spriteManager","#cvsCtx","#destroyed","#clears","#stopRender","#opts","#waitingPreviewFrame","attchEl","opts","ctx","createEmptyOscillatorNode","#audioCtx","#captureAudioDest","lastRenderTime","start","runCnt","expectFrameTime","workerTimer","#render","#updateRenderTime","#autoPreFrame","#pause","#playState","asn","#playingAudioCache","cvsCtx","ts","end","step","audioPlayAt","ctxDestAudioData","audio","curAudioTime","audioSourceArr","convertPCM2AudioSource","addTime","ads","spriteTimes","Log","readyVS","throttle","curTime","matchPreSprs","offset","#sprMapAudioNode","clip","MediaStreamClip","audioNode","fn","ms","t","com","Combinator","sprites","os","OffscreenSprite","pcmData","asArr","chan0Buf","chan1Buf","buf","audioSource","osc","real","imag","wave"],"mappings":"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"}