svg-scroll-draw 2.12.0 → 2.13.0
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/README.md +33 -0
- package/dist/cdn/vivus.global.js +1 -0
- package/dist/vivus/index.cjs +2 -0
- package/dist/vivus/index.d.mts +100 -0
- package/dist/vivus/index.d.ts +100 -0
- package/dist/vivus/index.mjs +2 -0
- package/package.json +22 -3
- package/dist/aos/index.d.mts +0 -53
- package/dist/aos/index.d.ts +0 -53
- package/dist/cinematic/index.d.mts +0 -72
- package/dist/cinematic/index.d.ts +0 -72
- package/dist/devtools/index.d.mts +0 -12
- package/dist/devtools/index.d.ts +0 -12
- package/dist/text/index.d.mts +0 -52
- package/dist/text/index.d.ts +0 -52
package/README.md
CHANGED
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
| `devtools` | `svg-scroll-draw/devtools` | Visual overlay showing every active animation's triggers and progress. Dev-only. |
|
|
33
33
|
| `AOS` | `svg-scroll-draw/aos` | Drop-in replacement for AOS: same `AOS.init()`, same `data-aos` markup, no `aos.css`. |
|
|
34
34
|
| `ScrollReveal` | `svg-scroll-draw/scrollreveal` | Drop-in replacement for ScrollReveal.js 4, MIT instead of GPL-3.0. |
|
|
35
|
+
| `Vivus` | `svg-scroll-draw/vivus` | Drop-in replacement for vivus 0.4: same `new Vivus()` API and output. |
|
|
35
36
|
|
|
36
37
|
All APIs return the same instance object: `{ destroy, replay, pause, resume, seek, getProgress }`.
|
|
37
38
|
|
|
@@ -430,6 +431,36 @@ Differences, on purpose:
|
|
|
430
431
|
|
|
431
432
|
---
|
|
432
433
|
|
|
434
|
+
## vivus drop-in — keep your `new Vivus()` code
|
|
435
|
+
|
|
436
|
+
On [vivus](https://github.com/maxwellito/vivus)? It has not shipped since 0.4.6 (April 2021).
|
|
437
|
+
`svg-scroll-draw/vivus` runs the same API, so the move is an import change. 3.9 KB gzipped, against
|
|
438
|
+
4.1 KB.
|
|
439
|
+
|
|
440
|
+
```diff
|
|
441
|
+
- import Vivus from 'vivus';
|
|
442
|
+
+ import Vivus from 'svg-scroll-draw/vivus';
|
|
443
|
+
|
|
444
|
+
new Vivus('my-svg', { type: 'oneByOne', duration: 200 }, () => console.log('drawn'));
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
No bundler? `<script src="https://unpkg.com/svg-scroll-draw/dist/cdn/vivus.global.js"></script>`
|
|
448
|
+
defines `window.Vivus`. With CommonJS, `require('svg-scroll-draw/vivus').default` is the class.
|
|
449
|
+
|
|
450
|
+
Every option, every animation type (`delayed`, `sync`, `async`, `nsync`, `oneByOne`, `scenario`,
|
|
451
|
+
`scenario-sync`), the `start` modes, `file` and `<object>` loading, the `data-start` / `data-duration` /
|
|
452
|
+
`data-delay` / `data-async` / `data-ignore` attributes, `Vivus.EASE` and the other timing functions, and
|
|
453
|
+
`play` / `stop` / `reset` / `finish` / `setFrameProgress` / `getStatus` / `destroy` / `recalc` behave as
|
|
454
|
+
in 0.4.6. Shapes become `<path>`s with the same `d` strings, and dashes get the same values: the browser
|
|
455
|
+
suite runs vivus 0.4.6 beside it across nine configurations and requires the SVG markup to match exactly
|
|
456
|
+
at every point of the animation. Like vivus, the clock is the animation frame.
|
|
457
|
+
|
|
458
|
+
One difference, on purpose: under `prefers-reduced-motion: reduce`, `play()` jumps to the end and still
|
|
459
|
+
fires its callbacks. When you want the stroke to follow the scroll instead of a clock, use
|
|
460
|
+
[`scrollDraw`](#scrolldraw--svg-path-drawing-v1-api-unchanged) from the same package.
|
|
461
|
+
|
|
462
|
+
---
|
|
463
|
+
|
|
433
464
|
## Instance API
|
|
434
465
|
|
|
435
466
|
Every function returns the same instance object:
|
|
@@ -522,6 +553,7 @@ devtools.highlight('#my-element'); // outline for 2 seconds
|
|
|
522
553
|
| `svg-scroll-draw/devtools` | `devtools` (dev-only) |
|
|
523
554
|
| `svg-scroll-draw/aos` | `AOS` (default), `init`, `refresh`, `refreshHard`, `destroy` |
|
|
524
555
|
| `svg-scroll-draw/scrollreveal` | `ScrollReveal` (default and named) |
|
|
556
|
+
| `svg-scroll-draw/vivus` | `Vivus` (default and named) |
|
|
525
557
|
|
|
526
558
|
---
|
|
527
559
|
|
|
@@ -535,6 +567,7 @@ devtools.highlight('#my-element'); // outline for 2 seconds
|
|
|
535
567
|
| `svg-scroll-draw/text` | 2.5 KB |
|
|
536
568
|
| `svg-scroll-draw/video` | 2.0 KB |
|
|
537
569
|
| `svg-scroll-draw/scrollreveal` | 4.5 KB |
|
|
570
|
+
| `svg-scroll-draw/vivus` | 3.9 KB |
|
|
538
571
|
| `svg-scroll-draw/aos` (styles included) | 3.0 KB |
|
|
539
572
|
| `svg-scroll-draw/snap` | 1.7 KB |
|
|
540
573
|
| `svg-scroll-draw/devtools` | 1.7 KB (dev only) |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(()=>{function g(){return typeof window>"u"||typeof window.matchMedia!="function"?!1:window.matchMedia("(prefers-reduced-motion: reduce)").matches}function m(r,...t){}var E=["delayed","sync","async","nsync","oneByOne","scenario","scenario-sync"],L=["inViewport","manual","autostart"];function u(r,t){let e=parseInt(r,10);return e>=0?e:t}function V(r){if(typeof window>"u")return!1;let t=window,e=i=>typeof t[i]=="function"&&r instanceof t[i];return e("SVGSVGElement")||e("SVGGElement")||r?.constructor===t.SVGElement}var y=["cx","cy","points","r","rx","ry","x","x1","x2","y","y1","y2"],$=["line","ellipse","circle","polygon","polyline","rect"],S="http://www.w3.org/2000/svg";function v(r){let t=r.points.trim().split(" ");if(r.points.indexOf(",")===-1){let i=[];for(let s=0;s<t.length;s+=2)i.push(`${t[s]},${t[s+1]}`);t=i}let e=`M${t[0]}`;for(let i=1;i<t.length;i++)t[i].indexOf(",")!==-1&&(e+=`L${t[i]}`);return e}function b(r,t,e,i){let s=parseFloat(e)||0,a=parseFloat(i)||0,n=parseFloat(r)||0,o=parseFloat(t)||0,l=n-s,h=n+s;return`M${l},${o}A${s},${a} 0,1,1 ${h},${o}A${s},${a} 0,1,1 ${l},${o}`}var x={line:r=>`M${r.x1||0},${r.y1||0}L${r.x2||0},${r.y2||0}`,rect(r){let t=parseFloat(r.x)||0,e=parseFloat(r.y)||0,i=parseFloat(r.width)||0,s=parseFloat(r.height)||0;if(r.rx||r.ry){let a=parseInt(r.rx,10)||-1,n=parseInt(r.ry,10)||-1;a=Math.min(Math.max(a<0?n:a,0),i/2),n=Math.min(Math.max(n<0?a:n,0),s/2);let o=`A ${a},${n},0,0,1,`;return`M ${t+a},${e} L ${t+i-a},${e} ${o}${t+i},${e+n} L ${t+i},${e+s-n} ${o}${t+i-a},${e+s} L ${t+a},${e+s} ${o}${t},${e+s-n} L ${t},${e+n} ${o}${t+a},${e}`}return`M${t} ${e} L${t+i} ${e} L${t+i} ${e+s} L${t} ${e+s} Z`},polyline:v,polygon:r=>`${v(r)}Z`,ellipse:r=>b(r.cx,r.cy,r.rx,r.ry),circle:r=>b(r.cx,r.cy,r.r,r.r)};function A(r){for(let t of Array.from(r.querySelectorAll($.join(",")))){let e={};for(let{name:a,value:n}of Array.from(t.attributes)){if(y.indexOf(a)!==-1&&n.indexOf("%")!==-1)throw new Error("Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into 'path' tags. Please use 'viewBox'.");e[a]=n}let i=x[t.tagName.toLowerCase()](e),s=document.createElementNS(S,"path");for(let{name:a,value:n}of Array.from(t.attributes))y.indexOf(a)===-1&&s.setAttribute(a,n);s.setAttribute("d",i),t.parentNode?.replaceChild(s,t)}}var c=class c{constructor(t,e,i){this.isReady=!1;this.type="delayed";this.start="inViewport";this.duration=120;this.delay=null;this.dashGap=1;this.forceRender=!1;this.reverseStack=!1;this.selfDestroy=!1;this.ignoreInvisible=!1;this.animTimingFunction=c.LINEAR;this.pathTimingFunction=c.LINEAR;this.callback=()=>{};this.map=[];this.frameLength=0;this.currentFrame=0;this.delayUnit=0;this.speed=1;this.handle=null;this.instanceCallback=null;this.mustRecalcScale=null;this.viewportListener=null;this.setElement(t,e),this.setOptions(e),this.setCallback(i),this.isReady&&this.init()}setElement(t,e){if(t===void 0)throw new Error('Vivus [constructor]: "element" parameter is required');let i=t;if(typeof i=="string"){let s=document.getElementById(i);if(!s)throw new Error('Vivus [constructor]: "element" parameter is not related to an existing ID');i=s}if(this.parentEl=i,e&&e.file){let s=new XMLHttpRequest;s.addEventListener("load",()=>{let a=document.createElement("div");a.innerHTML=s.responseText;let n=a.querySelector("svg");if(!n)throw new Error(`Vivus [load]: Cannot find the SVG in the loaded file : ${e.file}`);this.el=n,n.setAttribute("width","100%"),n.setAttribute("height","100%"),this.parentEl.appendChild(n),this.isReady=!0,this.init()}),s.open("GET",e.file),s.send();return}if(V(i)){this.el=i,this.isReady=!0;return}if(i instanceof HTMLObjectElement){let s=i,a=n=>{if(this.isReady)return;let o=s.contentDocument&&s.contentDocument.querySelector("svg");if(!o&&n)throw new Error("Vivus [constructor]: object loaded does not contain any SVG");o&&(s.getAttribute("built-by-vivus")&&(this.parentEl.insertBefore(o,s),this.parentEl.removeChild(s),o.setAttribute("width","100%"),o.setAttribute("height","100%")),this.el=o,this.isReady=!0,this.init())};a(),this.isReady||s.addEventListener("load",a);return}throw new Error('Vivus [constructor]: "element" parameter is not valid (or miss the "file" attribute)')}setOptions(t){if(t!==void 0&&(t===null||t.constructor!==Object))throw new Error('Vivus [constructor]: "options" parameter must be an object');let e=t||{};if(e.type&&E.indexOf(e.type)===-1)throw new Error(`Vivus [constructor]: ${e.type} is not an existing animation \`type\``);if(e.start&&L.indexOf(e.start)===-1)throw new Error(`Vivus [constructor]: ${e.start} is not an existing \`start\` option`);this.type=e.type||"delayed",this.start=e.start||"inViewport";let i=navigator.userAgent,s=i.indexOf("MSIE")!==-1||i.indexOf("Trident/")!==-1||i.indexOf("Edge/")!==-1;if(this.duration=u(e.duration,120),this.delay=u(e.delay,null),this.dashGap=u(e.dashGap,1),this.forceRender=Object.prototype.hasOwnProperty.call(e,"forceRender")?!!e.forceRender:s,this.reverseStack=!!e.reverseStack,this.selfDestroy=!!e.selfDestroy,this.onReady=e.onReady,this.map=[],this.ignoreInvisible=Object.prototype.hasOwnProperty.call(e,"ignoreInvisible")?!!e.ignoreInvisible:!1,this.animTimingFunction=e.animTimingFunction||c.LINEAR,this.pathTimingFunction=e.pathTimingFunction||c.LINEAR,this.delay!==null&&this.delay>=this.duration)throw new Error("Vivus [constructor]: delay must be shorter than duration")}setCallback(t){if(t&&typeof t!="function")throw new Error('Vivus [constructor]: "callback" parameter must be a function');this.callback=t||(()=>{})}mapping(){let t=0,e=0,i=0,s=!1,a=Array.from(this.el.querySelectorAll("path"));a.forEach((n,o)=>{if(this.isInvisible(n))return;let l={el:n,length:0,startAt:0,duration:0,isResizeSensitive:!1},h=1;if(n.getAttribute("vector-effect")==="non-scaling-stroke"){let d=n.getBoundingClientRect(),f=n.getBBox();h=Math.max(d.width/f.width,d.height/f.height),l.isResizeSensitive=!0,s=!0}if(l.length=Math.ceil(n.getTotalLength()*h),isNaN(l.length)){m("vivus: cannot retrieve a path element length",n);return}this.map.push(l),n.style.strokeDasharray=`${l.length} ${l.length+this.dashGap*2}`,n.style.strokeDashoffset=String(l.length+this.dashGap),l.length+=this.dashGap,e+=l.length,this.renderPath(o)}),s&&m("vivus: this SVG contains non-scaling-strokes. Call instance.recalc() when the SVG is resized."),e=e===0?1:e,this.delay=this.delay===null?this.duration/3:this.delay,this.delayUnit=this.delay/(a.length>1?a.length-1:1),this.reverseStack&&this.map.reverse(),this.map.forEach((n,o)=>{let l=()=>{let h={};for(let{name:d,value:f}of Array.from(n.el.attributes))h[d]=f;return h};switch(this.type){case"delayed":n.startAt=this.delayUnit*o,n.duration=this.duration-this.delay;break;case"oneByOne":n.startAt=i/e*this.duration,n.duration=n.length/e*this.duration;break;case"sync":case"async":case"nsync":n.startAt=0,n.duration=this.duration;break;case"scenario-sync":{let h=l();n.startAt=t+(u(h["data-delay"],this.delayUnit)||0),n.duration=u(h["data-duration"],this.duration),t=h["data-async"]!==void 0?n.startAt:n.startAt+n.duration,this.frameLength=Math.max(this.frameLength,n.startAt+n.duration);break}case"scenario":{let h=l();n.startAt=u(h["data-start"],this.delayUnit)||0,n.duration=u(h["data-duration"],this.duration),this.frameLength=Math.max(this.frameLength,n.startAt+n.duration);break}}i+=n.length,this.frameLength=this.frameLength||this.duration})}recalc(){this.mustRecalcScale||(this.mustRecalcScale=requestAnimationFrame(()=>this.performLineRecalc()))}performLineRecalc(){for(let t of this.map){if(!t.isResizeSensitive)continue;let e=t.el.getBoundingClientRect(),i=t.el.getBBox(),s=Math.max(e.width/i.width,e.height/i.height);t.length=Math.ceil(t.el.getTotalLength()*s),t.el.style.strokeDasharray=`${t.length} ${t.length+this.dashGap*2}`}this.trace(),this.mustRecalcScale=null}draw(){if(this.currentFrame+=this.speed,this.currentFrame<=0)this.stop(),this.reset();else if(this.currentFrame>=this.frameLength)this.stop(),this.currentFrame=this.frameLength,this.trace(),this.selfDestroy&&this.destroy();else{this.trace(),this.handle=requestAnimationFrame(()=>this.draw());return}this.finished()}finished(){if(this.callback(this),this.instanceCallback){let t=this.instanceCallback;this.instanceCallback=null,t(this)}}trace(){let t=this.animTimingFunction(this.currentFrame/this.frameLength)*this.frameLength;this.map.forEach((e,i)=>{let s=this.pathTimingFunction(Math.max(0,Math.min(1,(t-e.startAt)/e.duration)));e.progress!==s&&(e.progress=s,e.el.style.strokeDashoffset=String(Math.floor(e.length*(1-s))),this.renderPath(i))})}renderPath(t){let e=this.forceRender&&this.map&&this.map[t];if(!e)return;let i=e.el.cloneNode(!0);e.el.parentNode?.replaceChild(i,e.el),e.el=i}init(){this.frameLength=0,this.currentFrame=0,this.map=[],A(this.el),this.mapping(),this.starter(),this.onReady&&this.onReady(this)}starter(){if(this.start==="manual")return;if(this.start==="autostart"){this.play();return}let t=()=>{this.isInViewport(this.parentEl,1)&&(this.play(),window.removeEventListener("scroll",t),this.viewportListener=null)};this.viewportListener=t,window.addEventListener("scroll",t),t()}getStatus(){return this.currentFrame===0?"start":this.currentFrame===this.frameLength?"end":"progress"}reset(){return this.setFrameProgress(0)}finish(){return this.setFrameProgress(1)}setFrameProgress(t){let e=Math.min(1,Math.max(0,t));return this.currentFrame=Math.round(this.frameLength*e),this.trace(),this}play(t,e){this.instanceCallback=null;let i=t;if(i&&typeof i=="function")this.instanceCallback=i,i=void 0;else if(i&&typeof i!="number")throw new Error("Vivus [play]: invalid speed");return e&&typeof e=="function"&&!this.instanceCallback&&(this.instanceCallback=e),this.speed=i||1,g()?(this.stop(),this.currentFrame=this.speed<0?0:this.frameLength,this.trace(),this.speed>0&&this.selfDestroy&&this.destroy(),this.finished(),this):(this.handle||this.draw(),this)}stop(){return this.handle&&(cancelAnimationFrame(this.handle),this.handle=null),this}destroy(){this.stop(),this.viewportListener&&(window.removeEventListener("scroll",this.viewportListener),this.viewportListener=null),this.map.forEach((t,e)=>{t.el.style.strokeDashoffset="",t.el.style.strokeDasharray="",this.renderPath(e)})}isInvisible(t){let e=t.getAttribute("data-ignore");if(e!==null)return e!=="false";if(this.ignoreInvisible){let i=t.getBoundingClientRect();return!i.width&&!i.height}return!1}isInViewport(t,e=0){let i=window.pageYOffset||document.documentElement.scrollTop,s=i+Math.max(document.documentElement.clientHeight,window.innerHeight),a=t.getBoundingClientRect(),n=i+a.top;return n+a.height*(e||0)<=s&&n+a.height>=i}};c.LINEAR=t=>t,c.EASE=t=>-Math.cos(t*Math.PI)/2+.5,c.EASE_OUT=t=>1-Math.pow(1-t,3),c.EASE_IN=t=>Math.pow(t,3),c.EASE_OUT_BOUNCE=t=>{let e=-Math.cos(t*(.5*Math.PI))+1,i=Math.pow(e,1.5),s=Math.pow(1-t,2),a=-Math.abs(Math.cos(i*(2.5*Math.PI)))+1;return 1-s+a*s};var p=c,w=p;globalThis.Vivus=w;})();
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
'use strict';Object.defineProperty(exports,'__esModule',{value:true});function g(){return typeof window>"u"||typeof window.matchMedia!="function"?false:window.matchMedia("(prefers-reduced-motion: reduce)").matches}var w=typeof __SVG_SCROLL_DRAW_DEV__<"u"?__SVG_SCROLL_DRAW_DEV__:typeof process<"u"&&typeof process.env<"u"&&process.env.NODE_ENV!=="production";function m(r,...t){w&&console.warn(`[svg-scroll-draw] ${r}`,...t);}var E=["delayed","sync","async","nsync","oneByOne","scenario","scenario-sync"],L=["inViewport","manual","autostart"];function u(r,t){let e=parseInt(r,10);return e>=0?e:t}function V(r){if(typeof window>"u")return false;let t=window,e=i=>typeof t[i]=="function"&&r instanceof t[i];return e("SVGSVGElement")||e("SVGGElement")||r?.constructor===t.SVGElement}var y=["cx","cy","points","r","rx","ry","x","x1","x2","y","y1","y2"],$=["line","ellipse","circle","polygon","polyline","rect"],x="http://www.w3.org/2000/svg";function v(r){let t=r.points.trim().split(" ");if(r.points.indexOf(",")===-1){let i=[];for(let s=0;s<t.length;s+=2)i.push(`${t[s]},${t[s+1]}`);t=i;}let e=`M${t[0]}`;for(let i=1;i<t.length;i++)t[i].indexOf(",")!==-1&&(e+=`L${t[i]}`);return e}function b(r,t,e,i){let s=parseFloat(e)||0,a=parseFloat(i)||0,n=parseFloat(r)||0,o=parseFloat(t)||0,l=n-s,h=n+s;return `M${l},${o}A${s},${a} 0,1,1 ${h},${o}A${s},${a} 0,1,1 ${l},${o}`}var A={line:r=>`M${r.x1||0},${r.y1||0}L${r.x2||0},${r.y2||0}`,rect(r){let t=parseFloat(r.x)||0,e=parseFloat(r.y)||0,i=parseFloat(r.width)||0,s=parseFloat(r.height)||0;if(r.rx||r.ry){let a=parseInt(r.rx,10)||-1,n=parseInt(r.ry,10)||-1;a=Math.min(Math.max(a<0?n:a,0),i/2),n=Math.min(Math.max(n<0?a:n,0),s/2);let o=`A ${a},${n},0,0,1,`;return `M ${t+a},${e} L ${t+i-a},${e} ${o}${t+i},${e+n} L ${t+i},${e+s-n} ${o}${t+i-a},${e+s} L ${t+a},${e+s} ${o}${t},${e+s-n} L ${t},${e+n} ${o}${t+a},${e}`}return `M${t} ${e} L${t+i} ${e} L${t+i} ${e+s} L${t} ${e+s} Z`},polyline:v,polygon:r=>`${v(r)}Z`,ellipse:r=>b(r.cx,r.cy,r.rx,r.ry),circle:r=>b(r.cx,r.cy,r.r,r.r)};function R(r){for(let t of Array.from(r.querySelectorAll($.join(",")))){let e={};for(let{name:a,value:n}of Array.from(t.attributes)){if(y.indexOf(a)!==-1&&n.indexOf("%")!==-1)throw new Error("Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into 'path' tags. Please use 'viewBox'.");e[a]=n;}let i=A[t.tagName.toLowerCase()](e),s=document.createElementNS(x,"path");for(let{name:a,value:n}of Array.from(t.attributes))y.indexOf(a)===-1&&s.setAttribute(a,n);s.setAttribute("d",i),t.parentNode?.replaceChild(s,t);}}var c=class c{constructor(t,e,i){this.isReady=false;this.type="delayed";this.start="inViewport";this.duration=120;this.delay=null;this.dashGap=1;this.forceRender=false;this.reverseStack=false;this.selfDestroy=false;this.ignoreInvisible=false;this.animTimingFunction=c.LINEAR;this.pathTimingFunction=c.LINEAR;this.callback=()=>{};this.map=[];this.frameLength=0;this.currentFrame=0;this.delayUnit=0;this.speed=1;this.handle=null;this.instanceCallback=null;this.mustRecalcScale=null;this.viewportListener=null;this.setElement(t,e),this.setOptions(e),this.setCallback(i),this.isReady&&this.init();}setElement(t,e){if(t===void 0)throw new Error('Vivus [constructor]: "element" parameter is required');let i=t;if(typeof i=="string"){let s=document.getElementById(i);if(!s)throw new Error('Vivus [constructor]: "element" parameter is not related to an existing ID');i=s;}if(this.parentEl=i,e&&e.file){let s=new XMLHttpRequest;s.addEventListener("load",()=>{let a=document.createElement("div");a.innerHTML=s.responseText;let n=a.querySelector("svg");if(!n)throw new Error(`Vivus [load]: Cannot find the SVG in the loaded file : ${e.file}`);this.el=n,n.setAttribute("width","100%"),n.setAttribute("height","100%"),this.parentEl.appendChild(n),this.isReady=true,this.init();}),s.open("GET",e.file),s.send();return}if(V(i)){this.el=i,this.isReady=true;return}if(i instanceof HTMLObjectElement){let s=i,a=n=>{if(this.isReady)return;let o=s.contentDocument&&s.contentDocument.querySelector("svg");if(!o&&n)throw new Error("Vivus [constructor]: object loaded does not contain any SVG");o&&(s.getAttribute("built-by-vivus")&&(this.parentEl.insertBefore(o,s),this.parentEl.removeChild(s),o.setAttribute("width","100%"),o.setAttribute("height","100%")),this.el=o,this.isReady=true,this.init());};a(),this.isReady||s.addEventListener("load",a);return}throw new Error('Vivus [constructor]: "element" parameter is not valid (or miss the "file" attribute)')}setOptions(t){if(t!==void 0&&(t===null||t.constructor!==Object))throw new Error('Vivus [constructor]: "options" parameter must be an object');let e=t||{};if(e.type&&E.indexOf(e.type)===-1)throw new Error(`Vivus [constructor]: ${e.type} is not an existing animation \`type\``);if(e.start&&L.indexOf(e.start)===-1)throw new Error(`Vivus [constructor]: ${e.start} is not an existing \`start\` option`);this.type=e.type||"delayed",this.start=e.start||"inViewport";let i=navigator.userAgent,s=i.indexOf("MSIE")!==-1||i.indexOf("Trident/")!==-1||i.indexOf("Edge/")!==-1;if(this.duration=u(e.duration,120),this.delay=u(e.delay,null),this.dashGap=u(e.dashGap,1),this.forceRender=Object.prototype.hasOwnProperty.call(e,"forceRender")?!!e.forceRender:s,this.reverseStack=!!e.reverseStack,this.selfDestroy=!!e.selfDestroy,this.onReady=e.onReady,this.map=[],this.ignoreInvisible=Object.prototype.hasOwnProperty.call(e,"ignoreInvisible")?!!e.ignoreInvisible:false,this.animTimingFunction=e.animTimingFunction||c.LINEAR,this.pathTimingFunction=e.pathTimingFunction||c.LINEAR,this.delay!==null&&this.delay>=this.duration)throw new Error("Vivus [constructor]: delay must be shorter than duration")}setCallback(t){if(t&&typeof t!="function")throw new Error('Vivus [constructor]: "callback" parameter must be a function');this.callback=t||(()=>{});}mapping(){let t=0,e=0,i=0,s=false,a=Array.from(this.el.querySelectorAll("path"));a.forEach((n,o)=>{if(this.isInvisible(n))return;let l={el:n,length:0,startAt:0,duration:0,isResizeSensitive:false},h=1;if(n.getAttribute("vector-effect")==="non-scaling-stroke"){let d=n.getBoundingClientRect(),f=n.getBBox();h=Math.max(d.width/f.width,d.height/f.height),l.isResizeSensitive=true,s=true;}if(l.length=Math.ceil(n.getTotalLength()*h),isNaN(l.length)){m("vivus: cannot retrieve a path element length",n);return}this.map.push(l),n.style.strokeDasharray=`${l.length} ${l.length+this.dashGap*2}`,n.style.strokeDashoffset=String(l.length+this.dashGap),l.length+=this.dashGap,e+=l.length,this.renderPath(o);}),s&&m("vivus: this SVG contains non-scaling-strokes. Call instance.recalc() when the SVG is resized."),e=e===0?1:e,this.delay=this.delay===null?this.duration/3:this.delay,this.delayUnit=this.delay/(a.length>1?a.length-1:1),this.reverseStack&&this.map.reverse(),this.map.forEach((n,o)=>{let l=()=>{let h={};for(let{name:d,value:f}of Array.from(n.el.attributes))h[d]=f;return h};switch(this.type){case "delayed":n.startAt=this.delayUnit*o,n.duration=this.duration-this.delay;break;case "oneByOne":n.startAt=i/e*this.duration,n.duration=n.length/e*this.duration;break;case "sync":case "async":case "nsync":n.startAt=0,n.duration=this.duration;break;case "scenario-sync":{let h=l();n.startAt=t+(u(h["data-delay"],this.delayUnit)||0),n.duration=u(h["data-duration"],this.duration),t=h["data-async"]!==void 0?n.startAt:n.startAt+n.duration,this.frameLength=Math.max(this.frameLength,n.startAt+n.duration);break}case "scenario":{let h=l();n.startAt=u(h["data-start"],this.delayUnit)||0,n.duration=u(h["data-duration"],this.duration),this.frameLength=Math.max(this.frameLength,n.startAt+n.duration);break}}i+=n.length,this.frameLength=this.frameLength||this.duration;});}recalc(){this.mustRecalcScale||(this.mustRecalcScale=requestAnimationFrame(()=>this.performLineRecalc()));}performLineRecalc(){for(let t of this.map){if(!t.isResizeSensitive)continue;let e=t.el.getBoundingClientRect(),i=t.el.getBBox(),s=Math.max(e.width/i.width,e.height/i.height);t.length=Math.ceil(t.el.getTotalLength()*s),t.el.style.strokeDasharray=`${t.length} ${t.length+this.dashGap*2}`;}this.trace(),this.mustRecalcScale=null;}draw(){if(this.currentFrame+=this.speed,this.currentFrame<=0)this.stop(),this.reset();else if(this.currentFrame>=this.frameLength)this.stop(),this.currentFrame=this.frameLength,this.trace(),this.selfDestroy&&this.destroy();else {this.trace(),this.handle=requestAnimationFrame(()=>this.draw());return}this.finished();}finished(){if(this.callback(this),this.instanceCallback){let t=this.instanceCallback;this.instanceCallback=null,t(this);}}trace(){let t=this.animTimingFunction(this.currentFrame/this.frameLength)*this.frameLength;this.map.forEach((e,i)=>{let s=this.pathTimingFunction(Math.max(0,Math.min(1,(t-e.startAt)/e.duration)));e.progress!==s&&(e.progress=s,e.el.style.strokeDashoffset=String(Math.floor(e.length*(1-s))),this.renderPath(i));});}renderPath(t){let e=this.forceRender&&this.map&&this.map[t];if(!e)return;let i=e.el.cloneNode(true);e.el.parentNode?.replaceChild(i,e.el),e.el=i;}init(){this.frameLength=0,this.currentFrame=0,this.map=[],R(this.el),this.mapping(),this.starter(),this.onReady&&this.onReady(this);}starter(){if(this.start==="manual")return;if(this.start==="autostart"){this.play();return}let t=()=>{this.isInViewport(this.parentEl,1)&&(this.play(),window.removeEventListener("scroll",t),this.viewportListener=null);};this.viewportListener=t,window.addEventListener("scroll",t),t();}getStatus(){return this.currentFrame===0?"start":this.currentFrame===this.frameLength?"end":"progress"}reset(){return this.setFrameProgress(0)}finish(){return this.setFrameProgress(1)}setFrameProgress(t){let e=Math.min(1,Math.max(0,t));return this.currentFrame=Math.round(this.frameLength*e),this.trace(),this}play(t,e){this.instanceCallback=null;let i=t;if(i&&typeof i=="function")this.instanceCallback=i,i=void 0;else if(i&&typeof i!="number")throw new Error("Vivus [play]: invalid speed");return e&&typeof e=="function"&&!this.instanceCallback&&(this.instanceCallback=e),this.speed=i||1,g()?(this.stop(),this.currentFrame=this.speed<0?0:this.frameLength,this.trace(),this.speed>0&&this.selfDestroy&&this.destroy(),this.finished(),this):(this.handle||this.draw(),this)}stop(){return this.handle&&(cancelAnimationFrame(this.handle),this.handle=null),this}destroy(){this.stop(),this.viewportListener&&(window.removeEventListener("scroll",this.viewportListener),this.viewportListener=null),this.map.forEach((t,e)=>{t.el.style.strokeDashoffset="",t.el.style.strokeDasharray="",this.renderPath(e);});}isInvisible(t){let e=t.getAttribute("data-ignore");if(e!==null)return e!=="false";if(this.ignoreInvisible){let i=t.getBoundingClientRect();return !i.width&&!i.height}return false}isInViewport(t,e=0){let i=window.pageYOffset||document.documentElement.scrollTop,s=i+Math.max(document.documentElement.clientHeight,window.innerHeight),a=t.getBoundingClientRect(),n=i+a.top;return n+a.height*(e||0)<=s&&n+a.height>=i}};c.LINEAR=t=>t,c.EASE=t=>-Math.cos(t*Math.PI)/2+.5,c.EASE_OUT=t=>1-Math.pow(1-t,3),c.EASE_IN=t=>Math.pow(t,3),c.EASE_OUT_BOUNCE=t=>{let e=-Math.cos(t*(.5*Math.PI))+1,i=Math.pow(e,1.5),s=Math.pow(1-t,2),a=-Math.abs(Math.cos(i*(2.5*Math.PI)))+1;return 1-s+a*s};var p=c,O=p;
|
|
2
|
+
exports.Vivus=p;exports.default=O;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
type VivusType = 'delayed' | 'sync' | 'async' | 'nsync' | 'oneByOne' | 'scenario' | 'scenario-sync';
|
|
2
|
+
type VivusStart = 'inViewport' | 'manual' | 'autostart';
|
|
3
|
+
type VivusTiming = (x: number) => number;
|
|
4
|
+
type VivusCallback = (instance: Vivus) => void;
|
|
5
|
+
interface VivusOptions {
|
|
6
|
+
type?: VivusType;
|
|
7
|
+
/** Load the SVG from this URL into `element` instead of using markup. */
|
|
8
|
+
file?: string;
|
|
9
|
+
start?: VivusStart;
|
|
10
|
+
/** Animation length in frames. Default 120. */
|
|
11
|
+
duration?: number;
|
|
12
|
+
/** For `delayed`: frames between the first and last path starting. Default duration / 3. */
|
|
13
|
+
delay?: number;
|
|
14
|
+
/** Extra gap in the dash pattern, so the line start never shows early. Default 1. */
|
|
15
|
+
dashGap?: number;
|
|
16
|
+
/** Clone-and-replace each path after every update (an old IE/Edge repaint hack). */
|
|
17
|
+
forceRender?: boolean;
|
|
18
|
+
reverseStack?: boolean;
|
|
19
|
+
selfDestroy?: boolean;
|
|
20
|
+
onReady?: VivusCallback;
|
|
21
|
+
ignoreInvisible?: boolean;
|
|
22
|
+
pathTimingFunction?: VivusTiming;
|
|
23
|
+
animTimingFunction?: VivusTiming;
|
|
24
|
+
}
|
|
25
|
+
interface PathRecord {
|
|
26
|
+
el: SVGPathElement;
|
|
27
|
+
length: number;
|
|
28
|
+
startAt: number;
|
|
29
|
+
duration: number;
|
|
30
|
+
isResizeSensitive: boolean;
|
|
31
|
+
progress?: number;
|
|
32
|
+
}
|
|
33
|
+
declare class Vivus {
|
|
34
|
+
static LINEAR: VivusTiming;
|
|
35
|
+
static EASE: VivusTiming;
|
|
36
|
+
static EASE_OUT: VivusTiming;
|
|
37
|
+
static EASE_IN: VivusTiming;
|
|
38
|
+
static EASE_OUT_BOUNCE: VivusTiming;
|
|
39
|
+
el: Element;
|
|
40
|
+
parentEl: Element;
|
|
41
|
+
isReady: boolean;
|
|
42
|
+
type: VivusType;
|
|
43
|
+
start: VivusStart;
|
|
44
|
+
duration: number;
|
|
45
|
+
delay: number | null;
|
|
46
|
+
dashGap: number;
|
|
47
|
+
forceRender: boolean;
|
|
48
|
+
reverseStack: boolean;
|
|
49
|
+
selfDestroy: boolean;
|
|
50
|
+
ignoreInvisible: boolean;
|
|
51
|
+
onReady?: VivusCallback;
|
|
52
|
+
animTimingFunction: VivusTiming;
|
|
53
|
+
pathTimingFunction: VivusTiming;
|
|
54
|
+
callback: VivusCallback;
|
|
55
|
+
map: PathRecord[];
|
|
56
|
+
frameLength: number;
|
|
57
|
+
currentFrame: number;
|
|
58
|
+
delayUnit: number;
|
|
59
|
+
speed: number;
|
|
60
|
+
handle: number | null;
|
|
61
|
+
private instanceCallback;
|
|
62
|
+
private mustRecalcScale;
|
|
63
|
+
private viewportListener;
|
|
64
|
+
constructor(element: string | Element, options?: VivusOptions, callback?: VivusCallback);
|
|
65
|
+
private setElement;
|
|
66
|
+
private setOptions;
|
|
67
|
+
private setCallback;
|
|
68
|
+
/** Measure every path, set its dashes, and work out when each one draws. */
|
|
69
|
+
mapping(): void;
|
|
70
|
+
/** Re-measure `vector-effect: non-scaling-stroke` paths on the next frame (after a resize). */
|
|
71
|
+
recalc(): void;
|
|
72
|
+
performLineRecalc(): void;
|
|
73
|
+
/** One frame: advance by `speed`, render, and finish at either end. */
|
|
74
|
+
draw(): void;
|
|
75
|
+
private finished;
|
|
76
|
+
/** Render the current frame to every path's dash offset. */
|
|
77
|
+
trace(): void;
|
|
78
|
+
renderPath(index: number): void;
|
|
79
|
+
init(): void;
|
|
80
|
+
private starter;
|
|
81
|
+
/** `'start'`, `'progress'` or `'end'`. */
|
|
82
|
+
getStatus(): 'start' | 'progress' | 'end';
|
|
83
|
+
reset(): this;
|
|
84
|
+
finish(): this;
|
|
85
|
+
/** Jump to a point (0–1) and render it. */
|
|
86
|
+
setFrameProgress(progress: number): this;
|
|
87
|
+
/**
|
|
88
|
+
* Animate at `speed` frames per frame (negative plays backwards). The callback
|
|
89
|
+
* may be given alone, as the first argument.
|
|
90
|
+
*/
|
|
91
|
+
play(speed?: number | VivusCallback, callback?: VivusCallback): this;
|
|
92
|
+
stop(): this;
|
|
93
|
+
/** Stop and remove every dash style vivus set. */
|
|
94
|
+
destroy(): void;
|
|
95
|
+
isInvisible(el: Element): boolean;
|
|
96
|
+
/** Whether `el` is in view; with `h` = 1 its whole height must fit above the fold. */
|
|
97
|
+
isInViewport(el: Element, h?: number): boolean;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export { Vivus, type VivusCallback, type VivusOptions, type VivusStart, type VivusTiming, type VivusType, Vivus as default };
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
type VivusType = 'delayed' | 'sync' | 'async' | 'nsync' | 'oneByOne' | 'scenario' | 'scenario-sync';
|
|
2
|
+
type VivusStart = 'inViewport' | 'manual' | 'autostart';
|
|
3
|
+
type VivusTiming = (x: number) => number;
|
|
4
|
+
type VivusCallback = (instance: Vivus) => void;
|
|
5
|
+
interface VivusOptions {
|
|
6
|
+
type?: VivusType;
|
|
7
|
+
/** Load the SVG from this URL into `element` instead of using markup. */
|
|
8
|
+
file?: string;
|
|
9
|
+
start?: VivusStart;
|
|
10
|
+
/** Animation length in frames. Default 120. */
|
|
11
|
+
duration?: number;
|
|
12
|
+
/** For `delayed`: frames between the first and last path starting. Default duration / 3. */
|
|
13
|
+
delay?: number;
|
|
14
|
+
/** Extra gap in the dash pattern, so the line start never shows early. Default 1. */
|
|
15
|
+
dashGap?: number;
|
|
16
|
+
/** Clone-and-replace each path after every update (an old IE/Edge repaint hack). */
|
|
17
|
+
forceRender?: boolean;
|
|
18
|
+
reverseStack?: boolean;
|
|
19
|
+
selfDestroy?: boolean;
|
|
20
|
+
onReady?: VivusCallback;
|
|
21
|
+
ignoreInvisible?: boolean;
|
|
22
|
+
pathTimingFunction?: VivusTiming;
|
|
23
|
+
animTimingFunction?: VivusTiming;
|
|
24
|
+
}
|
|
25
|
+
interface PathRecord {
|
|
26
|
+
el: SVGPathElement;
|
|
27
|
+
length: number;
|
|
28
|
+
startAt: number;
|
|
29
|
+
duration: number;
|
|
30
|
+
isResizeSensitive: boolean;
|
|
31
|
+
progress?: number;
|
|
32
|
+
}
|
|
33
|
+
declare class Vivus {
|
|
34
|
+
static LINEAR: VivusTiming;
|
|
35
|
+
static EASE: VivusTiming;
|
|
36
|
+
static EASE_OUT: VivusTiming;
|
|
37
|
+
static EASE_IN: VivusTiming;
|
|
38
|
+
static EASE_OUT_BOUNCE: VivusTiming;
|
|
39
|
+
el: Element;
|
|
40
|
+
parentEl: Element;
|
|
41
|
+
isReady: boolean;
|
|
42
|
+
type: VivusType;
|
|
43
|
+
start: VivusStart;
|
|
44
|
+
duration: number;
|
|
45
|
+
delay: number | null;
|
|
46
|
+
dashGap: number;
|
|
47
|
+
forceRender: boolean;
|
|
48
|
+
reverseStack: boolean;
|
|
49
|
+
selfDestroy: boolean;
|
|
50
|
+
ignoreInvisible: boolean;
|
|
51
|
+
onReady?: VivusCallback;
|
|
52
|
+
animTimingFunction: VivusTiming;
|
|
53
|
+
pathTimingFunction: VivusTiming;
|
|
54
|
+
callback: VivusCallback;
|
|
55
|
+
map: PathRecord[];
|
|
56
|
+
frameLength: number;
|
|
57
|
+
currentFrame: number;
|
|
58
|
+
delayUnit: number;
|
|
59
|
+
speed: number;
|
|
60
|
+
handle: number | null;
|
|
61
|
+
private instanceCallback;
|
|
62
|
+
private mustRecalcScale;
|
|
63
|
+
private viewportListener;
|
|
64
|
+
constructor(element: string | Element, options?: VivusOptions, callback?: VivusCallback);
|
|
65
|
+
private setElement;
|
|
66
|
+
private setOptions;
|
|
67
|
+
private setCallback;
|
|
68
|
+
/** Measure every path, set its dashes, and work out when each one draws. */
|
|
69
|
+
mapping(): void;
|
|
70
|
+
/** Re-measure `vector-effect: non-scaling-stroke` paths on the next frame (after a resize). */
|
|
71
|
+
recalc(): void;
|
|
72
|
+
performLineRecalc(): void;
|
|
73
|
+
/** One frame: advance by `speed`, render, and finish at either end. */
|
|
74
|
+
draw(): void;
|
|
75
|
+
private finished;
|
|
76
|
+
/** Render the current frame to every path's dash offset. */
|
|
77
|
+
trace(): void;
|
|
78
|
+
renderPath(index: number): void;
|
|
79
|
+
init(): void;
|
|
80
|
+
private starter;
|
|
81
|
+
/** `'start'`, `'progress'` or `'end'`. */
|
|
82
|
+
getStatus(): 'start' | 'progress' | 'end';
|
|
83
|
+
reset(): this;
|
|
84
|
+
finish(): this;
|
|
85
|
+
/** Jump to a point (0–1) and render it. */
|
|
86
|
+
setFrameProgress(progress: number): this;
|
|
87
|
+
/**
|
|
88
|
+
* Animate at `speed` frames per frame (negative plays backwards). The callback
|
|
89
|
+
* may be given alone, as the first argument.
|
|
90
|
+
*/
|
|
91
|
+
play(speed?: number | VivusCallback, callback?: VivusCallback): this;
|
|
92
|
+
stop(): this;
|
|
93
|
+
/** Stop and remove every dash style vivus set. */
|
|
94
|
+
destroy(): void;
|
|
95
|
+
isInvisible(el: Element): boolean;
|
|
96
|
+
/** Whether `el` is in view; with `h` = 1 its whole height must fit above the fold. */
|
|
97
|
+
isInViewport(el: Element, h?: number): boolean;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export { Vivus, type VivusCallback, type VivusOptions, type VivusStart, type VivusTiming, type VivusType, Vivus as default };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function g(){return typeof window>"u"||typeof window.matchMedia!="function"?false:window.matchMedia("(prefers-reduced-motion: reduce)").matches}var w=typeof __SVG_SCROLL_DRAW_DEV__<"u"?__SVG_SCROLL_DRAW_DEV__:typeof process<"u"&&typeof process.env<"u"&&process.env.NODE_ENV!=="production";function m(r,...t){w&&console.warn(`[svg-scroll-draw] ${r}`,...t);}var E=["delayed","sync","async","nsync","oneByOne","scenario","scenario-sync"],L=["inViewport","manual","autostart"];function u(r,t){let e=parseInt(r,10);return e>=0?e:t}function V(r){if(typeof window>"u")return false;let t=window,e=i=>typeof t[i]=="function"&&r instanceof t[i];return e("SVGSVGElement")||e("SVGGElement")||r?.constructor===t.SVGElement}var y=["cx","cy","points","r","rx","ry","x","x1","x2","y","y1","y2"],$=["line","ellipse","circle","polygon","polyline","rect"],x="http://www.w3.org/2000/svg";function v(r){let t=r.points.trim().split(" ");if(r.points.indexOf(",")===-1){let i=[];for(let s=0;s<t.length;s+=2)i.push(`${t[s]},${t[s+1]}`);t=i;}let e=`M${t[0]}`;for(let i=1;i<t.length;i++)t[i].indexOf(",")!==-1&&(e+=`L${t[i]}`);return e}function b(r,t,e,i){let s=parseFloat(e)||0,a=parseFloat(i)||0,n=parseFloat(r)||0,o=parseFloat(t)||0,l=n-s,h=n+s;return `M${l},${o}A${s},${a} 0,1,1 ${h},${o}A${s},${a} 0,1,1 ${l},${o}`}var A={line:r=>`M${r.x1||0},${r.y1||0}L${r.x2||0},${r.y2||0}`,rect(r){let t=parseFloat(r.x)||0,e=parseFloat(r.y)||0,i=parseFloat(r.width)||0,s=parseFloat(r.height)||0;if(r.rx||r.ry){let a=parseInt(r.rx,10)||-1,n=parseInt(r.ry,10)||-1;a=Math.min(Math.max(a<0?n:a,0),i/2),n=Math.min(Math.max(n<0?a:n,0),s/2);let o=`A ${a},${n},0,0,1,`;return `M ${t+a},${e} L ${t+i-a},${e} ${o}${t+i},${e+n} L ${t+i},${e+s-n} ${o}${t+i-a},${e+s} L ${t+a},${e+s} ${o}${t},${e+s-n} L ${t},${e+n} ${o}${t+a},${e}`}return `M${t} ${e} L${t+i} ${e} L${t+i} ${e+s} L${t} ${e+s} Z`},polyline:v,polygon:r=>`${v(r)}Z`,ellipse:r=>b(r.cx,r.cy,r.rx,r.ry),circle:r=>b(r.cx,r.cy,r.r,r.r)};function R(r){for(let t of Array.from(r.querySelectorAll($.join(",")))){let e={};for(let{name:a,value:n}of Array.from(t.attributes)){if(y.indexOf(a)!==-1&&n.indexOf("%")!==-1)throw new Error("Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into 'path' tags. Please use 'viewBox'.");e[a]=n;}let i=A[t.tagName.toLowerCase()](e),s=document.createElementNS(x,"path");for(let{name:a,value:n}of Array.from(t.attributes))y.indexOf(a)===-1&&s.setAttribute(a,n);s.setAttribute("d",i),t.parentNode?.replaceChild(s,t);}}var c=class c{constructor(t,e,i){this.isReady=false;this.type="delayed";this.start="inViewport";this.duration=120;this.delay=null;this.dashGap=1;this.forceRender=false;this.reverseStack=false;this.selfDestroy=false;this.ignoreInvisible=false;this.animTimingFunction=c.LINEAR;this.pathTimingFunction=c.LINEAR;this.callback=()=>{};this.map=[];this.frameLength=0;this.currentFrame=0;this.delayUnit=0;this.speed=1;this.handle=null;this.instanceCallback=null;this.mustRecalcScale=null;this.viewportListener=null;this.setElement(t,e),this.setOptions(e),this.setCallback(i),this.isReady&&this.init();}setElement(t,e){if(t===void 0)throw new Error('Vivus [constructor]: "element" parameter is required');let i=t;if(typeof i=="string"){let s=document.getElementById(i);if(!s)throw new Error('Vivus [constructor]: "element" parameter is not related to an existing ID');i=s;}if(this.parentEl=i,e&&e.file){let s=new XMLHttpRequest;s.addEventListener("load",()=>{let a=document.createElement("div");a.innerHTML=s.responseText;let n=a.querySelector("svg");if(!n)throw new Error(`Vivus [load]: Cannot find the SVG in the loaded file : ${e.file}`);this.el=n,n.setAttribute("width","100%"),n.setAttribute("height","100%"),this.parentEl.appendChild(n),this.isReady=true,this.init();}),s.open("GET",e.file),s.send();return}if(V(i)){this.el=i,this.isReady=true;return}if(i instanceof HTMLObjectElement){let s=i,a=n=>{if(this.isReady)return;let o=s.contentDocument&&s.contentDocument.querySelector("svg");if(!o&&n)throw new Error("Vivus [constructor]: object loaded does not contain any SVG");o&&(s.getAttribute("built-by-vivus")&&(this.parentEl.insertBefore(o,s),this.parentEl.removeChild(s),o.setAttribute("width","100%"),o.setAttribute("height","100%")),this.el=o,this.isReady=true,this.init());};a(),this.isReady||s.addEventListener("load",a);return}throw new Error('Vivus [constructor]: "element" parameter is not valid (or miss the "file" attribute)')}setOptions(t){if(t!==void 0&&(t===null||t.constructor!==Object))throw new Error('Vivus [constructor]: "options" parameter must be an object');let e=t||{};if(e.type&&E.indexOf(e.type)===-1)throw new Error(`Vivus [constructor]: ${e.type} is not an existing animation \`type\``);if(e.start&&L.indexOf(e.start)===-1)throw new Error(`Vivus [constructor]: ${e.start} is not an existing \`start\` option`);this.type=e.type||"delayed",this.start=e.start||"inViewport";let i=navigator.userAgent,s=i.indexOf("MSIE")!==-1||i.indexOf("Trident/")!==-1||i.indexOf("Edge/")!==-1;if(this.duration=u(e.duration,120),this.delay=u(e.delay,null),this.dashGap=u(e.dashGap,1),this.forceRender=Object.prototype.hasOwnProperty.call(e,"forceRender")?!!e.forceRender:s,this.reverseStack=!!e.reverseStack,this.selfDestroy=!!e.selfDestroy,this.onReady=e.onReady,this.map=[],this.ignoreInvisible=Object.prototype.hasOwnProperty.call(e,"ignoreInvisible")?!!e.ignoreInvisible:false,this.animTimingFunction=e.animTimingFunction||c.LINEAR,this.pathTimingFunction=e.pathTimingFunction||c.LINEAR,this.delay!==null&&this.delay>=this.duration)throw new Error("Vivus [constructor]: delay must be shorter than duration")}setCallback(t){if(t&&typeof t!="function")throw new Error('Vivus [constructor]: "callback" parameter must be a function');this.callback=t||(()=>{});}mapping(){let t=0,e=0,i=0,s=false,a=Array.from(this.el.querySelectorAll("path"));a.forEach((n,o)=>{if(this.isInvisible(n))return;let l={el:n,length:0,startAt:0,duration:0,isResizeSensitive:false},h=1;if(n.getAttribute("vector-effect")==="non-scaling-stroke"){let d=n.getBoundingClientRect(),f=n.getBBox();h=Math.max(d.width/f.width,d.height/f.height),l.isResizeSensitive=true,s=true;}if(l.length=Math.ceil(n.getTotalLength()*h),isNaN(l.length)){m("vivus: cannot retrieve a path element length",n);return}this.map.push(l),n.style.strokeDasharray=`${l.length} ${l.length+this.dashGap*2}`,n.style.strokeDashoffset=String(l.length+this.dashGap),l.length+=this.dashGap,e+=l.length,this.renderPath(o);}),s&&m("vivus: this SVG contains non-scaling-strokes. Call instance.recalc() when the SVG is resized."),e=e===0?1:e,this.delay=this.delay===null?this.duration/3:this.delay,this.delayUnit=this.delay/(a.length>1?a.length-1:1),this.reverseStack&&this.map.reverse(),this.map.forEach((n,o)=>{let l=()=>{let h={};for(let{name:d,value:f}of Array.from(n.el.attributes))h[d]=f;return h};switch(this.type){case "delayed":n.startAt=this.delayUnit*o,n.duration=this.duration-this.delay;break;case "oneByOne":n.startAt=i/e*this.duration,n.duration=n.length/e*this.duration;break;case "sync":case "async":case "nsync":n.startAt=0,n.duration=this.duration;break;case "scenario-sync":{let h=l();n.startAt=t+(u(h["data-delay"],this.delayUnit)||0),n.duration=u(h["data-duration"],this.duration),t=h["data-async"]!==void 0?n.startAt:n.startAt+n.duration,this.frameLength=Math.max(this.frameLength,n.startAt+n.duration);break}case "scenario":{let h=l();n.startAt=u(h["data-start"],this.delayUnit)||0,n.duration=u(h["data-duration"],this.duration),this.frameLength=Math.max(this.frameLength,n.startAt+n.duration);break}}i+=n.length,this.frameLength=this.frameLength||this.duration;});}recalc(){this.mustRecalcScale||(this.mustRecalcScale=requestAnimationFrame(()=>this.performLineRecalc()));}performLineRecalc(){for(let t of this.map){if(!t.isResizeSensitive)continue;let e=t.el.getBoundingClientRect(),i=t.el.getBBox(),s=Math.max(e.width/i.width,e.height/i.height);t.length=Math.ceil(t.el.getTotalLength()*s),t.el.style.strokeDasharray=`${t.length} ${t.length+this.dashGap*2}`;}this.trace(),this.mustRecalcScale=null;}draw(){if(this.currentFrame+=this.speed,this.currentFrame<=0)this.stop(),this.reset();else if(this.currentFrame>=this.frameLength)this.stop(),this.currentFrame=this.frameLength,this.trace(),this.selfDestroy&&this.destroy();else {this.trace(),this.handle=requestAnimationFrame(()=>this.draw());return}this.finished();}finished(){if(this.callback(this),this.instanceCallback){let t=this.instanceCallback;this.instanceCallback=null,t(this);}}trace(){let t=this.animTimingFunction(this.currentFrame/this.frameLength)*this.frameLength;this.map.forEach((e,i)=>{let s=this.pathTimingFunction(Math.max(0,Math.min(1,(t-e.startAt)/e.duration)));e.progress!==s&&(e.progress=s,e.el.style.strokeDashoffset=String(Math.floor(e.length*(1-s))),this.renderPath(i));});}renderPath(t){let e=this.forceRender&&this.map&&this.map[t];if(!e)return;let i=e.el.cloneNode(true);e.el.parentNode?.replaceChild(i,e.el),e.el=i;}init(){this.frameLength=0,this.currentFrame=0,this.map=[],R(this.el),this.mapping(),this.starter(),this.onReady&&this.onReady(this);}starter(){if(this.start==="manual")return;if(this.start==="autostart"){this.play();return}let t=()=>{this.isInViewport(this.parentEl,1)&&(this.play(),window.removeEventListener("scroll",t),this.viewportListener=null);};this.viewportListener=t,window.addEventListener("scroll",t),t();}getStatus(){return this.currentFrame===0?"start":this.currentFrame===this.frameLength?"end":"progress"}reset(){return this.setFrameProgress(0)}finish(){return this.setFrameProgress(1)}setFrameProgress(t){let e=Math.min(1,Math.max(0,t));return this.currentFrame=Math.round(this.frameLength*e),this.trace(),this}play(t,e){this.instanceCallback=null;let i=t;if(i&&typeof i=="function")this.instanceCallback=i,i=void 0;else if(i&&typeof i!="number")throw new Error("Vivus [play]: invalid speed");return e&&typeof e=="function"&&!this.instanceCallback&&(this.instanceCallback=e),this.speed=i||1,g()?(this.stop(),this.currentFrame=this.speed<0?0:this.frameLength,this.trace(),this.speed>0&&this.selfDestroy&&this.destroy(),this.finished(),this):(this.handle||this.draw(),this)}stop(){return this.handle&&(cancelAnimationFrame(this.handle),this.handle=null),this}destroy(){this.stop(),this.viewportListener&&(window.removeEventListener("scroll",this.viewportListener),this.viewportListener=null),this.map.forEach((t,e)=>{t.el.style.strokeDashoffset="",t.el.style.strokeDasharray="",this.renderPath(e);});}isInvisible(t){let e=t.getAttribute("data-ignore");if(e!==null)return e!=="false";if(this.ignoreInvisible){let i=t.getBoundingClientRect();return !i.width&&!i.height}return false}isInViewport(t,e=0){let i=window.pageYOffset||document.documentElement.scrollTop,s=i+Math.max(document.documentElement.clientHeight,window.innerHeight),a=t.getBoundingClientRect(),n=i+a.top;return n+a.height*(e||0)<=s&&n+a.height>=i}};c.LINEAR=t=>t,c.EASE=t=>-Math.cos(t*Math.PI)/2+.5,c.EASE_OUT=t=>1-Math.pow(1-t,3),c.EASE_IN=t=>Math.pow(t,3),c.EASE_OUT_BOUNCE=t=>{let e=-Math.cos(t*(.5*Math.PI))+1,i=Math.pow(e,1.5),s=Math.pow(1-t,2),a=-Math.abs(Math.cos(i*(2.5*Math.PI)))+1;return 1-s+a*s};var p=c,O=p;
|
|
2
|
+
export{p as Vivus,O as default};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svg-scroll-draw",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.13.0",
|
|
4
4
|
"description": "Scroll-driven animation for the web — draw SVG paths, reveal elements, pin sections, scrub video. Zero dependencies, native CSS fast path, works with React, Vue, Svelte, Solid, Angular, Astro and vanilla JS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"svg",
|
|
@@ -62,7 +62,11 @@
|
|
|
62
62
|
"data-aos",
|
|
63
63
|
"scrollreveal",
|
|
64
64
|
"scrollreveal-alternative",
|
|
65
|
-
"scroll-reveal-mit"
|
|
65
|
+
"scroll-reveal-mit",
|
|
66
|
+
"vivus",
|
|
67
|
+
"vivus-alternative",
|
|
68
|
+
"svg-line-drawing",
|
|
69
|
+
"line-drawing"
|
|
66
70
|
],
|
|
67
71
|
"homepage": "https://svg-scroll-draw.vercel.app",
|
|
68
72
|
"repository": {
|
|
@@ -151,6 +155,9 @@
|
|
|
151
155
|
],
|
|
152
156
|
"scrollreveal": [
|
|
153
157
|
"./dist/scrollreveal/index.d.ts"
|
|
158
|
+
],
|
|
159
|
+
"vivus": [
|
|
160
|
+
"./dist/vivus/index.d.ts"
|
|
154
161
|
]
|
|
155
162
|
}
|
|
156
163
|
},
|
|
@@ -390,6 +397,16 @@
|
|
|
390
397
|
"default": "./dist/scrollreveal/index.cjs"
|
|
391
398
|
}
|
|
392
399
|
},
|
|
400
|
+
"./vivus": {
|
|
401
|
+
"import": {
|
|
402
|
+
"types": "./dist/vivus/index.d.mts",
|
|
403
|
+
"default": "./dist/vivus/index.mjs"
|
|
404
|
+
},
|
|
405
|
+
"require": {
|
|
406
|
+
"types": "./dist/vivus/index.d.ts",
|
|
407
|
+
"default": "./dist/vivus/index.cjs"
|
|
408
|
+
}
|
|
409
|
+
},
|
|
393
410
|
"./package.json": "./package.json"
|
|
394
411
|
},
|
|
395
412
|
"scripts": {
|
|
@@ -417,6 +434,7 @@
|
|
|
417
434
|
"tsup": "^8.0.0",
|
|
418
435
|
"typescript": "^5.0.0",
|
|
419
436
|
"vitest": "^2.0.0",
|
|
437
|
+
"vivus": "^0.4.6",
|
|
420
438
|
"vue": "^3.5.34"
|
|
421
439
|
},
|
|
422
440
|
"sideEffects": [
|
|
@@ -424,7 +442,8 @@
|
|
|
424
442
|
"./dist/cdn/*",
|
|
425
443
|
"./src/web-component/*",
|
|
426
444
|
"./src/cdn.ts",
|
|
427
|
-
"./src/scrollreveal/cdn.ts"
|
|
445
|
+
"./src/scrollreveal/cdn.ts",
|
|
446
|
+
"./src/vivus/cdn.ts"
|
|
428
447
|
],
|
|
429
448
|
"engines": {
|
|
430
449
|
"node": ">=18"
|
package/dist/aos/index.d.mts
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
type AOSAnchorPlacement = 'top-bottom' | 'top-center' | 'top-top' | 'center-bottom' | 'center-center' | 'center-top' | 'bottom-bottom' | 'bottom-center' | 'bottom-top';
|
|
2
|
-
interface AOSOptions {
|
|
3
|
-
/** Px from the trigger point before the animation starts. Default 120. */
|
|
4
|
-
offset?: number;
|
|
5
|
-
/** Ms to wait before animating in. Default 0. */
|
|
6
|
-
delay?: number;
|
|
7
|
-
/** Animation length in ms. Default 400. */
|
|
8
|
-
duration?: number;
|
|
9
|
-
/** An AOS easing name (`'ease-out-back'`…) or any CSS timing function. Default `'ease'`. */
|
|
10
|
-
easing?: string;
|
|
11
|
-
/** Animate only the first time the element scrolls in. Default false. */
|
|
12
|
-
once?: boolean;
|
|
13
|
-
/** Animate out again when the element scrolls past the top. Default false. */
|
|
14
|
-
mirror?: boolean;
|
|
15
|
-
/** Which edge of the element meets which edge of the window. Default `'top-bottom'`. */
|
|
16
|
-
anchorPlacement?: AOSAnchorPlacement;
|
|
17
|
-
/** Skip animations entirely: a boolean, a predicate, or a viewport class. */
|
|
18
|
-
disable?: boolean | 'phone' | 'tablet' | 'mobile' | (() => boolean);
|
|
19
|
-
/** Document event that starts AOS. Default `'DOMContentLoaded'`. */
|
|
20
|
-
startEvent?: string;
|
|
21
|
-
/** Do not watch the DOM for new `[data-aos]` elements. Default false. */
|
|
22
|
-
disableMutationObserver?: boolean;
|
|
23
|
-
/** Class added at init. Default `'aos-init'`. */
|
|
24
|
-
initClassName?: string;
|
|
25
|
-
/** Class added while animated in. Default `'aos-animate'`. */
|
|
26
|
-
animatedClassName?: string;
|
|
27
|
-
/** Also add the `data-aos` value as classes (for animate.css-style sets). Default false. */
|
|
28
|
-
useClassNames?: boolean;
|
|
29
|
-
/** Accepted for compatibility; scroll handling is batched per frame instead. */
|
|
30
|
-
throttleDelay?: number;
|
|
31
|
-
/** Accepted for compatibility; resize handling is debounced internally. */
|
|
32
|
-
debounceDelay?: number;
|
|
33
|
-
}
|
|
34
|
-
/** Start animating every `[data-aos]` element. Same options as AOS. */
|
|
35
|
-
declare function init(options?: AOSOptions): HTMLElement[];
|
|
36
|
-
/** Recalculate every trigger position (after a layout change). */
|
|
37
|
-
declare function refresh(): void;
|
|
38
|
-
/** Find `[data-aos]` elements again (after adding or removing some), then refresh. */
|
|
39
|
-
declare function refreshHard(): void;
|
|
40
|
-
/**
|
|
41
|
-
* Stop listening and remove the injected stylesheet. Not in AOS — added for
|
|
42
|
-
* single-page apps that unmount the page AOS was started on. Elements keep
|
|
43
|
-
* whatever classes they have.
|
|
44
|
-
*/
|
|
45
|
-
declare function destroy(): void;
|
|
46
|
-
declare const AOS: {
|
|
47
|
-
init: typeof init;
|
|
48
|
-
refresh: typeof refresh;
|
|
49
|
-
refreshHard: typeof refreshHard;
|
|
50
|
-
destroy: typeof destroy;
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
export { type AOSAnchorPlacement, type AOSOptions, AOS as default, destroy, init, refresh, refreshHard };
|
package/dist/aos/index.d.ts
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
type AOSAnchorPlacement = 'top-bottom' | 'top-center' | 'top-top' | 'center-bottom' | 'center-center' | 'center-top' | 'bottom-bottom' | 'bottom-center' | 'bottom-top';
|
|
2
|
-
interface AOSOptions {
|
|
3
|
-
/** Px from the trigger point before the animation starts. Default 120. */
|
|
4
|
-
offset?: number;
|
|
5
|
-
/** Ms to wait before animating in. Default 0. */
|
|
6
|
-
delay?: number;
|
|
7
|
-
/** Animation length in ms. Default 400. */
|
|
8
|
-
duration?: number;
|
|
9
|
-
/** An AOS easing name (`'ease-out-back'`…) or any CSS timing function. Default `'ease'`. */
|
|
10
|
-
easing?: string;
|
|
11
|
-
/** Animate only the first time the element scrolls in. Default false. */
|
|
12
|
-
once?: boolean;
|
|
13
|
-
/** Animate out again when the element scrolls past the top. Default false. */
|
|
14
|
-
mirror?: boolean;
|
|
15
|
-
/** Which edge of the element meets which edge of the window. Default `'top-bottom'`. */
|
|
16
|
-
anchorPlacement?: AOSAnchorPlacement;
|
|
17
|
-
/** Skip animations entirely: a boolean, a predicate, or a viewport class. */
|
|
18
|
-
disable?: boolean | 'phone' | 'tablet' | 'mobile' | (() => boolean);
|
|
19
|
-
/** Document event that starts AOS. Default `'DOMContentLoaded'`. */
|
|
20
|
-
startEvent?: string;
|
|
21
|
-
/** Do not watch the DOM for new `[data-aos]` elements. Default false. */
|
|
22
|
-
disableMutationObserver?: boolean;
|
|
23
|
-
/** Class added at init. Default `'aos-init'`. */
|
|
24
|
-
initClassName?: string;
|
|
25
|
-
/** Class added while animated in. Default `'aos-animate'`. */
|
|
26
|
-
animatedClassName?: string;
|
|
27
|
-
/** Also add the `data-aos` value as classes (for animate.css-style sets). Default false. */
|
|
28
|
-
useClassNames?: boolean;
|
|
29
|
-
/** Accepted for compatibility; scroll handling is batched per frame instead. */
|
|
30
|
-
throttleDelay?: number;
|
|
31
|
-
/** Accepted for compatibility; resize handling is debounced internally. */
|
|
32
|
-
debounceDelay?: number;
|
|
33
|
-
}
|
|
34
|
-
/** Start animating every `[data-aos]` element. Same options as AOS. */
|
|
35
|
-
declare function init(options?: AOSOptions): HTMLElement[];
|
|
36
|
-
/** Recalculate every trigger position (after a layout change). */
|
|
37
|
-
declare function refresh(): void;
|
|
38
|
-
/** Find `[data-aos]` elements again (after adding or removing some), then refresh. */
|
|
39
|
-
declare function refreshHard(): void;
|
|
40
|
-
/**
|
|
41
|
-
* Stop listening and remove the injected stylesheet. Not in AOS — added for
|
|
42
|
-
* single-page apps that unmount the page AOS was started on. Elements keep
|
|
43
|
-
* whatever classes they have.
|
|
44
|
-
*/
|
|
45
|
-
declare function destroy(): void;
|
|
46
|
-
declare const AOS: {
|
|
47
|
-
init: typeof init;
|
|
48
|
-
refresh: typeof refresh;
|
|
49
|
-
refreshHard: typeof refreshHard;
|
|
50
|
-
destroy: typeof destroy;
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
export { type AOSAnchorPlacement, type AOSOptions, AOS as default, destroy, init, refresh, refreshHard };
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
type StoryEasing = 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out' | 'spring' | 'bounce' | 'elastic';
|
|
2
|
-
/** A traced path that strokes itself on across a scroll range. */
|
|
3
|
-
interface DrawAnimation {
|
|
4
|
-
type: 'draw';
|
|
5
|
-
/** DOM id the runtime binds to (with leading '#'), e.g. "#path-3". */
|
|
6
|
-
target: string;
|
|
7
|
-
/** SVG path data, in canvas coordinates. */
|
|
8
|
-
d: string;
|
|
9
|
-
/** Pre-measured total path length (px). */
|
|
10
|
-
length: number;
|
|
11
|
-
/** Scroll progress where the draw begins, e.g. "20%". */
|
|
12
|
-
start: string;
|
|
13
|
-
/** Scroll progress where the draw completes, e.g. "50%". */
|
|
14
|
-
end: string;
|
|
15
|
-
stroke: string;
|
|
16
|
-
strokeWidth: number;
|
|
17
|
-
easing: StoryEasing;
|
|
18
|
-
}
|
|
19
|
-
/** Any layer fading opacity across a scroll range. */
|
|
20
|
-
interface FadeAnimation {
|
|
21
|
-
type: 'fade';
|
|
22
|
-
target: string;
|
|
23
|
-
start: string;
|
|
24
|
-
end: string;
|
|
25
|
-
from: number;
|
|
26
|
-
to: number;
|
|
27
|
-
}
|
|
28
|
-
type StoryAnimation = DrawAnimation | FadeAnimation;
|
|
29
|
-
interface StoryScene {
|
|
30
|
-
id: string;
|
|
31
|
-
/** Optional background layer (a product photo) as a data URL or remote URL. */
|
|
32
|
-
background?: string;
|
|
33
|
-
animations: StoryAnimation[];
|
|
34
|
-
}
|
|
35
|
-
interface Story {
|
|
36
|
-
version: 1;
|
|
37
|
-
/** Total scroll height of the experience, e.g. "400vh". */
|
|
38
|
-
totalHeight: string;
|
|
39
|
-
/** The authoring viewBox the coordinates are expressed in. */
|
|
40
|
-
canvas: {
|
|
41
|
-
width: number;
|
|
42
|
-
height: number;
|
|
43
|
-
};
|
|
44
|
-
scenes: StoryScene[];
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
interface CinematicOptions {
|
|
48
|
-
/** Mount point — a selector or element. Becomes the scroll wrapper. */
|
|
49
|
-
wrapper: string | HTMLElement;
|
|
50
|
-
}
|
|
51
|
-
interface CinematicInstance {
|
|
52
|
-
/** Stop the scroll loop and detach observers (built DOM is left in place). */
|
|
53
|
-
destroy: () => void;
|
|
54
|
-
/** Current global scroll progress through the story (0–1). */
|
|
55
|
-
getProgress: () => number;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* The viral loader. Reads a Cinematic Story (authored in the Studio) and wires
|
|
59
|
-
* a scroll-scrubbed timeline: paths stroke themselves on and layers fade in as
|
|
60
|
-
* the user scrolls, all driven off the wrapper's scroll progress.
|
|
61
|
-
*
|
|
62
|
-
* import { Cinematic } from "svg-scroll-draw";
|
|
63
|
-
* import story from "./story.json";
|
|
64
|
-
* new Cinematic({ wrapper: "#app" }).loadStory(story);
|
|
65
|
-
*/
|
|
66
|
-
declare class Cinematic {
|
|
67
|
-
private mount;
|
|
68
|
-
constructor(options: CinematicOptions);
|
|
69
|
-
loadStory(story: Story): CinematicInstance;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export { Cinematic, type CinematicInstance, type CinematicOptions, type DrawAnimation, type FadeAnimation, type Story, type StoryAnimation, type StoryEasing, type StoryScene };
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
type StoryEasing = 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out' | 'spring' | 'bounce' | 'elastic';
|
|
2
|
-
/** A traced path that strokes itself on across a scroll range. */
|
|
3
|
-
interface DrawAnimation {
|
|
4
|
-
type: 'draw';
|
|
5
|
-
/** DOM id the runtime binds to (with leading '#'), e.g. "#path-3". */
|
|
6
|
-
target: string;
|
|
7
|
-
/** SVG path data, in canvas coordinates. */
|
|
8
|
-
d: string;
|
|
9
|
-
/** Pre-measured total path length (px). */
|
|
10
|
-
length: number;
|
|
11
|
-
/** Scroll progress where the draw begins, e.g. "20%". */
|
|
12
|
-
start: string;
|
|
13
|
-
/** Scroll progress where the draw completes, e.g. "50%". */
|
|
14
|
-
end: string;
|
|
15
|
-
stroke: string;
|
|
16
|
-
strokeWidth: number;
|
|
17
|
-
easing: StoryEasing;
|
|
18
|
-
}
|
|
19
|
-
/** Any layer fading opacity across a scroll range. */
|
|
20
|
-
interface FadeAnimation {
|
|
21
|
-
type: 'fade';
|
|
22
|
-
target: string;
|
|
23
|
-
start: string;
|
|
24
|
-
end: string;
|
|
25
|
-
from: number;
|
|
26
|
-
to: number;
|
|
27
|
-
}
|
|
28
|
-
type StoryAnimation = DrawAnimation | FadeAnimation;
|
|
29
|
-
interface StoryScene {
|
|
30
|
-
id: string;
|
|
31
|
-
/** Optional background layer (a product photo) as a data URL or remote URL. */
|
|
32
|
-
background?: string;
|
|
33
|
-
animations: StoryAnimation[];
|
|
34
|
-
}
|
|
35
|
-
interface Story {
|
|
36
|
-
version: 1;
|
|
37
|
-
/** Total scroll height of the experience, e.g. "400vh". */
|
|
38
|
-
totalHeight: string;
|
|
39
|
-
/** The authoring viewBox the coordinates are expressed in. */
|
|
40
|
-
canvas: {
|
|
41
|
-
width: number;
|
|
42
|
-
height: number;
|
|
43
|
-
};
|
|
44
|
-
scenes: StoryScene[];
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
interface CinematicOptions {
|
|
48
|
-
/** Mount point — a selector or element. Becomes the scroll wrapper. */
|
|
49
|
-
wrapper: string | HTMLElement;
|
|
50
|
-
}
|
|
51
|
-
interface CinematicInstance {
|
|
52
|
-
/** Stop the scroll loop and detach observers (built DOM is left in place). */
|
|
53
|
-
destroy: () => void;
|
|
54
|
-
/** Current global scroll progress through the story (0–1). */
|
|
55
|
-
getProgress: () => number;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* The viral loader. Reads a Cinematic Story (authored in the Studio) and wires
|
|
59
|
-
* a scroll-scrubbed timeline: paths stroke themselves on and layers fade in as
|
|
60
|
-
* the user scrolls, all driven off the wrapper's scroll progress.
|
|
61
|
-
*
|
|
62
|
-
* import { Cinematic } from "svg-scroll-draw";
|
|
63
|
-
* import story from "./story.json";
|
|
64
|
-
* new Cinematic({ wrapper: "#app" }).loadStory(story);
|
|
65
|
-
*/
|
|
66
|
-
declare class Cinematic {
|
|
67
|
-
private mount;
|
|
68
|
-
constructor(options: CinematicOptions);
|
|
69
|
-
loadStory(story: Story): CinematicInstance;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export { Cinematic, type CinematicInstance, type CinematicOptions, type DrawAnimation, type FadeAnimation, type Story, type StoryAnimation, type StoryEasing, type StoryScene };
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
declare function enable(): void;
|
|
2
|
-
declare function disable(): void;
|
|
3
|
-
declare function toggle(): void;
|
|
4
|
-
declare function highlight(target: string | Element): void;
|
|
5
|
-
declare const devtools: {
|
|
6
|
-
enable: typeof enable;
|
|
7
|
-
disable: typeof disable;
|
|
8
|
-
toggle: typeof toggle;
|
|
9
|
-
highlight: typeof highlight;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export { devtools };
|
package/dist/devtools/index.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
declare function enable(): void;
|
|
2
|
-
declare function disable(): void;
|
|
3
|
-
declare function toggle(): void;
|
|
4
|
-
declare function highlight(target: string | Element): void;
|
|
5
|
-
declare const devtools: {
|
|
6
|
-
enable: typeof enable;
|
|
7
|
-
disable: typeof disable;
|
|
8
|
-
toggle: typeof toggle;
|
|
9
|
-
highlight: typeof highlight;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export { devtools };
|
package/dist/text/index.d.mts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
type EasingName = 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out' | 'spring' | 'bounce' | 'elastic';
|
|
2
|
-
interface TriggerConfig {
|
|
3
|
-
start?: string;
|
|
4
|
-
end?: string;
|
|
5
|
-
}
|
|
6
|
-
interface ScrollDrawInstance {
|
|
7
|
-
destroy: () => void;
|
|
8
|
-
/** Reset and replay the animation from the beginning. */
|
|
9
|
-
replay: () => void;
|
|
10
|
-
/** Pause the animation at the current progress. */
|
|
11
|
-
pause: () => void;
|
|
12
|
-
/** Resume a paused animation. */
|
|
13
|
-
resume: () => void;
|
|
14
|
-
/** Jump to a specific progress value (0–1) and pause. */
|
|
15
|
-
seek: (progress: number) => void;
|
|
16
|
-
/** Returns current draw progress (0–1). */
|
|
17
|
-
getProgress: () => number;
|
|
18
|
-
/**
|
|
19
|
-
* Re-measure after a layout change: path lengths, and the scroll trigger window.
|
|
20
|
-
*
|
|
21
|
-
* The engine already re-measures on `resize`, on `orientationchange`, and via a
|
|
22
|
-
* `ResizeObserver` on the document element — but none of those fire for a layout
|
|
23
|
-
* change that leaves the document height alone, such as a tab switching, a
|
|
24
|
-
* sibling collapsing, or a font swapping inside a fixed-height box. Call this
|
|
25
|
-
* after one of those.
|
|
26
|
-
*
|
|
27
|
-
* Optional on this shared type because several instances here are fan-outs over
|
|
28
|
-
* other instances or SSR no-op stubs. `scrollDraw`, `scrollPin`,
|
|
29
|
-
* `scrollHorizontal`, `scrollDrawTimeline` and the group APIs all provide it;
|
|
30
|
-
* use `instance.refresh?.()` if you hold an instance of unknown origin.
|
|
31
|
-
*/
|
|
32
|
-
refresh?: () => void;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
interface ScrollTextOptions {
|
|
36
|
-
split?: 'chars' | 'words' | 'lines';
|
|
37
|
-
stagger?: number;
|
|
38
|
-
easing?: EasingName | ((t: number) => number);
|
|
39
|
-
from?: {
|
|
40
|
-
opacity?: number;
|
|
41
|
-
y?: number;
|
|
42
|
-
x?: number;
|
|
43
|
-
rotate?: number;
|
|
44
|
-
scale?: number;
|
|
45
|
-
};
|
|
46
|
-
trigger?: TriggerConfig;
|
|
47
|
-
once?: boolean;
|
|
48
|
-
onComplete?: () => void;
|
|
49
|
-
}
|
|
50
|
-
declare function scrollText(target: string | Element, options?: ScrollTextOptions): ScrollDrawInstance;
|
|
51
|
-
|
|
52
|
-
export { type ScrollTextOptions, scrollText };
|
package/dist/text/index.d.ts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
type EasingName = 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out' | 'spring' | 'bounce' | 'elastic';
|
|
2
|
-
interface TriggerConfig {
|
|
3
|
-
start?: string;
|
|
4
|
-
end?: string;
|
|
5
|
-
}
|
|
6
|
-
interface ScrollDrawInstance {
|
|
7
|
-
destroy: () => void;
|
|
8
|
-
/** Reset and replay the animation from the beginning. */
|
|
9
|
-
replay: () => void;
|
|
10
|
-
/** Pause the animation at the current progress. */
|
|
11
|
-
pause: () => void;
|
|
12
|
-
/** Resume a paused animation. */
|
|
13
|
-
resume: () => void;
|
|
14
|
-
/** Jump to a specific progress value (0–1) and pause. */
|
|
15
|
-
seek: (progress: number) => void;
|
|
16
|
-
/** Returns current draw progress (0–1). */
|
|
17
|
-
getProgress: () => number;
|
|
18
|
-
/**
|
|
19
|
-
* Re-measure after a layout change: path lengths, and the scroll trigger window.
|
|
20
|
-
*
|
|
21
|
-
* The engine already re-measures on `resize`, on `orientationchange`, and via a
|
|
22
|
-
* `ResizeObserver` on the document element — but none of those fire for a layout
|
|
23
|
-
* change that leaves the document height alone, such as a tab switching, a
|
|
24
|
-
* sibling collapsing, or a font swapping inside a fixed-height box. Call this
|
|
25
|
-
* after one of those.
|
|
26
|
-
*
|
|
27
|
-
* Optional on this shared type because several instances here are fan-outs over
|
|
28
|
-
* other instances or SSR no-op stubs. `scrollDraw`, `scrollPin`,
|
|
29
|
-
* `scrollHorizontal`, `scrollDrawTimeline` and the group APIs all provide it;
|
|
30
|
-
* use `instance.refresh?.()` if you hold an instance of unknown origin.
|
|
31
|
-
*/
|
|
32
|
-
refresh?: () => void;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
interface ScrollTextOptions {
|
|
36
|
-
split?: 'chars' | 'words' | 'lines';
|
|
37
|
-
stagger?: number;
|
|
38
|
-
easing?: EasingName | ((t: number) => number);
|
|
39
|
-
from?: {
|
|
40
|
-
opacity?: number;
|
|
41
|
-
y?: number;
|
|
42
|
-
x?: number;
|
|
43
|
-
rotate?: number;
|
|
44
|
-
scale?: number;
|
|
45
|
-
};
|
|
46
|
-
trigger?: TriggerConfig;
|
|
47
|
-
once?: boolean;
|
|
48
|
-
onComplete?: () => void;
|
|
49
|
-
}
|
|
50
|
-
declare function scrollText(target: string | Element, options?: ScrollTextOptions): ScrollDrawInstance;
|
|
51
|
-
|
|
52
|
-
export { type ScrollTextOptions, scrollText };
|