web-annotation-renderer 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index7.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const y=require("./index6.cjs"),u=require("./index10.cjs");class p extends y.default{constructor(e,r){super(e,r),this.layerElement=document.createElement("div"),this.layerElement.style.position="absolute",this.layerElement.style.inset="0",this.layerElement.style.pointerEvents="none",this.layerElement.style.zIndex="25",this.container.appendChild(this.layerElement),this.elements=new Map,this.rafId=null}render(){this.layerElement.innerHTML="",this.elements.clear(),this.annotations.forEach(e=>{if(e.mode!=="quads"||!e.quads?.length)return;const r=e.quads.reduce((a,i)=>a+i.w,0);e.quads.forEach((a,i)=>{const s=u.rectNormToAbs(a,this.viewport),n=e.quads.slice(0,i).reduce((m,c)=>m+c.w,0),h=n/r,d=(n+a.w)/r,t=document.createElement("div");t.style.position="absolute",t.style.left=`${s.left}px`,t.style.top=`${s.top}px`,t.style.width=`${s.width}px`,t.style.height=`${s.height}px`,t.style.overflow="hidden",t.style.borderRadius="2px";const l=document.createElement("div");l.style.width="100%",l.style.height="100%",l.style.background=e?.style?.color??"rgba(255,230,100,0.35)",l.style.outline="1px solid rgba(255,200,0,0.6)",l.style.transformOrigin="left center",l.style.transform="scaleX(0)",l.style.willChange="transform",t.appendChild(l),this.layerElement.appendChild(t);const o=`${e.id}-${i}`;this.elements.set(o,{element:l,wrapper:t,annotation:e,segStart:h,segEnd:d})})})}updateTime(e){super.updateTime(e),this.rafId&&(cancelAnimationFrame(this.rafId),this.rafId=null);const r=()=>{this.isDestroyed||(this.elements.forEach(({element:a,wrapper:i,annotation:s,segStart:n,segEnd:h})=>{if(e<s.start)i.style.display="none";else{i.style.display="block";const d=Math.max(0,Math.min(1,(e-s.start)/Math.max(1e-6,s.end-s.start))),t=Math.max(0,Math.min(1,(d-n)/Math.max(1e-6,h-n)));a.style.transform=`scaleX(${t})`}}),this.rafId=requestAnimationFrame(r))};r()}update(){}destroy(){this.rafId&&(cancelAnimationFrame(this.rafId),this.rafId=null),this.elements.clear(),this.elements=null,this.layerElement&&this.layerElement.parentNode&&this.layerElement.parentNode.removeChild(this.layerElement),this.layerElement=null,super.destroy()}}exports.default=p;
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const c=require("./index6.cjs"),u=require("./index10.cjs");class p extends c.default{constructor(e,a){super(e,a),this.layerElement=document.createElement("div"),this.layerElement.style.position="absolute",this.layerElement.style.inset="0",this.layerElement.style.pointerEvents="none",this.layerElement.style.zIndex="25",this.container.appendChild(this.layerElement),this.elements=new Map}render(){this.layerElement.innerHTML="",this.elements.clear(),this.annotations.forEach(e=>{if(e.mode!=="quads"||!e.quads?.length)return;const a=e.quads.reduce((r,s)=>r+s.w,0);e.quads.forEach((r,s)=>{const i=u.rectNormToAbs(r,this.viewport),n=e.quads.slice(0,s).reduce((y,m)=>y+m.w,0),h=n/a,d=(n+r.w)/a,t=document.createElement("div");t.style.position="absolute",t.style.left=`${i.left}px`,t.style.top=`${i.top}px`,t.style.width=`${i.width}px`,t.style.height=`${i.height}px`,t.style.overflow="hidden",t.style.borderRadius="2px";const l=document.createElement("div");l.style.width="100%",l.style.height="100%",l.style.background=e?.style?.color??"rgba(255,230,100,0.35)",l.style.outline="1px solid rgba(255,200,0,0.6)",l.style.transformOrigin="left center",l.style.transform="scaleX(0)",l.style.willChange="transform",t.appendChild(l),this.layerElement.appendChild(t);const o=`${e.id}-${s}`;this.elements.set(o,{element:l,wrapper:t,annotation:e,segStart:h,segEnd:d})})})}updateTime(e){super.updateTime(e),!this.isDestroyed&&this.elements.forEach(({element:a,wrapper:r,annotation:s,segStart:i,segEnd:n})=>{if(e<s.start)r.style.display="none";else{r.style.display="block";const h=Math.max(0,Math.min(1,(e-s.start)/Math.max(1e-6,s.end-s.start))),d=Math.max(0,Math.min(1,(h-i)/Math.max(1e-6,n-i)));a.style.transform=`scaleX(${d})`}})}update(){}destroy(){this.elements.clear(),this.elements=null,this.layerElement&&this.layerElement.parentNode&&this.layerElement.parentNode.removeChild(this.layerElement),this.layerElement=null,super.destroy()}}exports.default=p;
2
2
  //# sourceMappingURL=index7.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index7.cjs","sources":["../src/layers/HighlightLayer.js"],"sourcesContent":["import BaseLayer from './BaseLayer.js';\nimport { rectNormToAbs } from '../utils/coordinateUtils.js';\n\n/**\n * HighlightLayer - Renders highlight annotations with progressive reveal\n *\n * Extends BaseLayer to render rectangular highlight regions (quads) with\n * progressive left-to-right scaleX animation based on timeline position.\n * Supports multi-line highlights with per-quad timing segments.\n *\n * @extends BaseLayer\n */\nclass HighlightLayer extends BaseLayer {\n /**\n * Creates a new HighlightLayer instance\n *\n * @param {HTMLElement} container - Parent DOM element for layer content\n * @param {Object} viewport - Initial viewport dimensions\n * @param {number} viewport.width - Viewport width in pixels\n * @param {number} viewport.height - Viewport height in pixels\n * @param {number} viewport.scale - PDF scale/zoom level\n */\n constructor(container, viewport) {\n super(container, viewport);\n\n // Create layer container element\n this.layerElement = document.createElement('div');\n this.layerElement.style.position = 'absolute';\n this.layerElement.style.inset = '0';\n this.layerElement.style.pointerEvents = 'none';\n this.layerElement.style.zIndex = '25';\n\n this.container.appendChild(this.layerElement);\n\n // Initialize element storage\n this.elements = new Map();\n\n // Initialize RAF ID\n this.rafId = null;\n }\n\n /**\n * Renders highlight elements for all annotations\n *\n * Creates DOM structure for each quad in each annotation. Calculates\n * timing segments for progressive animation. Clears and recreates all\n * elements when called.\n */\n render() {\n // Clear existing elements\n this.layerElement.innerHTML = '';\n this.elements.clear();\n\n // Process each annotation\n this.annotations.forEach((annotation) => {\n // Skip if not quad mode or no quads\n if (annotation.mode !== 'quads' || !annotation.quads?.length) {\n return;\n }\n\n // Calculate total width across all quads\n const totalW = annotation.quads.reduce((sum, quad) => sum + quad.w, 0);\n\n // Process each quad\n annotation.quads.forEach((quad, idx) => {\n // Convert normalized coordinates to absolute pixels\n const abs = rectNormToAbs(quad, this.viewport);\n\n // Calculate timing segment for this quad\n const prevW = annotation.quads.slice(0, idx).reduce((sum, q) => sum + q.w, 0);\n const segStart = prevW / totalW;\n const segEnd = (prevW + quad.w) / totalW;\n\n // Create wrapper div\n const wrapper = document.createElement('div');\n wrapper.style.position = 'absolute';\n wrapper.style.left = `${abs.left}px`;\n wrapper.style.top = `${abs.top}px`;\n wrapper.style.width = `${abs.width}px`;\n wrapper.style.height = `${abs.height}px`;\n wrapper.style.overflow = 'hidden';\n wrapper.style.borderRadius = '2px';\n\n // Create highlight div\n const highlight = document.createElement('div');\n highlight.style.width = '100%';\n highlight.style.height = '100%';\n highlight.style.background = annotation?.style?.color ?? 'rgba(255,230,100,0.35)';\n highlight.style.outline = '1px solid rgba(255,200,0,0.6)';\n highlight.style.transformOrigin = 'left center';\n highlight.style.transform = 'scaleX(0)';\n highlight.style.willChange = 'transform';\n\n // Assemble DOM structure\n wrapper.appendChild(highlight);\n this.layerElement.appendChild(wrapper);\n\n // Store reference for animation\n const key = `${annotation.id}-${idx}`;\n this.elements.set(key, {\n element: highlight,\n wrapper: wrapper,\n annotation: annotation,\n segStart: segStart,\n segEnd: segEnd\n });\n });\n });\n }\n\n /**\n * Updates highlight animations based on current timeline position\n *\n * Starts requestAnimationFrame loop to animate scaleX transform for\n * each highlight element. Calculates progress for each quad segment\n * and updates visibility.\n *\n * @param {number} nowSec - Current timeline position in seconds\n */\n updateTime(nowSec) {\n super.updateTime(nowSec);\n\n // Cancel existing RAF if running\n if (this.rafId) {\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n\n // Start animation loop\n const animate = () => {\n if (this.isDestroyed) {\n return;\n }\n\n // Update each highlight element\n this.elements.forEach(({ element, wrapper, annotation, segStart, segEnd }) => {\n // Hide wrapper if time hasn't reached annotation start\n if (nowSec < annotation.start) {\n wrapper.style.display = 'none';\n } else {\n // Show wrapper\n wrapper.style.display = 'block';\n\n // Calculate global progress (0 to 1)\n const globalProgress = Math.max(\n 0,\n Math.min(\n 1,\n (nowSec - annotation.start) / Math.max(1e-6, annotation.end - annotation.start)\n )\n );\n\n // Calculate local progress for this quad segment (0 to 1)\n const localProgress = Math.max(\n 0,\n Math.min(\n 1,\n (globalProgress - segStart) / Math.max(1e-6, segEnd - segStart)\n )\n );\n\n // Apply scaleX transform\n element.style.transform = `scaleX(${localProgress})`;\n }\n });\n\n // Schedule next frame\n this.rafId = requestAnimationFrame(animate);\n };\n\n animate();\n }\n\n /**\n * Updates the visual state of the layer\n *\n * Not used by HighlightLayer - animation handled in updateTime()\n */\n update() {\n // Not used - updateTime handles animation directly\n }\n\n /**\n * Destroys the layer and releases all resources\n *\n * Cancels animation loop, clears element storage, removes DOM elements,\n * and calls parent cleanup.\n */\n destroy() {\n // Cancel RAF if running\n if (this.rafId) {\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n\n // Clear element storage\n this.elements.clear();\n this.elements = null;\n\n // Remove layer element from DOM\n if (this.layerElement && this.layerElement.parentNode) {\n this.layerElement.parentNode.removeChild(this.layerElement);\n }\n this.layerElement = null;\n\n // Call parent destroy\n super.destroy();\n }\n}\n\nexport default HighlightLayer;\n"],"names":["HighlightLayer","BaseLayer","container","viewport","annotation","totalW","sum","quad","idx","abs","rectNormToAbs","prevW","q","segStart","segEnd","wrapper","highlight","key","nowSec","animate","element","globalProgress","localProgress"],"mappings":"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"}
1
+ {"version":3,"file":"index7.cjs","sources":["../src/layers/HighlightLayer.js"],"sourcesContent":["import BaseLayer from './BaseLayer.js';\nimport { rectNormToAbs } from '../utils/coordinateUtils.js';\n\n/**\n * HighlightLayer - Renders highlight annotations with progressive reveal\n *\n * Extends BaseLayer to render rectangular highlight regions (quads) with\n * progressive left-to-right scaleX animation based on timeline position.\n * Supports multi-line highlights with per-quad timing segments.\n *\n * @extends BaseLayer\n */\nclass HighlightLayer extends BaseLayer {\n /**\n * Creates a new HighlightLayer instance\n *\n * @param {HTMLElement} container - Parent DOM element for layer content\n * @param {Object} viewport - Initial viewport dimensions\n * @param {number} viewport.width - Viewport width in pixels\n * @param {number} viewport.height - Viewport height in pixels\n * @param {number} viewport.scale - PDF scale/zoom level\n */\n constructor(container, viewport) {\n super(container, viewport);\n\n // Create layer container element\n this.layerElement = document.createElement('div');\n this.layerElement.style.position = 'absolute';\n this.layerElement.style.inset = '0';\n this.layerElement.style.pointerEvents = 'none';\n this.layerElement.style.zIndex = '25';\n\n this.container.appendChild(this.layerElement);\n\n // Initialize element storage\n this.elements = new Map();\n }\n\n /**\n * Renders highlight elements for all annotations\n *\n * Creates DOM structure for each quad in each annotation. Calculates\n * timing segments for progressive animation. Clears and recreates all\n * elements when called.\n */\n render() {\n // Clear existing elements\n this.layerElement.innerHTML = '';\n this.elements.clear();\n\n // Process each annotation\n this.annotations.forEach((annotation) => {\n // Skip if not quad mode or no quads\n if (annotation.mode !== 'quads' || !annotation.quads?.length) {\n return;\n }\n\n // Calculate total width across all quads\n const totalW = annotation.quads.reduce((sum, quad) => sum + quad.w, 0);\n\n // Process each quad\n annotation.quads.forEach((quad, idx) => {\n // Convert normalized coordinates to absolute pixels\n const abs = rectNormToAbs(quad, this.viewport);\n\n // Calculate timing segment for this quad\n const prevW = annotation.quads.slice(0, idx).reduce((sum, q) => sum + q.w, 0);\n const segStart = prevW / totalW;\n const segEnd = (prevW + quad.w) / totalW;\n\n // Create wrapper div\n const wrapper = document.createElement('div');\n wrapper.style.position = 'absolute';\n wrapper.style.left = `${abs.left}px`;\n wrapper.style.top = `${abs.top}px`;\n wrapper.style.width = `${abs.width}px`;\n wrapper.style.height = `${abs.height}px`;\n wrapper.style.overflow = 'hidden';\n wrapper.style.borderRadius = '2px';\n\n // Create highlight div\n const highlight = document.createElement('div');\n highlight.style.width = '100%';\n highlight.style.height = '100%';\n highlight.style.background = annotation?.style?.color ?? 'rgba(255,230,100,0.35)';\n highlight.style.outline = '1px solid rgba(255,200,0,0.6)';\n highlight.style.transformOrigin = 'left center';\n highlight.style.transform = 'scaleX(0)';\n highlight.style.willChange = 'transform';\n\n // Assemble DOM structure\n wrapper.appendChild(highlight);\n this.layerElement.appendChild(wrapper);\n\n // Store reference for animation\n const key = `${annotation.id}-${idx}`;\n this.elements.set(key, {\n element: highlight,\n wrapper: wrapper,\n annotation: annotation,\n segStart: segStart,\n segEnd: segEnd\n });\n });\n });\n }\n\n /**\n * Updates highlight animations based on current timeline position\n *\n * Updates scaleX transform for each highlight element based on timeline.\n * Calculates progress for each quad segment and updates visibility.\n * Renders once per call - no continuous loop.\n *\n * @param {number} nowSec - Current timeline position in seconds\n */\n updateTime(nowSec) {\n super.updateTime(nowSec);\n\n if (this.isDestroyed) {\n return;\n }\n\n // Update each highlight element\n this.elements.forEach(({ element, wrapper, annotation, segStart, segEnd }) => {\n // Hide wrapper if time hasn't reached annotation start\n if (nowSec < annotation.start) {\n wrapper.style.display = 'none';\n } else {\n // Show wrapper\n wrapper.style.display = 'block';\n\n // Calculate global progress (0 to 1)\n const globalProgress = Math.max(\n 0,\n Math.min(\n 1,\n (nowSec - annotation.start) / Math.max(1e-6, annotation.end - annotation.start)\n )\n );\n\n // Calculate local progress for this quad segment (0 to 1)\n const localProgress = Math.max(\n 0,\n Math.min(\n 1,\n (globalProgress - segStart) / Math.max(1e-6, segEnd - segStart)\n )\n );\n\n // Apply scaleX transform\n element.style.transform = `scaleX(${localProgress})`;\n }\n });\n }\n\n /**\n * Updates the visual state of the layer\n *\n * Not used by HighlightLayer - animation handled in updateTime()\n */\n update() {\n // Not used - updateTime handles animation directly\n }\n\n /**\n * Destroys the layer and releases all resources\n *\n * Clears element storage, removes DOM elements, and calls parent cleanup.\n */\n destroy() {\n // Clear element storage\n this.elements.clear();\n this.elements = null;\n\n // Remove layer element from DOM\n if (this.layerElement && this.layerElement.parentNode) {\n this.layerElement.parentNode.removeChild(this.layerElement);\n }\n this.layerElement = null;\n\n // Call parent destroy\n super.destroy();\n }\n}\n\nexport default HighlightLayer;\n"],"names":["HighlightLayer","BaseLayer","container","viewport","annotation","totalW","sum","quad","idx","abs","rectNormToAbs","prevW","q","segStart","segEnd","wrapper","highlight","key","nowSec","element","globalProgress","localProgress"],"mappings":"uKAYA,MAAMA,UAAuBC,EAAAA,OAAU,CAUrC,YAAYC,EAAWC,EAAU,CAC/B,MAAMD,EAAWC,CAAQ,EAGzB,KAAK,aAAe,SAAS,cAAc,KAAK,EAChD,KAAK,aAAa,MAAM,SAAW,WACnC,KAAK,aAAa,MAAM,MAAQ,IAChC,KAAK,aAAa,MAAM,cAAgB,OACxC,KAAK,aAAa,MAAM,OAAS,KAEjC,KAAK,UAAU,YAAY,KAAK,YAAY,EAG5C,KAAK,SAAW,IAAI,GACtB,CASA,QAAS,CAEP,KAAK,aAAa,UAAY,GAC9B,KAAK,SAAS,MAAK,EAGnB,KAAK,YAAY,QAASC,GAAe,CAEvC,GAAIA,EAAW,OAAS,SAAW,CAACA,EAAW,OAAO,OACpD,OAIF,MAAMC,EAASD,EAAW,MAAM,OAAO,CAACE,EAAKC,IAASD,EAAMC,EAAK,EAAG,CAAC,EAGrEH,EAAW,MAAM,QAAQ,CAACG,EAAMC,IAAQ,CAEtC,MAAMC,EAAMC,EAAAA,cAAcH,EAAM,KAAK,QAAQ,EAGvCI,EAAQP,EAAW,MAAM,MAAM,EAAGI,CAAG,EAAE,OAAO,CAACF,EAAKM,IAAMN,EAAMM,EAAE,EAAG,CAAC,EACtEC,EAAWF,EAAQN,EACnBS,GAAUH,EAAQJ,EAAK,GAAKF,EAG5BU,EAAU,SAAS,cAAc,KAAK,EAC5CA,EAAQ,MAAM,SAAW,WACzBA,EAAQ,MAAM,KAAO,GAAGN,EAAI,IAAI,KAChCM,EAAQ,MAAM,IAAM,GAAGN,EAAI,GAAG,KAC9BM,EAAQ,MAAM,MAAQ,GAAGN,EAAI,KAAK,KAClCM,EAAQ,MAAM,OAAS,GAAGN,EAAI,MAAM,KACpCM,EAAQ,MAAM,SAAW,SACzBA,EAAQ,MAAM,aAAe,MAG7B,MAAMC,EAAY,SAAS,cAAc,KAAK,EAC9CA,EAAU,MAAM,MAAQ,OACxBA,EAAU,MAAM,OAAS,OACzBA,EAAU,MAAM,WAAaZ,GAAY,OAAO,OAAS,yBACzDY,EAAU,MAAM,QAAU,gCAC1BA,EAAU,MAAM,gBAAkB,cAClCA,EAAU,MAAM,UAAY,YAC5BA,EAAU,MAAM,WAAa,YAG7BD,EAAQ,YAAYC,CAAS,EAC7B,KAAK,aAAa,YAAYD,CAAO,EAGrC,MAAME,EAAM,GAAGb,EAAW,EAAE,IAAII,CAAG,GACnC,KAAK,SAAS,IAAIS,EAAK,CACrB,QAASD,EACT,QAASD,EACT,WAAYX,EACZ,SAAUS,EACV,OAAQC,CAClB,CAAS,CACH,CAAC,CACH,CAAC,CACH,CAWA,WAAWI,EAAQ,CACjB,MAAM,WAAWA,CAAM,EAEnB,MAAK,aAKT,KAAK,SAAS,QAAQ,CAAC,CAAE,QAAAC,EAAS,QAAAJ,EAAS,WAAAX,EAAY,SAAAS,EAAU,OAAAC,KAAa,CAE5E,GAAII,EAASd,EAAW,MACtBW,EAAQ,MAAM,QAAU,WACnB,CAELA,EAAQ,MAAM,QAAU,QAGxB,MAAMK,EAAiB,KAAK,IAC1B,EACA,KAAK,IACH,GACCF,EAASd,EAAW,OAAS,KAAK,IAAI,KAAMA,EAAW,IAAMA,EAAW,KAAK,CAC1F,CACA,EAGciB,EAAgB,KAAK,IACzB,EACA,KAAK,IACH,GACCD,EAAiBP,GAAY,KAAK,IAAI,KAAMC,EAASD,CAAQ,CAC1E,CACA,EAGQM,EAAQ,MAAM,UAAY,UAAUE,CAAa,GACnD,CACF,CAAC,CACH,CAOA,QAAS,CAET,CAOA,SAAU,CAER,KAAK,SAAS,MAAK,EACnB,KAAK,SAAW,KAGZ,KAAK,cAAgB,KAAK,aAAa,YACzC,KAAK,aAAa,WAAW,YAAY,KAAK,YAAY,EAE5D,KAAK,aAAe,KAGpB,MAAM,QAAO,CACf,CACF"}
package/dist/index7.js CHANGED
@@ -1,6 +1,6 @@
1
- import c from "./index6.js";
2
- import { rectNormToAbs as p } from "./index10.js";
3
- class g extends c {
1
+ import p from "./index6.js";
2
+ import { rectNormToAbs as c } from "./index10.js";
3
+ class f extends p {
4
4
  /**
5
5
  * Creates a new HighlightLayer instance
6
6
  *
@@ -10,8 +10,8 @@ class g extends c {
10
10
  * @param {number} viewport.height - Viewport height in pixels
11
11
  * @param {number} viewport.scale - PDF scale/zoom level
12
12
  */
13
- constructor(e, r) {
14
- super(e, r), this.layerElement = document.createElement("div"), this.layerElement.style.position = "absolute", this.layerElement.style.inset = "0", this.layerElement.style.pointerEvents = "none", this.layerElement.style.zIndex = "25", this.container.appendChild(this.layerElement), this.elements = /* @__PURE__ */ new Map(), this.rafId = null;
13
+ constructor(e, a) {
14
+ super(e, a), this.layerElement = document.createElement("div"), this.layerElement.style.position = "absolute", this.layerElement.style.inset = "0", this.layerElement.style.pointerEvents = "none", this.layerElement.style.zIndex = "25", this.container.appendChild(this.layerElement), this.elements = /* @__PURE__ */ new Map();
15
15
  }
16
16
  /**
17
17
  * Renders highlight elements for all annotations
@@ -24,18 +24,18 @@ class g extends c {
24
24
  this.layerElement.innerHTML = "", this.elements.clear(), this.annotations.forEach((e) => {
25
25
  if (e.mode !== "quads" || !e.quads?.length)
26
26
  return;
27
- const r = e.quads.reduce((a, i) => a + i.w, 0);
28
- e.quads.forEach((a, i) => {
29
- const s = p(a, this.viewport), n = e.quads.slice(0, i).reduce((o, y) => o + y.w, 0), h = n / r, d = (n + a.w) / r, t = document.createElement("div");
30
- t.style.position = "absolute", t.style.left = `${s.left}px`, t.style.top = `${s.top}px`, t.style.width = `${s.width}px`, t.style.height = `${s.height}px`, t.style.overflow = "hidden", t.style.borderRadius = "2px";
27
+ const a = e.quads.reduce((r, s) => r + s.w, 0);
28
+ e.quads.forEach((r, s) => {
29
+ const i = c(r, this.viewport), h = e.quads.slice(0, s).reduce((o, y) => o + y.w, 0), n = h / a, d = (h + r.w) / a, t = document.createElement("div");
30
+ t.style.position = "absolute", t.style.left = `${i.left}px`, t.style.top = `${i.top}px`, t.style.width = `${i.width}px`, t.style.height = `${i.height}px`, t.style.overflow = "hidden", t.style.borderRadius = "2px";
31
31
  const l = document.createElement("div");
32
32
  l.style.width = "100%", l.style.height = "100%", l.style.background = e?.style?.color ?? "rgba(255,230,100,0.35)", l.style.outline = "1px solid rgba(255,200,0,0.6)", l.style.transformOrigin = "left center", l.style.transform = "scaleX(0)", l.style.willChange = "transform", t.appendChild(l), this.layerElement.appendChild(t);
33
- const m = `${e.id}-${i}`;
33
+ const m = `${e.id}-${s}`;
34
34
  this.elements.set(m, {
35
35
  element: l,
36
36
  wrapper: t,
37
37
  annotation: e,
38
- segStart: h,
38
+ segStart: n,
39
39
  segEnd: d
40
40
  });
41
41
  });
@@ -44,38 +44,34 @@ class g extends c {
44
44
  /**
45
45
  * Updates highlight animations based on current timeline position
46
46
  *
47
- * Starts requestAnimationFrame loop to animate scaleX transform for
48
- * each highlight element. Calculates progress for each quad segment
49
- * and updates visibility.
47
+ * Updates scaleX transform for each highlight element based on timeline.
48
+ * Calculates progress for each quad segment and updates visibility.
49
+ * Renders once per call - no continuous loop.
50
50
  *
51
51
  * @param {number} nowSec - Current timeline position in seconds
52
52
  */
53
53
  updateTime(e) {
54
- super.updateTime(e), this.rafId && (cancelAnimationFrame(this.rafId), this.rafId = null);
55
- const r = () => {
56
- this.isDestroyed || (this.elements.forEach(({ element: a, wrapper: i, annotation: s, segStart: n, segEnd: h }) => {
57
- if (e < s.start)
58
- i.style.display = "none";
59
- else {
60
- i.style.display = "block";
61
- const d = Math.max(
62
- 0,
63
- Math.min(
64
- 1,
65
- (e - s.start) / Math.max(1e-6, s.end - s.start)
66
- )
67
- ), t = Math.max(
68
- 0,
69
- Math.min(
70
- 1,
71
- (d - n) / Math.max(1e-6, h - n)
72
- )
73
- );
74
- a.style.transform = `scaleX(${t})`;
75
- }
76
- }), this.rafId = requestAnimationFrame(r));
77
- };
78
- r();
54
+ super.updateTime(e), !this.isDestroyed && this.elements.forEach(({ element: a, wrapper: r, annotation: s, segStart: i, segEnd: h }) => {
55
+ if (e < s.start)
56
+ r.style.display = "none";
57
+ else {
58
+ r.style.display = "block";
59
+ const n = Math.max(
60
+ 0,
61
+ Math.min(
62
+ 1,
63
+ (e - s.start) / Math.max(1e-6, s.end - s.start)
64
+ )
65
+ ), d = Math.max(
66
+ 0,
67
+ Math.min(
68
+ 1,
69
+ (n - i) / Math.max(1e-6, h - i)
70
+ )
71
+ );
72
+ a.style.transform = `scaleX(${d})`;
73
+ }
74
+ });
79
75
  }
80
76
  /**
81
77
  * Updates the visual state of the layer
@@ -87,14 +83,13 @@ class g extends c {
87
83
  /**
88
84
  * Destroys the layer and releases all resources
89
85
  *
90
- * Cancels animation loop, clears element storage, removes DOM elements,
91
- * and calls parent cleanup.
86
+ * Clears element storage, removes DOM elements, and calls parent cleanup.
92
87
  */
93
88
  destroy() {
94
- this.rafId && (cancelAnimationFrame(this.rafId), this.rafId = null), this.elements.clear(), this.elements = null, this.layerElement && this.layerElement.parentNode && this.layerElement.parentNode.removeChild(this.layerElement), this.layerElement = null, super.destroy();
89
+ this.elements.clear(), this.elements = null, this.layerElement && this.layerElement.parentNode && this.layerElement.parentNode.removeChild(this.layerElement), this.layerElement = null, super.destroy();
95
90
  }
96
91
  }
97
92
  export {
98
- g as default
93
+ f as default
99
94
  };
100
95
  //# sourceMappingURL=index7.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index7.js","sources":["../src/layers/HighlightLayer.js"],"sourcesContent":["import BaseLayer from './BaseLayer.js';\nimport { rectNormToAbs } from '../utils/coordinateUtils.js';\n\n/**\n * HighlightLayer - Renders highlight annotations with progressive reveal\n *\n * Extends BaseLayer to render rectangular highlight regions (quads) with\n * progressive left-to-right scaleX animation based on timeline position.\n * Supports multi-line highlights with per-quad timing segments.\n *\n * @extends BaseLayer\n */\nclass HighlightLayer extends BaseLayer {\n /**\n * Creates a new HighlightLayer instance\n *\n * @param {HTMLElement} container - Parent DOM element for layer content\n * @param {Object} viewport - Initial viewport dimensions\n * @param {number} viewport.width - Viewport width in pixels\n * @param {number} viewport.height - Viewport height in pixels\n * @param {number} viewport.scale - PDF scale/zoom level\n */\n constructor(container, viewport) {\n super(container, viewport);\n\n // Create layer container element\n this.layerElement = document.createElement('div');\n this.layerElement.style.position = 'absolute';\n this.layerElement.style.inset = '0';\n this.layerElement.style.pointerEvents = 'none';\n this.layerElement.style.zIndex = '25';\n\n this.container.appendChild(this.layerElement);\n\n // Initialize element storage\n this.elements = new Map();\n\n // Initialize RAF ID\n this.rafId = null;\n }\n\n /**\n * Renders highlight elements for all annotations\n *\n * Creates DOM structure for each quad in each annotation. Calculates\n * timing segments for progressive animation. Clears and recreates all\n * elements when called.\n */\n render() {\n // Clear existing elements\n this.layerElement.innerHTML = '';\n this.elements.clear();\n\n // Process each annotation\n this.annotations.forEach((annotation) => {\n // Skip if not quad mode or no quads\n if (annotation.mode !== 'quads' || !annotation.quads?.length) {\n return;\n }\n\n // Calculate total width across all quads\n const totalW = annotation.quads.reduce((sum, quad) => sum + quad.w, 0);\n\n // Process each quad\n annotation.quads.forEach((quad, idx) => {\n // Convert normalized coordinates to absolute pixels\n const abs = rectNormToAbs(quad, this.viewport);\n\n // Calculate timing segment for this quad\n const prevW = annotation.quads.slice(0, idx).reduce((sum, q) => sum + q.w, 0);\n const segStart = prevW / totalW;\n const segEnd = (prevW + quad.w) / totalW;\n\n // Create wrapper div\n const wrapper = document.createElement('div');\n wrapper.style.position = 'absolute';\n wrapper.style.left = `${abs.left}px`;\n wrapper.style.top = `${abs.top}px`;\n wrapper.style.width = `${abs.width}px`;\n wrapper.style.height = `${abs.height}px`;\n wrapper.style.overflow = 'hidden';\n wrapper.style.borderRadius = '2px';\n\n // Create highlight div\n const highlight = document.createElement('div');\n highlight.style.width = '100%';\n highlight.style.height = '100%';\n highlight.style.background = annotation?.style?.color ?? 'rgba(255,230,100,0.35)';\n highlight.style.outline = '1px solid rgba(255,200,0,0.6)';\n highlight.style.transformOrigin = 'left center';\n highlight.style.transform = 'scaleX(0)';\n highlight.style.willChange = 'transform';\n\n // Assemble DOM structure\n wrapper.appendChild(highlight);\n this.layerElement.appendChild(wrapper);\n\n // Store reference for animation\n const key = `${annotation.id}-${idx}`;\n this.elements.set(key, {\n element: highlight,\n wrapper: wrapper,\n annotation: annotation,\n segStart: segStart,\n segEnd: segEnd\n });\n });\n });\n }\n\n /**\n * Updates highlight animations based on current timeline position\n *\n * Starts requestAnimationFrame loop to animate scaleX transform for\n * each highlight element. Calculates progress for each quad segment\n * and updates visibility.\n *\n * @param {number} nowSec - Current timeline position in seconds\n */\n updateTime(nowSec) {\n super.updateTime(nowSec);\n\n // Cancel existing RAF if running\n if (this.rafId) {\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n\n // Start animation loop\n const animate = () => {\n if (this.isDestroyed) {\n return;\n }\n\n // Update each highlight element\n this.elements.forEach(({ element, wrapper, annotation, segStart, segEnd }) => {\n // Hide wrapper if time hasn't reached annotation start\n if (nowSec < annotation.start) {\n wrapper.style.display = 'none';\n } else {\n // Show wrapper\n wrapper.style.display = 'block';\n\n // Calculate global progress (0 to 1)\n const globalProgress = Math.max(\n 0,\n Math.min(\n 1,\n (nowSec - annotation.start) / Math.max(1e-6, annotation.end - annotation.start)\n )\n );\n\n // Calculate local progress for this quad segment (0 to 1)\n const localProgress = Math.max(\n 0,\n Math.min(\n 1,\n (globalProgress - segStart) / Math.max(1e-6, segEnd - segStart)\n )\n );\n\n // Apply scaleX transform\n element.style.transform = `scaleX(${localProgress})`;\n }\n });\n\n // Schedule next frame\n this.rafId = requestAnimationFrame(animate);\n };\n\n animate();\n }\n\n /**\n * Updates the visual state of the layer\n *\n * Not used by HighlightLayer - animation handled in updateTime()\n */\n update() {\n // Not used - updateTime handles animation directly\n }\n\n /**\n * Destroys the layer and releases all resources\n *\n * Cancels animation loop, clears element storage, removes DOM elements,\n * and calls parent cleanup.\n */\n destroy() {\n // Cancel RAF if running\n if (this.rafId) {\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n\n // Clear element storage\n this.elements.clear();\n this.elements = null;\n\n // Remove layer element from DOM\n if (this.layerElement && this.layerElement.parentNode) {\n this.layerElement.parentNode.removeChild(this.layerElement);\n }\n this.layerElement = null;\n\n // Call parent destroy\n super.destroy();\n }\n}\n\nexport default HighlightLayer;\n"],"names":["HighlightLayer","BaseLayer","container","viewport","annotation","totalW","sum","quad","idx","abs","rectNormToAbs","prevW","q","segStart","segEnd","wrapper","highlight","key","nowSec","animate","element","globalProgress","localProgress"],"mappings":"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"}
1
+ {"version":3,"file":"index7.js","sources":["../src/layers/HighlightLayer.js"],"sourcesContent":["import BaseLayer from './BaseLayer.js';\nimport { rectNormToAbs } from '../utils/coordinateUtils.js';\n\n/**\n * HighlightLayer - Renders highlight annotations with progressive reveal\n *\n * Extends BaseLayer to render rectangular highlight regions (quads) with\n * progressive left-to-right scaleX animation based on timeline position.\n * Supports multi-line highlights with per-quad timing segments.\n *\n * @extends BaseLayer\n */\nclass HighlightLayer extends BaseLayer {\n /**\n * Creates a new HighlightLayer instance\n *\n * @param {HTMLElement} container - Parent DOM element for layer content\n * @param {Object} viewport - Initial viewport dimensions\n * @param {number} viewport.width - Viewport width in pixels\n * @param {number} viewport.height - Viewport height in pixels\n * @param {number} viewport.scale - PDF scale/zoom level\n */\n constructor(container, viewport) {\n super(container, viewport);\n\n // Create layer container element\n this.layerElement = document.createElement('div');\n this.layerElement.style.position = 'absolute';\n this.layerElement.style.inset = '0';\n this.layerElement.style.pointerEvents = 'none';\n this.layerElement.style.zIndex = '25';\n\n this.container.appendChild(this.layerElement);\n\n // Initialize element storage\n this.elements = new Map();\n }\n\n /**\n * Renders highlight elements for all annotations\n *\n * Creates DOM structure for each quad in each annotation. Calculates\n * timing segments for progressive animation. Clears and recreates all\n * elements when called.\n */\n render() {\n // Clear existing elements\n this.layerElement.innerHTML = '';\n this.elements.clear();\n\n // Process each annotation\n this.annotations.forEach((annotation) => {\n // Skip if not quad mode or no quads\n if (annotation.mode !== 'quads' || !annotation.quads?.length) {\n return;\n }\n\n // Calculate total width across all quads\n const totalW = annotation.quads.reduce((sum, quad) => sum + quad.w, 0);\n\n // Process each quad\n annotation.quads.forEach((quad, idx) => {\n // Convert normalized coordinates to absolute pixels\n const abs = rectNormToAbs(quad, this.viewport);\n\n // Calculate timing segment for this quad\n const prevW = annotation.quads.slice(0, idx).reduce((sum, q) => sum + q.w, 0);\n const segStart = prevW / totalW;\n const segEnd = (prevW + quad.w) / totalW;\n\n // Create wrapper div\n const wrapper = document.createElement('div');\n wrapper.style.position = 'absolute';\n wrapper.style.left = `${abs.left}px`;\n wrapper.style.top = `${abs.top}px`;\n wrapper.style.width = `${abs.width}px`;\n wrapper.style.height = `${abs.height}px`;\n wrapper.style.overflow = 'hidden';\n wrapper.style.borderRadius = '2px';\n\n // Create highlight div\n const highlight = document.createElement('div');\n highlight.style.width = '100%';\n highlight.style.height = '100%';\n highlight.style.background = annotation?.style?.color ?? 'rgba(255,230,100,0.35)';\n highlight.style.outline = '1px solid rgba(255,200,0,0.6)';\n highlight.style.transformOrigin = 'left center';\n highlight.style.transform = 'scaleX(0)';\n highlight.style.willChange = 'transform';\n\n // Assemble DOM structure\n wrapper.appendChild(highlight);\n this.layerElement.appendChild(wrapper);\n\n // Store reference for animation\n const key = `${annotation.id}-${idx}`;\n this.elements.set(key, {\n element: highlight,\n wrapper: wrapper,\n annotation: annotation,\n segStart: segStart,\n segEnd: segEnd\n });\n });\n });\n }\n\n /**\n * Updates highlight animations based on current timeline position\n *\n * Updates scaleX transform for each highlight element based on timeline.\n * Calculates progress for each quad segment and updates visibility.\n * Renders once per call - no continuous loop.\n *\n * @param {number} nowSec - Current timeline position in seconds\n */\n updateTime(nowSec) {\n super.updateTime(nowSec);\n\n if (this.isDestroyed) {\n return;\n }\n\n // Update each highlight element\n this.elements.forEach(({ element, wrapper, annotation, segStart, segEnd }) => {\n // Hide wrapper if time hasn't reached annotation start\n if (nowSec < annotation.start) {\n wrapper.style.display = 'none';\n } else {\n // Show wrapper\n wrapper.style.display = 'block';\n\n // Calculate global progress (0 to 1)\n const globalProgress = Math.max(\n 0,\n Math.min(\n 1,\n (nowSec - annotation.start) / Math.max(1e-6, annotation.end - annotation.start)\n )\n );\n\n // Calculate local progress for this quad segment (0 to 1)\n const localProgress = Math.max(\n 0,\n Math.min(\n 1,\n (globalProgress - segStart) / Math.max(1e-6, segEnd - segStart)\n )\n );\n\n // Apply scaleX transform\n element.style.transform = `scaleX(${localProgress})`;\n }\n });\n }\n\n /**\n * Updates the visual state of the layer\n *\n * Not used by HighlightLayer - animation handled in updateTime()\n */\n update() {\n // Not used - updateTime handles animation directly\n }\n\n /**\n * Destroys the layer and releases all resources\n *\n * Clears element storage, removes DOM elements, and calls parent cleanup.\n */\n destroy() {\n // Clear element storage\n this.elements.clear();\n this.elements = null;\n\n // Remove layer element from DOM\n if (this.layerElement && this.layerElement.parentNode) {\n this.layerElement.parentNode.removeChild(this.layerElement);\n }\n this.layerElement = null;\n\n // Call parent destroy\n super.destroy();\n }\n}\n\nexport default HighlightLayer;\n"],"names":["HighlightLayer","BaseLayer","container","viewport","annotation","totalW","sum","quad","idx","abs","rectNormToAbs","prevW","q","segStart","segEnd","wrapper","highlight","key","nowSec","element","globalProgress","localProgress"],"mappings":"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"}
package/dist/index9.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const c=require("./index6.cjs");class d extends c.default{constructor(t,s){super(t,s),this.canvasElement=document.createElement("canvas"),this.canvasElement.style.position="absolute",this.canvasElement.style.inset="0",this.canvasElement.style.pointerEvents="none",this.canvasElement.style.zIndex="40",this.container.appendChild(this.canvasElement),this.ctx=this.canvasElement.getContext("2d"),this.rafId=null,this._setupCanvas()}_setupCanvas(){const t=window.devicePixelRatio||1;this.canvasElement.width=Math.round(this.viewport.width*t),this.canvasElement.height=Math.round(this.viewport.height*t),this.canvasElement.style.width=`${this.viewport.width}px`,this.canvasElement.style.height=`${this.viewport.height}px`,this.ctx.setTransform(t,0,0,t,0,0)}setViewport(t){super.setViewport(t),this._setupCanvas()}updateTime(t){super.updateTime(t),this.rafId&&cancelAnimationFrame(this.rafId);const s=()=>{if(!this.isDestroyed){this.ctx.clearRect(0,0,this.canvasElement.width,this.canvasElement.height);for(const e of this.annotations){if(t<e.start)continue;const o=e.end-e.start,l=Math.min(t-e.start,o);for(const i of e.strokes||[]){this.ctx.lineCap="round",this.ctx.lineJoin="round",this.ctx.strokeStyle=i.color||"#1f2937",this.ctx.lineWidth=i.size||3,this.ctx.beginPath();let n=!1;for(const a of i.points){if(a.t>l)break;const h=a.x*this.viewport.width,r=a.y*this.viewport.height;n?this.ctx.lineTo(h,r):(this.ctx.moveTo(h,r),n=!0)}n&&this.ctx.stroke()}}this.rafId=requestAnimationFrame(s)}};s()}render(){}update(){}destroy(){this.rafId&&(cancelAnimationFrame(this.rafId),this.rafId=null),this.ctx=null,this.canvasElement&&this.canvasElement.parentNode&&this.canvasElement.parentNode.removeChild(this.canvasElement),this.canvasElement=null,super.destroy()}}exports.default=d;
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const l=require("./index6.cjs");class c extends l.default{constructor(t,e){super(t,e),this.canvasElement=document.createElement("canvas"),this.canvasElement.style.position="absolute",this.canvasElement.style.inset="0",this.canvasElement.style.pointerEvents="none",this.canvasElement.style.zIndex="40",this.container.appendChild(this.canvasElement),this.ctx=this.canvasElement.getContext("2d"),this._setupCanvas()}_setupCanvas(){const t=window.devicePixelRatio||1;this.canvasElement.width=Math.round(this.viewport.width*t),this.canvasElement.height=Math.round(this.viewport.height*t),this.canvasElement.style.width=`${this.viewport.width}px`,this.canvasElement.style.height=`${this.viewport.height}px`,this.ctx.setTransform(t,0,0,t,0,0)}setViewport(t){super.setViewport(t),this._setupCanvas()}updateTime(t){if(super.updateTime(t),!this.isDestroyed){this.ctx.clearRect(0,0,this.canvasElement.width,this.canvasElement.height);for(const e of this.annotations){if(t<e.start)continue;const o=e.end-e.start,r=Math.min(t-e.start,o);for(const s of e.strokes||[]){this.ctx.lineCap="round",this.ctx.lineJoin="round",this.ctx.strokeStyle=s.color||"#1f2937",this.ctx.lineWidth=s.size||3,this.ctx.beginPath();let i=!1;for(const n of s.points){if(n.t>r)break;const a=n.x*this.viewport.width,h=n.y*this.viewport.height;i?this.ctx.lineTo(a,h):(this.ctx.moveTo(a,h),i=!0)}i&&this.ctx.stroke()}}}}render(){}update(){}destroy(){this.ctx=null,this.canvasElement&&this.canvasElement.parentNode&&this.canvasElement.parentNode.removeChild(this.canvasElement),this.canvasElement=null,super.destroy()}}exports.default=c;
2
2
  //# sourceMappingURL=index9.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index9.cjs","sources":["../src/layers/DrawingLayer.js"],"sourcesContent":["import BaseLayer from './BaseLayer.js';\n\n/**\n * DrawingLayer - Renders ink/drawing annotations on HTML canvas\n *\n * Extends BaseLayer to provide progressive stroke animation for ink annotations.\n * Draws stroke points incrementally based on timeline position using requestAnimationFrame.\n * Handles device pixel ratio scaling for crisp rendering on high-DPI displays.\n *\n * Features:\n * - Progressive stroke drawing point-by-point\n * - Multiple strokes per annotation with custom colors/sizes\n * - Device pixel ratio handling for Retina displays\n * - Smooth 60fps animation with RAF\n * - Efficient canvas clear/redraw cycle\n *\n * @extends BaseLayer\n */\nclass DrawingLayer extends BaseLayer {\n /**\n * Creates a new DrawingLayer instance\n *\n * @param {HTMLElement} container - Parent DOM element for layer content\n * @param {Object} viewport - Initial viewport dimensions\n * @param {number} viewport.width - Viewport width in pixels\n * @param {number} viewport.height - Viewport height in pixels\n * @param {number} viewport.scale - PDF scale/zoom level\n */\n constructor(container, viewport) {\n super(container, viewport);\n\n // Create canvas element\n this.canvasElement = document.createElement('canvas');\n this.canvasElement.style.position = 'absolute';\n this.canvasElement.style.inset = '0';\n this.canvasElement.style.pointerEvents = 'none';\n this.canvasElement.style.zIndex = '40';\n\n // Append to container\n this.container.appendChild(this.canvasElement);\n\n // Get 2D context\n this.ctx = this.canvasElement.getContext('2d');\n\n // Initialize animation frame ID\n this.rafId = null;\n\n // Setup canvas with device pixel ratio\n this._setupCanvas();\n }\n\n /**\n * Configures canvas dimensions with device pixel ratio scaling\n *\n * Sets canvas buffer size for high-resolution rendering on Retina displays\n * while maintaining correct display size in CSS pixels. Scales context\n * transform to allow drawing with CSS pixel coordinates.\n *\n * @private\n */\n _setupCanvas() {\n const dpr = window.devicePixelRatio || 1;\n\n // Set canvas buffer resolution (high-res for crisp rendering)\n this.canvasElement.width = Math.round(this.viewport.width * dpr);\n this.canvasElement.height = Math.round(this.viewport.height * dpr);\n\n // Set canvas display size (CSS pixels)\n this.canvasElement.style.width = `${this.viewport.width}px`;\n this.canvasElement.style.height = `${this.viewport.height}px`;\n\n // Scale context to account for device pixel ratio\n this.ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n }\n\n /**\n * Updates viewport dimensions and resizes canvas\n *\n * Reconfigures canvas buffer and display size when viewport changes\n * due to page navigation or zoom operations.\n *\n * @param {Object} viewport - New viewport dimensions\n * @param {number} viewport.width - Viewport width in pixels\n * @param {number} viewport.height - Viewport height in pixels\n * @param {number} viewport.scale - PDF scale/zoom level\n * @override\n */\n setViewport(viewport) {\n super.setViewport(viewport);\n this._setupCanvas();\n }\n\n /**\n * Updates timeline position and starts progressive stroke drawing\n *\n * Cancels any existing animation loop and starts a new requestAnimationFrame\n * loop to redraw the canvas with strokes progressively drawn based on elapsed time.\n * Each frame clears the canvas and redraws all visible strokes.\n *\n * @param {number} nowSec - Current timeline position in seconds\n * @throws {Error} If called after layer is destroyed\n * @override\n */\n updateTime(nowSec) {\n super.updateTime(nowSec);\n\n // Cancel existing RAF to prevent multiple loops\n if (this.rafId) {\n cancelAnimationFrame(this.rafId);\n }\n\n // Start drawing loop\n const draw = () => {\n // Check destroyed state\n if (this.isDestroyed) return;\n\n // Clear canvas\n this.ctx.clearRect(0, 0, this.canvasElement.width, this.canvasElement.height);\n\n // Draw each annotation\n for (const a of this.annotations) {\n // Skip annotations that haven't started yet\n if (nowSec < a.start) continue;\n\n // Calculate elapsed time (capped at duration for persistence)\n const duration = a.end - a.start;\n const elapsed = Math.min(nowSec - a.start, duration);\n\n // Draw each stroke\n for (const stroke of (a.strokes || [])) {\n // Configure stroke style\n this.ctx.lineCap = 'round';\n this.ctx.lineJoin = 'round';\n this.ctx.strokeStyle = stroke.color || '#1f2937';\n this.ctx.lineWidth = stroke.size || 3;\n this.ctx.beginPath();\n\n let started = false;\n\n // Draw points up to current time\n for (const point of stroke.points) {\n // Skip points that haven't been drawn yet\n if (point.t > elapsed) break;\n\n // Convert normalized coordinates to canvas pixels\n const x = point.x * this.viewport.width;\n const y = point.y * this.viewport.height;\n\n if (!started) {\n this.ctx.moveTo(x, y);\n started = true;\n } else {\n this.ctx.lineTo(x, y);\n }\n }\n\n // Render the stroke\n if (started) {\n this.ctx.stroke();\n }\n }\n }\n\n // Schedule next frame\n this.rafId = requestAnimationFrame(draw);\n };\n\n // Start the loop\n draw();\n }\n\n /**\n * Renders the layer content\n *\n * No-op for DrawingLayer - canvas rendering happens in updateTime() RAF loop.\n * Canvas element is created once in constructor and drawn to continuously.\n *\n * @override\n */\n render() {\n // No-op: Canvas rendering happens in updateTime() RAF loop\n // Canvas element is created once in constructor\n }\n\n /**\n * Updates the visual state of the layer\n *\n * Not used for DrawingLayer - updateTime() handles updates via RAF loop.\n *\n * @override\n */\n update() {\n // Not used - updateTime handles drawing via RAF loop\n }\n\n /**\n * Destroys the layer and releases resources\n *\n * Cancels animation loop, clears references, and removes canvas from DOM.\n * Safe to call multiple times (idempotent).\n *\n * @override\n */\n destroy() {\n // Cancel animation loop first\n if (this.rafId) {\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n\n // Clear context reference\n this.ctx = null;\n\n // Remove canvas from DOM\n if (this.canvasElement && this.canvasElement.parentNode) {\n this.canvasElement.parentNode.removeChild(this.canvasElement);\n }\n this.canvasElement = null;\n\n // Call parent cleanup (always last)\n super.destroy();\n }\n}\n\nexport default DrawingLayer;\n"],"names":["DrawingLayer","BaseLayer","container","viewport","dpr","nowSec","draw","a","duration","elapsed","stroke","started","point","x","y"],"mappings":"4IAkBA,MAAMA,UAAqBC,EAAAA,OAAU,CAUnC,YAAYC,EAAWC,EAAU,CAC/B,MAAMD,EAAWC,CAAQ,EAGzB,KAAK,cAAgB,SAAS,cAAc,QAAQ,EACpD,KAAK,cAAc,MAAM,SAAW,WACpC,KAAK,cAAc,MAAM,MAAQ,IACjC,KAAK,cAAc,MAAM,cAAgB,OACzC,KAAK,cAAc,MAAM,OAAS,KAGlC,KAAK,UAAU,YAAY,KAAK,aAAa,EAG7C,KAAK,IAAM,KAAK,cAAc,WAAW,IAAI,EAG7C,KAAK,MAAQ,KAGb,KAAK,aAAY,CACnB,CAWA,cAAe,CACb,MAAMC,EAAM,OAAO,kBAAoB,EAGvC,KAAK,cAAc,MAAQ,KAAK,MAAM,KAAK,SAAS,MAAQA,CAAG,EAC/D,KAAK,cAAc,OAAS,KAAK,MAAM,KAAK,SAAS,OAASA,CAAG,EAGjE,KAAK,cAAc,MAAM,MAAQ,GAAG,KAAK,SAAS,KAAK,KACvD,KAAK,cAAc,MAAM,OAAS,GAAG,KAAK,SAAS,MAAM,KAGzD,KAAK,IAAI,aAAaA,EAAK,EAAG,EAAGA,EAAK,EAAG,CAAC,CAC5C,CAcA,YAAYD,EAAU,CACpB,MAAM,YAAYA,CAAQ,EAC1B,KAAK,aAAY,CACnB,CAaA,WAAWE,EAAQ,CACjB,MAAM,WAAWA,CAAM,EAGnB,KAAK,OACP,qBAAqB,KAAK,KAAK,EAIjC,MAAMC,EAAO,IAAM,CAEjB,GAAI,MAAK,YAGT,MAAK,IAAI,UAAU,EAAG,EAAG,KAAK,cAAc,MAAO,KAAK,cAAc,MAAM,EAG5E,UAAWC,KAAK,KAAK,YAAa,CAEhC,GAAIF,EAASE,EAAE,MAAO,SAGtB,MAAMC,EAAWD,EAAE,IAAMA,EAAE,MACrBE,EAAU,KAAK,IAAIJ,EAASE,EAAE,MAAOC,CAAQ,EAGnD,UAAWE,KAAWH,EAAE,SAAW,CAAA,EAAK,CAEtC,KAAK,IAAI,QAAU,QACnB,KAAK,IAAI,SAAW,QACpB,KAAK,IAAI,YAAcG,EAAO,OAAS,UACvC,KAAK,IAAI,UAAYA,EAAO,MAAQ,EACpC,KAAK,IAAI,UAAS,EAElB,IAAIC,EAAU,GAGd,UAAWC,KAASF,EAAO,OAAQ,CAEjC,GAAIE,EAAM,EAAIH,EAAS,MAGvB,MAAMI,EAAID,EAAM,EAAI,KAAK,SAAS,MAC5BE,EAAIF,EAAM,EAAI,KAAK,SAAS,OAE7BD,EAIH,KAAK,IAAI,OAAOE,EAAGC,CAAC,GAHpB,KAAK,IAAI,OAAOD,EAAGC,CAAC,EACpBH,EAAU,GAId,CAGIA,GACF,KAAK,IAAI,OAAM,CAEnB,CACF,CAGA,KAAK,MAAQ,sBAAsBL,CAAI,EACzC,EAGAA,EAAI,CACN,CAUA,QAAS,CAGT,CASA,QAAS,CAET,CAUA,SAAU,CAEJ,KAAK,QACP,qBAAqB,KAAK,KAAK,EAC/B,KAAK,MAAQ,MAIf,KAAK,IAAM,KAGP,KAAK,eAAiB,KAAK,cAAc,YAC3C,KAAK,cAAc,WAAW,YAAY,KAAK,aAAa,EAE9D,KAAK,cAAgB,KAGrB,MAAM,QAAO,CACf,CACF"}
1
+ {"version":3,"file":"index9.cjs","sources":["../src/layers/DrawingLayer.js"],"sourcesContent":["import BaseLayer from './BaseLayer.js';\n\n/**\n * DrawingLayer - Renders ink/drawing annotations on HTML canvas\n *\n * Extends BaseLayer to provide progressive stroke animation for ink annotations.\n * Draws stroke points incrementally based on timeline position using requestAnimationFrame.\n * Handles device pixel ratio scaling for crisp rendering on high-DPI displays.\n *\n * Features:\n * - Progressive stroke drawing point-by-point\n * - Multiple strokes per annotation with custom colors/sizes\n * - Device pixel ratio handling for Retina displays\n * - Smooth 60fps animation with RAF\n * - Efficient canvas clear/redraw cycle\n *\n * @extends BaseLayer\n */\nclass DrawingLayer extends BaseLayer {\n /**\n * Creates a new DrawingLayer instance\n *\n * @param {HTMLElement} container - Parent DOM element for layer content\n * @param {Object} viewport - Initial viewport dimensions\n * @param {number} viewport.width - Viewport width in pixels\n * @param {number} viewport.height - Viewport height in pixels\n * @param {number} viewport.scale - PDF scale/zoom level\n */\n constructor(container, viewport) {\n super(container, viewport);\n\n // Create canvas element\n this.canvasElement = document.createElement('canvas');\n this.canvasElement.style.position = 'absolute';\n this.canvasElement.style.inset = '0';\n this.canvasElement.style.pointerEvents = 'none';\n this.canvasElement.style.zIndex = '40';\n\n // Append to container\n this.container.appendChild(this.canvasElement);\n\n // Get 2D context\n this.ctx = this.canvasElement.getContext('2d');\n\n // Setup canvas with device pixel ratio\n this._setupCanvas();\n }\n\n /**\n * Configures canvas dimensions with device pixel ratio scaling\n *\n * Sets canvas buffer size for high-resolution rendering on Retina displays\n * while maintaining correct display size in CSS pixels. Scales context\n * transform to allow drawing with CSS pixel coordinates.\n *\n * @private\n */\n _setupCanvas() {\n const dpr = window.devicePixelRatio || 1;\n\n // Set canvas buffer resolution (high-res for crisp rendering)\n this.canvasElement.width = Math.round(this.viewport.width * dpr);\n this.canvasElement.height = Math.round(this.viewport.height * dpr);\n\n // Set canvas display size (CSS pixels)\n this.canvasElement.style.width = `${this.viewport.width}px`;\n this.canvasElement.style.height = `${this.viewport.height}px`;\n\n // Scale context to account for device pixel ratio\n this.ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n }\n\n /**\n * Updates viewport dimensions and resizes canvas\n *\n * Reconfigures canvas buffer and display size when viewport changes\n * due to page navigation or zoom operations.\n *\n * @param {Object} viewport - New viewport dimensions\n * @param {number} viewport.width - Viewport width in pixels\n * @param {number} viewport.height - Viewport height in pixels\n * @param {number} viewport.scale - PDF scale/zoom level\n * @override\n */\n setViewport(viewport) {\n super.setViewport(viewport);\n this._setupCanvas();\n }\n\n /**\n * Updates timeline position and draws progressive strokes\n *\n * Redraws the canvas with strokes progressively drawn based on elapsed time.\n * Clears the canvas and redraws all visible strokes.\n * Renders once per call - no continuous loop.\n *\n * @param {number} nowSec - Current timeline position in seconds\n * @throws {Error} If called after layer is destroyed\n * @override\n */\n updateTime(nowSec) {\n super.updateTime(nowSec);\n\n // Check destroyed state\n if (this.isDestroyed) return;\n\n // Clear canvas\n this.ctx.clearRect(0, 0, this.canvasElement.width, this.canvasElement.height);\n\n // Draw each annotation\n for (const a of this.annotations) {\n // Skip annotations that haven't started yet\n if (nowSec < a.start) continue;\n\n // Calculate elapsed time (capped at duration for persistence)\n const duration = a.end - a.start;\n const elapsed = Math.min(nowSec - a.start, duration);\n\n // Draw each stroke\n for (const stroke of (a.strokes || [])) {\n // Configure stroke style\n this.ctx.lineCap = 'round';\n this.ctx.lineJoin = 'round';\n this.ctx.strokeStyle = stroke.color || '#1f2937';\n this.ctx.lineWidth = stroke.size || 3;\n this.ctx.beginPath();\n\n let started = false;\n\n // Draw points up to current time\n for (const point of stroke.points) {\n // Skip points that haven't been drawn yet\n if (point.t > elapsed) break;\n\n // Convert normalized coordinates to canvas pixels\n const x = point.x * this.viewport.width;\n const y = point.y * this.viewport.height;\n\n if (!started) {\n this.ctx.moveTo(x, y);\n started = true;\n } else {\n this.ctx.lineTo(x, y);\n }\n }\n\n // Render the stroke\n if (started) {\n this.ctx.stroke();\n }\n }\n }\n }\n\n /**\n * Renders the layer content\n *\n * No-op for DrawingLayer - canvas rendering happens in updateTime().\n * Canvas element is created once in constructor.\n *\n * @override\n */\n render() {\n // No-op: Canvas rendering happens in updateTime()\n // Canvas element is created once in constructor\n }\n\n /**\n * Updates the visual state of the layer\n *\n * Not used for DrawingLayer - updateTime() handles drawing directly.\n *\n * @override\n */\n update() {\n // Not used - updateTime handles drawing directly\n }\n\n /**\n * Destroys the layer and releases resources\n *\n * Clears references and removes canvas from DOM.\n * Safe to call multiple times (idempotent).\n *\n * @override\n */\n destroy() {\n // Clear context reference\n this.ctx = null;\n\n // Remove canvas from DOM\n if (this.canvasElement && this.canvasElement.parentNode) {\n this.canvasElement.parentNode.removeChild(this.canvasElement);\n }\n this.canvasElement = null;\n\n // Call parent cleanup (always last)\n super.destroy();\n }\n}\n\nexport default DrawingLayer;\n"],"names":["DrawingLayer","BaseLayer","container","viewport","dpr","nowSec","a","duration","elapsed","stroke","started","point","x","y"],"mappings":"4IAkBA,MAAMA,UAAqBC,EAAAA,OAAU,CAUnC,YAAYC,EAAWC,EAAU,CAC/B,MAAMD,EAAWC,CAAQ,EAGzB,KAAK,cAAgB,SAAS,cAAc,QAAQ,EACpD,KAAK,cAAc,MAAM,SAAW,WACpC,KAAK,cAAc,MAAM,MAAQ,IACjC,KAAK,cAAc,MAAM,cAAgB,OACzC,KAAK,cAAc,MAAM,OAAS,KAGlC,KAAK,UAAU,YAAY,KAAK,aAAa,EAG7C,KAAK,IAAM,KAAK,cAAc,WAAW,IAAI,EAG7C,KAAK,aAAY,CACnB,CAWA,cAAe,CACb,MAAMC,EAAM,OAAO,kBAAoB,EAGvC,KAAK,cAAc,MAAQ,KAAK,MAAM,KAAK,SAAS,MAAQA,CAAG,EAC/D,KAAK,cAAc,OAAS,KAAK,MAAM,KAAK,SAAS,OAASA,CAAG,EAGjE,KAAK,cAAc,MAAM,MAAQ,GAAG,KAAK,SAAS,KAAK,KACvD,KAAK,cAAc,MAAM,OAAS,GAAG,KAAK,SAAS,MAAM,KAGzD,KAAK,IAAI,aAAaA,EAAK,EAAG,EAAGA,EAAK,EAAG,CAAC,CAC5C,CAcA,YAAYD,EAAU,CACpB,MAAM,YAAYA,CAAQ,EAC1B,KAAK,aAAY,CACnB,CAaA,WAAWE,EAAQ,CAIjB,GAHA,MAAM,WAAWA,CAAM,EAGnB,MAAK,YAGT,MAAK,IAAI,UAAU,EAAG,EAAG,KAAK,cAAc,MAAO,KAAK,cAAc,MAAM,EAG5E,UAAWC,KAAK,KAAK,YAAa,CAEhC,GAAID,EAASC,EAAE,MAAO,SAGtB,MAAMC,EAAWD,EAAE,IAAMA,EAAE,MACrBE,EAAU,KAAK,IAAIH,EAASC,EAAE,MAAOC,CAAQ,EAGnD,UAAWE,KAAWH,EAAE,SAAW,CAAA,EAAK,CAEtC,KAAK,IAAI,QAAU,QACnB,KAAK,IAAI,SAAW,QACpB,KAAK,IAAI,YAAcG,EAAO,OAAS,UACvC,KAAK,IAAI,UAAYA,EAAO,MAAQ,EACpC,KAAK,IAAI,UAAS,EAElB,IAAIC,EAAU,GAGd,UAAWC,KAASF,EAAO,OAAQ,CAEjC,GAAIE,EAAM,EAAIH,EAAS,MAGvB,MAAMI,EAAID,EAAM,EAAI,KAAK,SAAS,MAC5BE,EAAIF,EAAM,EAAI,KAAK,SAAS,OAE7BD,EAIH,KAAK,IAAI,OAAOE,EAAGC,CAAC,GAHpB,KAAK,IAAI,OAAOD,EAAGC,CAAC,EACpBH,EAAU,GAId,CAGIA,GACF,KAAK,IAAI,OAAM,CAEnB,CACF,EACF,CAUA,QAAS,CAGT,CASA,QAAS,CAET,CAUA,SAAU,CAER,KAAK,IAAM,KAGP,KAAK,eAAiB,KAAK,cAAc,YAC3C,KAAK,cAAc,WAAW,YAAY,KAAK,aAAa,EAE9D,KAAK,cAAgB,KAGrB,MAAM,QAAO,CACf,CACF"}
package/dist/index9.js CHANGED
@@ -1,5 +1,5 @@
1
- import l from "./index6.js";
2
- class p extends l {
1
+ import c from "./index6.js";
2
+ class p extends c {
3
3
  /**
4
4
  * Creates a new DrawingLayer instance
5
5
  *
@@ -9,8 +9,8 @@ class p extends l {
9
9
  * @param {number} viewport.height - Viewport height in pixels
10
10
  * @param {number} viewport.scale - PDF scale/zoom level
11
11
  */
12
- constructor(t, s) {
13
- super(t, s), this.canvasElement = document.createElement("canvas"), this.canvasElement.style.position = "absolute", this.canvasElement.style.inset = "0", this.canvasElement.style.pointerEvents = "none", this.canvasElement.style.zIndex = "40", this.container.appendChild(this.canvasElement), this.ctx = this.canvasElement.getContext("2d"), this.rafId = null, this._setupCanvas();
12
+ constructor(t, e) {
13
+ super(t, e), this.canvasElement = document.createElement("canvas"), this.canvasElement.style.position = "absolute", this.canvasElement.style.inset = "0", this.canvasElement.style.pointerEvents = "none", this.canvasElement.style.zIndex = "40", this.container.appendChild(this.canvasElement), this.ctx = this.canvasElement.getContext("2d"), this._setupCanvas();
14
14
  }
15
15
  /**
16
16
  * Configures canvas dimensions with device pixel ratio scaling
@@ -41,45 +41,40 @@ class p extends l {
41
41
  super.setViewport(t), this._setupCanvas();
42
42
  }
43
43
  /**
44
- * Updates timeline position and starts progressive stroke drawing
44
+ * Updates timeline position and draws progressive strokes
45
45
  *
46
- * Cancels any existing animation loop and starts a new requestAnimationFrame
47
- * loop to redraw the canvas with strokes progressively drawn based on elapsed time.
48
- * Each frame clears the canvas and redraws all visible strokes.
46
+ * Redraws the canvas with strokes progressively drawn based on elapsed time.
47
+ * Clears the canvas and redraws all visible strokes.
48
+ * Renders once per call - no continuous loop.
49
49
  *
50
50
  * @param {number} nowSec - Current timeline position in seconds
51
51
  * @throws {Error} If called after layer is destroyed
52
52
  * @override
53
53
  */
54
54
  updateTime(t) {
55
- super.updateTime(t), this.rafId && cancelAnimationFrame(this.rafId);
56
- const s = () => {
57
- if (!this.isDestroyed) {
58
- this.ctx.clearRect(0, 0, this.canvasElement.width, this.canvasElement.height);
59
- for (const e of this.annotations) {
60
- if (t < e.start) continue;
61
- const o = e.end - e.start, c = Math.min(t - e.start, o);
62
- for (const i of e.strokes || []) {
63
- this.ctx.lineCap = "round", this.ctx.lineJoin = "round", this.ctx.strokeStyle = i.color || "#1f2937", this.ctx.lineWidth = i.size || 3, this.ctx.beginPath();
64
- let n = !1;
65
- for (const a of i.points) {
66
- if (a.t > c) break;
67
- const h = a.x * this.viewport.width, r = a.y * this.viewport.height;
68
- n ? this.ctx.lineTo(h, r) : (this.ctx.moveTo(h, r), n = !0);
69
- }
70
- n && this.ctx.stroke();
55
+ if (super.updateTime(t), !this.isDestroyed) {
56
+ this.ctx.clearRect(0, 0, this.canvasElement.width, this.canvasElement.height);
57
+ for (const e of this.annotations) {
58
+ if (t < e.start) continue;
59
+ const o = e.end - e.start, r = Math.min(t - e.start, o);
60
+ for (const s of e.strokes || []) {
61
+ this.ctx.lineCap = "round", this.ctx.lineJoin = "round", this.ctx.strokeStyle = s.color || "#1f2937", this.ctx.lineWidth = s.size || 3, this.ctx.beginPath();
62
+ let i = !1;
63
+ for (const n of s.points) {
64
+ if (n.t > r) break;
65
+ const a = n.x * this.viewport.width, h = n.y * this.viewport.height;
66
+ i ? this.ctx.lineTo(a, h) : (this.ctx.moveTo(a, h), i = !0);
71
67
  }
68
+ i && this.ctx.stroke();
72
69
  }
73
- this.rafId = requestAnimationFrame(s);
74
70
  }
75
- };
76
- s();
71
+ }
77
72
  }
78
73
  /**
79
74
  * Renders the layer content
80
75
  *
81
- * No-op for DrawingLayer - canvas rendering happens in updateTime() RAF loop.
82
- * Canvas element is created once in constructor and drawn to continuously.
76
+ * No-op for DrawingLayer - canvas rendering happens in updateTime().
77
+ * Canvas element is created once in constructor.
83
78
  *
84
79
  * @override
85
80
  */
@@ -88,7 +83,7 @@ class p extends l {
88
83
  /**
89
84
  * Updates the visual state of the layer
90
85
  *
91
- * Not used for DrawingLayer - updateTime() handles updates via RAF loop.
86
+ * Not used for DrawingLayer - updateTime() handles drawing directly.
92
87
  *
93
88
  * @override
94
89
  */
@@ -97,13 +92,13 @@ class p extends l {
97
92
  /**
98
93
  * Destroys the layer and releases resources
99
94
  *
100
- * Cancels animation loop, clears references, and removes canvas from DOM.
95
+ * Clears references and removes canvas from DOM.
101
96
  * Safe to call multiple times (idempotent).
102
97
  *
103
98
  * @override
104
99
  */
105
100
  destroy() {
106
- this.rafId && (cancelAnimationFrame(this.rafId), this.rafId = null), this.ctx = null, this.canvasElement && this.canvasElement.parentNode && this.canvasElement.parentNode.removeChild(this.canvasElement), this.canvasElement = null, super.destroy();
101
+ this.ctx = null, this.canvasElement && this.canvasElement.parentNode && this.canvasElement.parentNode.removeChild(this.canvasElement), this.canvasElement = null, super.destroy();
107
102
  }
108
103
  }
109
104
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"index9.js","sources":["../src/layers/DrawingLayer.js"],"sourcesContent":["import BaseLayer from './BaseLayer.js';\n\n/**\n * DrawingLayer - Renders ink/drawing annotations on HTML canvas\n *\n * Extends BaseLayer to provide progressive stroke animation for ink annotations.\n * Draws stroke points incrementally based on timeline position using requestAnimationFrame.\n * Handles device pixel ratio scaling for crisp rendering on high-DPI displays.\n *\n * Features:\n * - Progressive stroke drawing point-by-point\n * - Multiple strokes per annotation with custom colors/sizes\n * - Device pixel ratio handling for Retina displays\n * - Smooth 60fps animation with RAF\n * - Efficient canvas clear/redraw cycle\n *\n * @extends BaseLayer\n */\nclass DrawingLayer extends BaseLayer {\n /**\n * Creates a new DrawingLayer instance\n *\n * @param {HTMLElement} container - Parent DOM element for layer content\n * @param {Object} viewport - Initial viewport dimensions\n * @param {number} viewport.width - Viewport width in pixels\n * @param {number} viewport.height - Viewport height in pixels\n * @param {number} viewport.scale - PDF scale/zoom level\n */\n constructor(container, viewport) {\n super(container, viewport);\n\n // Create canvas element\n this.canvasElement = document.createElement('canvas');\n this.canvasElement.style.position = 'absolute';\n this.canvasElement.style.inset = '0';\n this.canvasElement.style.pointerEvents = 'none';\n this.canvasElement.style.zIndex = '40';\n\n // Append to container\n this.container.appendChild(this.canvasElement);\n\n // Get 2D context\n this.ctx = this.canvasElement.getContext('2d');\n\n // Initialize animation frame ID\n this.rafId = null;\n\n // Setup canvas with device pixel ratio\n this._setupCanvas();\n }\n\n /**\n * Configures canvas dimensions with device pixel ratio scaling\n *\n * Sets canvas buffer size for high-resolution rendering on Retina displays\n * while maintaining correct display size in CSS pixels. Scales context\n * transform to allow drawing with CSS pixel coordinates.\n *\n * @private\n */\n _setupCanvas() {\n const dpr = window.devicePixelRatio || 1;\n\n // Set canvas buffer resolution (high-res for crisp rendering)\n this.canvasElement.width = Math.round(this.viewport.width * dpr);\n this.canvasElement.height = Math.round(this.viewport.height * dpr);\n\n // Set canvas display size (CSS pixels)\n this.canvasElement.style.width = `${this.viewport.width}px`;\n this.canvasElement.style.height = `${this.viewport.height}px`;\n\n // Scale context to account for device pixel ratio\n this.ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n }\n\n /**\n * Updates viewport dimensions and resizes canvas\n *\n * Reconfigures canvas buffer and display size when viewport changes\n * due to page navigation or zoom operations.\n *\n * @param {Object} viewport - New viewport dimensions\n * @param {number} viewport.width - Viewport width in pixels\n * @param {number} viewport.height - Viewport height in pixels\n * @param {number} viewport.scale - PDF scale/zoom level\n * @override\n */\n setViewport(viewport) {\n super.setViewport(viewport);\n this._setupCanvas();\n }\n\n /**\n * Updates timeline position and starts progressive stroke drawing\n *\n * Cancels any existing animation loop and starts a new requestAnimationFrame\n * loop to redraw the canvas with strokes progressively drawn based on elapsed time.\n * Each frame clears the canvas and redraws all visible strokes.\n *\n * @param {number} nowSec - Current timeline position in seconds\n * @throws {Error} If called after layer is destroyed\n * @override\n */\n updateTime(nowSec) {\n super.updateTime(nowSec);\n\n // Cancel existing RAF to prevent multiple loops\n if (this.rafId) {\n cancelAnimationFrame(this.rafId);\n }\n\n // Start drawing loop\n const draw = () => {\n // Check destroyed state\n if (this.isDestroyed) return;\n\n // Clear canvas\n this.ctx.clearRect(0, 0, this.canvasElement.width, this.canvasElement.height);\n\n // Draw each annotation\n for (const a of this.annotations) {\n // Skip annotations that haven't started yet\n if (nowSec < a.start) continue;\n\n // Calculate elapsed time (capped at duration for persistence)\n const duration = a.end - a.start;\n const elapsed = Math.min(nowSec - a.start, duration);\n\n // Draw each stroke\n for (const stroke of (a.strokes || [])) {\n // Configure stroke style\n this.ctx.lineCap = 'round';\n this.ctx.lineJoin = 'round';\n this.ctx.strokeStyle = stroke.color || '#1f2937';\n this.ctx.lineWidth = stroke.size || 3;\n this.ctx.beginPath();\n\n let started = false;\n\n // Draw points up to current time\n for (const point of stroke.points) {\n // Skip points that haven't been drawn yet\n if (point.t > elapsed) break;\n\n // Convert normalized coordinates to canvas pixels\n const x = point.x * this.viewport.width;\n const y = point.y * this.viewport.height;\n\n if (!started) {\n this.ctx.moveTo(x, y);\n started = true;\n } else {\n this.ctx.lineTo(x, y);\n }\n }\n\n // Render the stroke\n if (started) {\n this.ctx.stroke();\n }\n }\n }\n\n // Schedule next frame\n this.rafId = requestAnimationFrame(draw);\n };\n\n // Start the loop\n draw();\n }\n\n /**\n * Renders the layer content\n *\n * No-op for DrawingLayer - canvas rendering happens in updateTime() RAF loop.\n * Canvas element is created once in constructor and drawn to continuously.\n *\n * @override\n */\n render() {\n // No-op: Canvas rendering happens in updateTime() RAF loop\n // Canvas element is created once in constructor\n }\n\n /**\n * Updates the visual state of the layer\n *\n * Not used for DrawingLayer - updateTime() handles updates via RAF loop.\n *\n * @override\n */\n update() {\n // Not used - updateTime handles drawing via RAF loop\n }\n\n /**\n * Destroys the layer and releases resources\n *\n * Cancels animation loop, clears references, and removes canvas from DOM.\n * Safe to call multiple times (idempotent).\n *\n * @override\n */\n destroy() {\n // Cancel animation loop first\n if (this.rafId) {\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n\n // Clear context reference\n this.ctx = null;\n\n // Remove canvas from DOM\n if (this.canvasElement && this.canvasElement.parentNode) {\n this.canvasElement.parentNode.removeChild(this.canvasElement);\n }\n this.canvasElement = null;\n\n // Call parent cleanup (always last)\n super.destroy();\n }\n}\n\nexport default DrawingLayer;\n"],"names":["DrawingLayer","BaseLayer","container","viewport","dpr","nowSec","draw","a","duration","elapsed","stroke","started","point","x","y"],"mappings":"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"}
1
+ {"version":3,"file":"index9.js","sources":["../src/layers/DrawingLayer.js"],"sourcesContent":["import BaseLayer from './BaseLayer.js';\n\n/**\n * DrawingLayer - Renders ink/drawing annotations on HTML canvas\n *\n * Extends BaseLayer to provide progressive stroke animation for ink annotations.\n * Draws stroke points incrementally based on timeline position using requestAnimationFrame.\n * Handles device pixel ratio scaling for crisp rendering on high-DPI displays.\n *\n * Features:\n * - Progressive stroke drawing point-by-point\n * - Multiple strokes per annotation with custom colors/sizes\n * - Device pixel ratio handling for Retina displays\n * - Smooth 60fps animation with RAF\n * - Efficient canvas clear/redraw cycle\n *\n * @extends BaseLayer\n */\nclass DrawingLayer extends BaseLayer {\n /**\n * Creates a new DrawingLayer instance\n *\n * @param {HTMLElement} container - Parent DOM element for layer content\n * @param {Object} viewport - Initial viewport dimensions\n * @param {number} viewport.width - Viewport width in pixels\n * @param {number} viewport.height - Viewport height in pixels\n * @param {number} viewport.scale - PDF scale/zoom level\n */\n constructor(container, viewport) {\n super(container, viewport);\n\n // Create canvas element\n this.canvasElement = document.createElement('canvas');\n this.canvasElement.style.position = 'absolute';\n this.canvasElement.style.inset = '0';\n this.canvasElement.style.pointerEvents = 'none';\n this.canvasElement.style.zIndex = '40';\n\n // Append to container\n this.container.appendChild(this.canvasElement);\n\n // Get 2D context\n this.ctx = this.canvasElement.getContext('2d');\n\n // Setup canvas with device pixel ratio\n this._setupCanvas();\n }\n\n /**\n * Configures canvas dimensions with device pixel ratio scaling\n *\n * Sets canvas buffer size for high-resolution rendering on Retina displays\n * while maintaining correct display size in CSS pixels. Scales context\n * transform to allow drawing with CSS pixel coordinates.\n *\n * @private\n */\n _setupCanvas() {\n const dpr = window.devicePixelRatio || 1;\n\n // Set canvas buffer resolution (high-res for crisp rendering)\n this.canvasElement.width = Math.round(this.viewport.width * dpr);\n this.canvasElement.height = Math.round(this.viewport.height * dpr);\n\n // Set canvas display size (CSS pixels)\n this.canvasElement.style.width = `${this.viewport.width}px`;\n this.canvasElement.style.height = `${this.viewport.height}px`;\n\n // Scale context to account for device pixel ratio\n this.ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n }\n\n /**\n * Updates viewport dimensions and resizes canvas\n *\n * Reconfigures canvas buffer and display size when viewport changes\n * due to page navigation or zoom operations.\n *\n * @param {Object} viewport - New viewport dimensions\n * @param {number} viewport.width - Viewport width in pixels\n * @param {number} viewport.height - Viewport height in pixels\n * @param {number} viewport.scale - PDF scale/zoom level\n * @override\n */\n setViewport(viewport) {\n super.setViewport(viewport);\n this._setupCanvas();\n }\n\n /**\n * Updates timeline position and draws progressive strokes\n *\n * Redraws the canvas with strokes progressively drawn based on elapsed time.\n * Clears the canvas and redraws all visible strokes.\n * Renders once per call - no continuous loop.\n *\n * @param {number} nowSec - Current timeline position in seconds\n * @throws {Error} If called after layer is destroyed\n * @override\n */\n updateTime(nowSec) {\n super.updateTime(nowSec);\n\n // Check destroyed state\n if (this.isDestroyed) return;\n\n // Clear canvas\n this.ctx.clearRect(0, 0, this.canvasElement.width, this.canvasElement.height);\n\n // Draw each annotation\n for (const a of this.annotations) {\n // Skip annotations that haven't started yet\n if (nowSec < a.start) continue;\n\n // Calculate elapsed time (capped at duration for persistence)\n const duration = a.end - a.start;\n const elapsed = Math.min(nowSec - a.start, duration);\n\n // Draw each stroke\n for (const stroke of (a.strokes || [])) {\n // Configure stroke style\n this.ctx.lineCap = 'round';\n this.ctx.lineJoin = 'round';\n this.ctx.strokeStyle = stroke.color || '#1f2937';\n this.ctx.lineWidth = stroke.size || 3;\n this.ctx.beginPath();\n\n let started = false;\n\n // Draw points up to current time\n for (const point of stroke.points) {\n // Skip points that haven't been drawn yet\n if (point.t > elapsed) break;\n\n // Convert normalized coordinates to canvas pixels\n const x = point.x * this.viewport.width;\n const y = point.y * this.viewport.height;\n\n if (!started) {\n this.ctx.moveTo(x, y);\n started = true;\n } else {\n this.ctx.lineTo(x, y);\n }\n }\n\n // Render the stroke\n if (started) {\n this.ctx.stroke();\n }\n }\n }\n }\n\n /**\n * Renders the layer content\n *\n * No-op for DrawingLayer - canvas rendering happens in updateTime().\n * Canvas element is created once in constructor.\n *\n * @override\n */\n render() {\n // No-op: Canvas rendering happens in updateTime()\n // Canvas element is created once in constructor\n }\n\n /**\n * Updates the visual state of the layer\n *\n * Not used for DrawingLayer - updateTime() handles drawing directly.\n *\n * @override\n */\n update() {\n // Not used - updateTime handles drawing directly\n }\n\n /**\n * Destroys the layer and releases resources\n *\n * Clears references and removes canvas from DOM.\n * Safe to call multiple times (idempotent).\n *\n * @override\n */\n destroy() {\n // Clear context reference\n this.ctx = null;\n\n // Remove canvas from DOM\n if (this.canvasElement && this.canvasElement.parentNode) {\n this.canvasElement.parentNode.removeChild(this.canvasElement);\n }\n this.canvasElement = null;\n\n // Call parent cleanup (always last)\n super.destroy();\n }\n}\n\nexport default DrawingLayer;\n"],"names":["DrawingLayer","BaseLayer","container","viewport","dpr","nowSec","a","duration","elapsed","stroke","started","point","x","y"],"mappings":";AAkBA,MAAMA,UAAqBC,EAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUnC,YAAYC,GAAWC,GAAU;AAC/B,UAAMD,GAAWC,CAAQ,GAGzB,KAAK,gBAAgB,SAAS,cAAc,QAAQ,GACpD,KAAK,cAAc,MAAM,WAAW,YACpC,KAAK,cAAc,MAAM,QAAQ,KACjC,KAAK,cAAc,MAAM,gBAAgB,QACzC,KAAK,cAAc,MAAM,SAAS,MAGlC,KAAK,UAAU,YAAY,KAAK,aAAa,GAG7C,KAAK,MAAM,KAAK,cAAc,WAAW,IAAI,GAG7C,KAAK,aAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,eAAe;AACb,UAAMC,IAAM,OAAO,oBAAoB;AAGvC,SAAK,cAAc,QAAQ,KAAK,MAAM,KAAK,SAAS,QAAQA,CAAG,GAC/D,KAAK,cAAc,SAAS,KAAK,MAAM,KAAK,SAAS,SAASA,CAAG,GAGjE,KAAK,cAAc,MAAM,QAAQ,GAAG,KAAK,SAAS,KAAK,MACvD,KAAK,cAAc,MAAM,SAAS,GAAG,KAAK,SAAS,MAAM,MAGzD,KAAK,IAAI,aAAaA,GAAK,GAAG,GAAGA,GAAK,GAAG,CAAC;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,YAAYD,GAAU;AACpB,UAAM,YAAYA,CAAQ,GAC1B,KAAK,aAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,WAAWE,GAAQ;AAIjB,QAHA,MAAM,WAAWA,CAAM,GAGnB,MAAK,aAGT;AAAA,WAAK,IAAI,UAAU,GAAG,GAAG,KAAK,cAAc,OAAO,KAAK,cAAc,MAAM;AAG5E,iBAAWC,KAAK,KAAK,aAAa;AAEhC,YAAID,IAASC,EAAE,MAAO;AAGtB,cAAMC,IAAWD,EAAE,MAAMA,EAAE,OACrBE,IAAU,KAAK,IAAIH,IAASC,EAAE,OAAOC,CAAQ;AAGnD,mBAAWE,KAAWH,EAAE,WAAW,CAAA,GAAK;AAEtC,eAAK,IAAI,UAAU,SACnB,KAAK,IAAI,WAAW,SACpB,KAAK,IAAI,cAAcG,EAAO,SAAS,WACvC,KAAK,IAAI,YAAYA,EAAO,QAAQ,GACpC,KAAK,IAAI,UAAS;AAElB,cAAIC,IAAU;AAGd,qBAAWC,KAASF,EAAO,QAAQ;AAEjC,gBAAIE,EAAM,IAAIH,EAAS;AAGvB,kBAAMI,IAAID,EAAM,IAAI,KAAK,SAAS,OAC5BE,IAAIF,EAAM,IAAI,KAAK,SAAS;AAElC,YAAKD,IAIH,KAAK,IAAI,OAAOE,GAAGC,CAAC,KAHpB,KAAK,IAAI,OAAOD,GAAGC,CAAC,GACpBH,IAAU;AAAA,UAId;AAGA,UAAIA,KACF,KAAK,IAAI,OAAM;AAAA,QAEnB;AAAA,MACF;AAAA;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,SAAS;AAAA,EAGT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,SAAS;AAAA,EAET;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,UAAU;AAER,SAAK,MAAM,MAGP,KAAK,iBAAiB,KAAK,cAAc,cAC3C,KAAK,cAAc,WAAW,YAAY,KAAK,aAAa,GAE9D,KAAK,gBAAgB,MAGrB,MAAM,QAAO;AAAA,EACf;AACF;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "web-annotation-renderer",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "type": "module",
5
5
  "description": "Framework-agnostic PDF annotation renderer with timeline synchronization for educational content and interactive documents",
6
6
  "keywords": [