MCPcopy Create free account
hub / github.com/heygen-com/hyperframes / handleSetTiming

Function handleSetTiming

packages/sdk/src/engine/mutate.ts:401–562  ·  view source on GitHub ↗
(
  parsed: ParsedDocument,
  ids: HfId[],
  timing: { start?: number; duration?: number; trackIndex?: number },
)

Source from the content-addressed store, hash-verified

399
400// fallow-ignore-next-line complexity
401function handleSetTiming(
402 parsed: ParsedDocument,
403 ids: HfId[],
404 timing: { start?: number; duration?: number; trackIndex?: number },
405): MutationResult {
406 const result: MutationResult = { forward: [], inverse: [] };
407
408 // Parse GSAP script once; updateAnimationInScript re-parses internally per call but
409 // we avoid re-fetching the script element on every iteration.
410 const origScript = getGsapScript(parsed.document);
411 const parsedGsap = origScript ? parseGsapScriptAcornForWrite(origScript) : null;
412 let currentScript = origScript;
413
414 for (const id of ids) {
415 const el = resolveScoped(parsed.document, id);
416 if (!el) continue;
417
418 const oldStartStr = el.getAttribute("data-start");
419 const oldEndStr = el.getAttribute("data-end");
420 const oldDurationStr = el.getAttribute("data-duration");
421 const oldTrackStr = el.getAttribute("data-track-index");
422
423 const oldStart = oldStartStr !== null ? parseFloat(oldStartStr) : null;
424 const oldEnd = oldEndStr !== null ? parseFloat(oldEndStr) : null;
425 const oldDurationAttr = oldDurationStr !== null ? parseFloat(oldDurationStr) : null;
426 // Prefer an explicit data-duration — the attribute clips are authored with and
427 // the runtime reads — falling back to data-end − data-start. Reading only
428 // data-end left oldDuration null for duration-authored clips, collapsing the
429 // GSAP duration-scale ratio to 1 and scaling nothing.
430 const oldDuration =
431 oldDurationAttr !== null
432 ? oldDurationAttr
433 : oldStart !== null && oldEnd !== null
434 ? oldEnd - oldStart
435 : null;
436 const oldTrack = oldTrackStr !== null ? parseInt(oldTrackStr, 10) : null;
437
438 const newStart = timing.start ?? oldStart;
439 const newDuration = timing.duration ?? oldDuration;
440
441 if (timing.start !== undefined && newStart !== null) {
442 const path = timingPath(id, "start");
443 const p = scalarChange(path, oldStart, newStart);
444 result.forward.push(p.forward);
445 result.inverse.push(p.inverse);
446 el.setAttribute("data-start", String(newStart));
447 }
448
449 // Write to whichever timing attribute the clip actually uses. A data-duration
450 // clip updates data-duration only on a real resize (duration is invariant
451 // under a move); a data-end clip updates data-end whenever start or duration
452 // changes (end = start + duration). Writing a fresh data-end beside a stale
453 // data-duration had no playback effect.
454 if (oldDurationStr !== null) {
455 if (timing.duration !== undefined && newDuration !== null) {
456 const path = timingPath(id, "duration");
457 const p = scalarChange(path, oldDurationAttr, newDuration);
458 result.forward.push(p.forward);

Callers 1

applyOpFunction · 0.85

Calls 11

getGsapScriptFunction · 0.85
resolveScopedFunction · 0.85
timingPathFunction · 0.85
scalarChangeFunction · 0.85
selectorMatchesIdFunction · 0.85
setGsapScriptFunction · 0.85
gsapScriptChangeFunction · 0.85
getAttributeMethod · 0.65
setAttributeMethod · 0.65
updateAnimationInScriptFunction · 0.50

Tested by

no test coverage detected