cropt2 2.0.19 → 2.0.20
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/cropt.esm.min.js +1 -1
- package/dist/cropt.min.css +1 -1
- package/dist/cropt.min.js +1 -1
- package/package.json +7 -7
package/dist/cropt.esm.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function t(){return{boundary:document.createElement("div"),viewport:document.createElement("div"),preview:document.createElement("img"),overlay:document.createElement("div"),controls:document.createElement("div"),resizeHandleRight:document.createElement("div"),resizeHandleBottom:document.createElement("div"),toolBar:document.createElement("div"),zoomer:document.createElement("input"),rotateLeft:document.createElement("button"),rotateRight:document.createElement("button")}}function e(t,e,i){return Math.round(Math.max(Math.min(t,e),i))}export default class{element;elements;options={mouseWheelZoom:"on",viewport:{width:0,height:0,borderRadius:"0px"},zoomerInputClass:"cr-slider",enableZoomSlider:!0,enableKeypress:!1,resizeBars:!1,enableRotateBtns:!1};#t=.85;#e=50;#i=50;#o=1;#n=0;#s=!1;#r="#fff";#a=new AbortController;#l=function(t){let e;return(...i)=>{window.clearTimeout(e),e=window.setTimeout(()=>t(...i),100)}}(()=>{this.#h()});constructor(e,i){if(e.classList.contains("cropt-container"))throw new Error("Cropt appears initialized (element has 'cropt-container' class). Aborting.");i.viewport&&(i.viewport={...this.options.viewport,...i.viewport},(!i.viewport?.width||i.viewport.width<100)&&(i.viewport.width=Math.max(100,e.clientWidth-60)),(!i.viewport?.height||i.viewport.height<100)&&(i.viewport.height=Math.max(100,e.clientHeight-60))),this.options={...this.options,...i},this.options.transparencyColor&&(this.#r=this.options.transparencyColor),this.element=e,this.element.classList.add("cropt-container"),this.elements=t(),this.elements.toolBar.classList.add("cr-toolbar-wrap"),this.elements.boundary.classList.add("cr-boundary"),this.elements.viewport.classList.add("cr-viewport"),this.elements.overlay.classList.add("cr-overlay"),this.elements.controls.classList.add("cr-controls"),this.elements.viewport.setAttribute("tabindex","0"),this.#d(this.elements.preview),this.elements.boundary.appendChild(this.elements.preview),this.elements.boundary.appendChild(this.elements.viewport),this.elements.boundary.appendChild(this.elements.overlay),this.elements.boundary.appendChild(this.elements.controls),this.#m(),this.options.enableRotateBtns&&(this.elements.rotateLeft.type="button",this.elements.rotateLeft.innerHTML="↺",this.elements.rotateLeft.setAttribute("aria-label","rotate left"),this.elements.rotateLeft.classList.add("cr-rotate-btn","cr-rotate-left"),this.elements.rotateRight.type="button",this.elements.rotateRight.innerHTML="↻",this.elements.rotateRight.setAttribute("aria-label","rotate right"),this.elements.rotateRight.classList.add("cr-rotate-btn","cr-rotate-right"),this.elements.toolBar.appendChild(this.elements.rotateLeft),this.elements.toolBar.appendChild(this.elements.rotateRight)),this.elements.zoomer.type="range",this.elements.zoomer.step="0.0001",this.elements.zoomer.value="1",this.options.enableZoomSlider&&(this.elements.zoomer.className=this.options.zoomerInputClass,this.elements.zoomer.setAttribute("aria-label","zoom"),this.elements.toolBar.appendChild(this.elements.zoomer)),this.element.appendChild(this.elements.boundary),this.element.appendChild(this.elements.toolBar),this.elements.toolBar.childNodes.length?this.element.style.setProperty("--cropt-toolbar","32px"):this.element.style.setProperty("--cropt-toolbar","0px"),this.#p(),this.#c(),this.#g(),this.#u()}bind(t,e){if(!t)throw new Error("src cannot be empty");return function(t){return new Promise((e,i)=>{const o=new Image;o.crossOrigin="anonymous",o.onload=()=>{e(o)},o.onerror=i,o.src=t})}(t).then(async t=>{if(this.#w(t),"object"==typeof e&&e?.transform)e?.viewport&&this.setOptions({viewport:e.viewport}),setTimeout(async()=>{e.transform?.rotate&&await this.setRotation(e.transform.rotate);const t=e.transform?.scale||null;this.#v(t),this.#b(e.transform),this.#h()},0);else{const t=Number(e)||null;this.#f(t)}})}#y(){const t=t=>Math.round(Math.max(0,t/this.#o)),e=this.elements.preview.getBoundingClientRect(),i=this.elements.viewport.getBoundingClientRect(),o=this.elements.viewport.offsetWidth,n=this.elements.viewport.offsetHeight,s=(i.width-o)/2,r=(i.height-n)/2,a=i.left-e.left,l=i.top-e.top;return{left:t(a),top:t(l),right:t(a+o+s),bottom:t(l+n+r),width:t(o+s),height:t(n+r)}}get(){const t=this.#y();let e={x:t.left,y:t.top,width:t.width,height:t.height};const i=this.elements.preview.naturalWidth,o=this.elements.preview.naturalHeight;return 90===this.#n||270===this.#n?(e.width=t.height,e.height=t.width,90===this.#n?(e.x=t.top,e.y=i-t.left-t.width):(e.x=o-t.top-t.height,e.y=t.left)):180===this.#n&&(e.x=i-t.left-t.width,e.y=o-t.top-t.height),e.x=Math.max(0,e.x),e.y=Math.max(0,e.y),{crop:e,transform:this.#b(),viewport:{width:Math.round(this.options.viewport.width),height:Math.round(this.options.viewport.height),borderRadius:this.options.viewport.borderRadius}}}toCanvas(t=null,e=""){const i=this.#y(),o=t&&t<0;t&&o&&(t=-t);let n=i.width,s=i.height;if(t&&(!o||n>t||s>t)){const e=this.elements.viewport.getBoundingClientRect(),i=e.width/e.height;i>1?(n=t,s=t/i):(s=t,n=t*i)}return Promise.resolve(this.#C(i,n,s,e))}toBlob(t=null,e="image/webp",i=1){return"image/webp"===e&&i<1&&!document.createElement("canvas").toDataURL("image/webp").startsWith("data:image/webp")&&(e="image/jpeg"),new Promise((o,n)=>{this.toCanvas(t,e).then(t=>{t.toBlob(e=>{null===e?n("Canvas blob is null"):(e.width=t.width,e.height=t.height,o(e))},e,i)})})}refresh(){this.#f()}setOptions(t){const e=this.options.viewport.width,i=this.options.viewport.height,o=this.options.viewport;t.viewport&&(t.viewport={...o,...t.viewport}),this.options={...this.options,...t},this.#p(),o.width===e&&o.height===i||this.#v()}setZoom(t){const e=this.elements.zoomer,i=parseFloat(e.min),o=parseFloat(e.max);e.value=Math.max(i,Math.min(o,t)).toFixed(4),this.#x()}async setRotation(t){if(void 0===t)return;const e=(t%360+360)%360,i=e-this.#n;0!==i&&(this.#n=e,await this.#R(i),this.#f())}async#R(t){const e=this.elements.preview,i=await createImageBitmap(e),o=90===Math.abs(t%180),n=document.createElement("canvas");n.width=o?i.height:i.width,n.height=o?i.width:i.height;const s=n.getContext("2d");if(!s)throw new Error("Could not get canvas context");s.translate(n.width/2,n.height/2),s.rotate(t*Math.PI/180),s.drawImage(i,-i.width/2,-i.height/2),i.close();const r=await new Promise((t,e)=>{n.toBlob(i=>i?t(i):e(new Error("Failed to create blob")),"image/webp",1)});this.#s&&URL.revokeObjectURL(e.src),e.src=URL.createObjectURL(r),await e.decode(),this.#s=!0}destroy(){this.#a.abort(),this.#s&&URL.revokeObjectURL(this.elements.preview.src),this.element.removeChild(this.elements.boundary),this.element.classList.remove("cropt-container"),this.element.removeChild(this.elements.toolBar),this.elements=t()}#b(t){const e=this.elements.preview,i=()=>{const[t,i]=(e.style.transformOrigin||"0px 0px").split(" ");return{x:parseFloat(t)||0,y:parseFloat(i)||0}};if(void 0!==t){const{x:o=0,y:n=0,scale:s=1}=t;if(e.style.transform=`translate(${o}px, ${n}px) scale(${s})`,void 0!==t.origin){const i=t.origin.x??0,o=t.origin.y??0;e.style.transformOrigin=`${i}px ${o}px`}return{x:o,y:n,scale:s,rotate:this.#n,origin:i()}}const o=e.style.transform||"";let n=0,s=0,r=1;for(const t of["translate","scale"]){const e=new RegExp(`${t}s*\\(([^)]+)\\)`),i=o.match(e);if(i){const e=i[1].trim();if("translate"===t){const[t,i]=e.split(",").map(t=>t.trim());n=Math.round(parseFloat(t))||0,s=void 0!==i?Math.round(parseFloat(i))||0:n}else"scale"===t&&(r=parseFloat(e)||1)}}return{x:n,y:s,scale:r,rotate:this.#n,origin:i()}}#p(){if(!this.elements?.viewport)return;const t=this.elements.viewport;t.style.borderRadius=this.options.viewport?.borderRadius||"50%",t.style.width=(this.options.viewport?.width||100)+"px",t.style.height=(this.options.viewport?.height||100)+"px",this.#L()}#m(){if(!this.options.resizeBars)return;const{resizeHandleRight:t,resizeHandleBottom:e}=this.elements;t.classList.add("cr-resize-handle","cr-resize-handle-right");const i=document.createElement("div");i.classList.add("cr-resize-handle-grabber"),t.appendChild(i),e.classList.add("cr-resize-handle","cr-resize-handle-bottom");const o=document.createElement("div");o.classList.add("cr-resize-handle-grabber"),e.appendChild(o),this.elements.controls.appendChild(t),this.elements.controls.appendChild(e),this.#E(),setTimeout(()=>this.#L(),200)}#L(){if(!this.options.resizeBars)return;const{resizeHandleRight:t,resizeHandleBottom:e,viewport:i,boundary:o}=this.elements,n=this.options.viewport.width,s=this.options.viewport.height,r=i.getBoundingClientRect(),a=o.getBoundingClientRect(),l=r.left-a.left,h=r.top-a.top;t.style.left=l+n-22+"px",t.style.top=h+s/2-22+"px",e.style.left=l+n/2-22+"px",e.style.top=h+s-22+"px"}#E(){let t=0,e=0;const i=i=>{i.preventDefault();const o=i.pageX-t,n=Math.floor(.95*this.elements.boundary.clientWidth),s=Math.min(n,Math.max(this.#e,e+o));this.options.viewport.width=s,this.#p()},o=()=>{document.removeEventListener("pointermove",i),document.removeEventListener("pointerup",o)};this.elements.resizeHandleRight.addEventListener("pointerdown",n=>{0===n.button&&(n.preventDefault(),n.stopPropagation(),t=n.pageX,e=this.options.viewport.width,document.addEventListener("pointermove",i,{signal:this.#a.signal}),document.addEventListener("pointerup",o,{signal:this.#a.signal}))},{signal:this.#a.signal});let n=0,s=0;const r=t=>{t.preventDefault();const e=t.pageY-n,i=Math.floor(.95*this.elements.boundary.clientHeight),o=Math.min(i,Math.max(this.#i,s+e));this.options.viewport.height=o,this.#p()},a=()=>{document.removeEventListener("pointermove",r),document.removeEventListener("pointerup",a)};this.elements.resizeHandleBottom.addEventListener("pointerdown",t=>{0===t.button&&(t.preventDefault(),t.stopPropagation(),n=t.pageY,s=this.options.viewport.height,document.addEventListener("pointermove",r,{signal:this.#a.signal}),document.addEventListener("pointerup",a,{signal:this.#a.signal}))},{signal:this.#a.signal})}#B(t){const e=document.createElement("canvas"),i=e.getContext("2d");if(null===i)throw new Error("Canvas context cannot be null");e.width=t.width,e.height=t.height;const o=this.elements.preview;return i.drawImage(o,t.left,t.top,t.width,t.height,0,0,e.width,e.height),e}#C(t,e,i,o){const n=this.#B(t),s=n.getContext("2d"),r=document.createElement("canvas"),a=r.getContext("2d"),l=document.createElement("canvas"),h=l.getContext("2d");if(l.width=e,l.height=i,null===h||null===s||null===a)throw new Error("Canvas context cannot be null");let d={width:n.width,height:n.height};for(;d.width>2*l.width;){let t=d.width,e=d.height;r.width=t,r.height=e,a.clearRect(0,0,r.width,r.height),a.drawImage(n,0,0),d={width:Math.floor(t/2),height:Math.floor(e/2)},s.clearRect(0,0,t,e),s.drawImage(r,0,0,t,e,0,0,d.width,d.height)}return"image/jpeg"===o&&(h.fillStyle=this.#r,h.fillRect(0,0,l.width,l.height)),h.drawImage(n,0,0,d.width,d.height,0,0,l.width,l.height),n.width=n.height=0,r.width=r.height=0,l}#z(){const t=this.#o,e=this.elements.viewport.getBoundingClientRect(),i=this.elements.boundary.clientWidth/2,o=this.elements.boundary.clientHeight/2,n=this.elements.preview.getBoundingClientRect(),s=e.width/2,r=e.height/2,a=-1*(s/t-i),l=-1*(r/t-o),h=1/t*s,d=1/t*r;return{translate:{maxX:a,minX:a-(n.width*(1/t)-e.width*(1/t)),maxY:l,minY:l-(n.height*(1/t)-e.height*(1/t))},origin:{maxX:n.width*(1/t)-h,minX:h,maxY:n.height*(1/t)-d,minY:d}}}#M(t,i){const o=this.elements.preview.getBoundingClientRect(),n=this.elements.viewport.getBoundingClientRect(),s=this.#b();s.y+=e(n.top-o.top,i,n.bottom-o.bottom),s.x+=e(n.left-o.left,t,n.right-o.right),this.#P(s),this.#l()}#c(){let t=0,e=0,i=[],o=0,n=n=>{n.preventDefault();const s=i.findIndex(t=>t.pointerId===n.pointerId);if(-1!==s){if(i[s]=n,2===i.length){let t=i[0],e=i[1],n=Math.hypot(t.pageX-e.pageX,t.pageY-e.pageY);return 0===o&&(o=n/this.#o),void this.setZoom(n/o)}0===o&&(this.#M(n.pageX-t,n.pageY-e),t=n.pageX,e=n.pageY)}},s=t=>{const e=i.findIndex(e=>e.pointerId===t.pointerId);-1!==e&&i.splice(e,1),0===i.length&&(this.elements.overlay.removeEventListener("pointermove",n),this.elements.overlay.removeEventListener("pointerup",s),this.elements.overlay.removeEventListener("pointerout",s),this.#I(!1,this.elements.preview),o=0)};this.elements.overlay.addEventListener("pointerdown",o=>{o.button||(o.preventDefault(),i.push(o),this.elements.overlay.setPointerCapture(o.pointerId),i.length>1||(t=o.pageX,e=o.pageY,this.#I(!0,this.elements.preview),this.elements.overlay.addEventListener("pointermove",n,{signal:this.#a.signal}),this.elements.overlay.addEventListener("pointerup",s,{signal:this.#a.signal}),this.elements.overlay.addEventListener("pointerout",s,{signal:this.#a.signal})))},{signal:this.#a.signal}),this.options.enableKeypress&&document.addEventListener("keydown",t=>{if(document.activeElement&&["INPUT","TEXTAREA","SELECT","BUTTON"].includes(document.activeElement.nodeName))return;const e=function(t){switch(t){case"ArrowLeft":return[2,0];case"ArrowUp":return[0,2];case"ArrowRight":return[-2,0];case"ArrowDown":return[0,-2];default:return null}}(t.key);if(null!==e)if(t.shiftKey&&e[1]){t.preventDefault();const i=parseFloat(this.elements.zoomer.value);this.setZoom(i+.005*e[1])}else t.preventDefault(),this.#M(e[0],e[1])},{signal:this.#a.signal})}#g(){this.options.enableZoomSlider&&this.elements.zoomer.addEventListener("input",()=>this.#x(),{signal:this.#a.signal}),"off"!==this.options.mouseWheelZoom&&this.elements.boundary.addEventListener("wheel",t=>{let e=0;("ctrl"!==this.options.mouseWheelZoom||t.ctrlKey)&&(t.deltaY&&(e=-1*t.deltaY/2e3),t.preventDefault(),this.setZoom(this.#o+e*this.#o))},{signal:this.#a.signal})}#x(){const t=this.#b();this.#o=parseFloat(this.elements.zoomer.value),t.scale=this.#o;const e=this.#z(),i=e.translate,o=e.origin;t.x>=i.maxX&&(t.origin.x=o.minX,t.x=i.maxX),t.x<=i.minX&&(t.origin.x=o.maxX,t.x=i.minX),t.y>=i.maxY&&(t.origin.y=o.minY,t.y=i.maxY),t.y<=i.minY&&(t.origin.y=o.maxY,t.y=i.minY),this.#b(t),this.#l()}#u(){this.options.enableRotateBtns&&(this.elements.rotateLeft.addEventListener("click",()=>this.setRotation(this.#n-90),{signal:this.#a.signal}),this.elements.rotateRight.addEventListener("click",()=>this.setRotation(this.#n+90),{signal:this.#a.signal}))}#w(t){this.#d(t),this.elements.preview.parentNode&&this.elements.preview.parentNode.replaceChild(t,this.elements.preview),this.elements.preview=t}#d(t){t.classList.add("cr-image"),t.style.background=this.#r,t.setAttribute("alt","preview"),this.#I(!1,t)}#I(t,e){e.setAttribute("aria-grabbed",t.toString()),this.elements.boundary.setAttribute("aria-dropeffect",t?"move":"none")}#H(){return null!==this.elements.preview.offsetParent}#h(){const t=this.elements.boundary.getBoundingClientRect(),e=this.elements.preview.getBoundingClientRect(),i=this.elements.overlay;i.style.width=e.width+"px",i.style.height=e.height+"px",i.style.top=e.top-t.top+"px",i.style.left=e.left-t.left+"px"}#f(t=null){if(!this.#H())return;const e={x:0,y:0,scale:1,origin:{x:0,y:0}};this.#b(e),this.#v(t),e.scale=this.#o,this.#b(e),this.#Z(),this.#h()}#P(t){const e=this.elements.viewport.getBoundingClientRect(),i=this.elements.preview.getBoundingClientRect(),{origin:o}=this.#b(),n=e.top-i.top+e.height/2,s=e.left-i.left+e.width/2,r={x:Math.round(s/this.#o),y:Math.round(n/this.#o)};t.x=Math.round(t.x-(r.x-(o.x??0))*(1-this.#o)),t.y=Math.round(t.y-(r.y-(o.y??0))*(1-this.#o)),this.#b({...t,origin:r})}#v(t=null){const e=this.elements.preview,i=this.elements.viewport.getBoundingClientRect(),o=Math.max(i.width/e.naturalWidth,i.height/e.naturalHeight);let n=this.#t;if(o>=n&&(n+=o),this.elements.zoomer.min=o.toFixed(3),this.elements.zoomer.max=n.toFixed(3),null===t){const i=this.elements.boundary.getBoundingClientRect();t=Math.max(i.width/e.naturalWidth,i.height/e.naturalHeight)}this.setZoom(t)}#Z(){const t=this.elements.preview.getBoundingClientRect(),e=this.elements.viewport.getBoundingClientRect(),i=this.elements.boundary.getBoundingClientRect(),o=e.left-i.left,n=e.top-i.top,s=o-(t.width-e.width)/2,r=n-(t.height-e.height)/2;this.#P({x:s,y:r,scale:this.#o})}}
|
|
1
|
+
function t(t,e){let i;return(...s)=>{window.clearTimeout(i),i=window.setTimeout(()=>t(...s),e)}}function e(){return{boundary:document.createElement("div"),viewport:document.createElement("div"),preview:document.createElement("img"),overlay:document.createElement("div"),controls:document.createElement("div"),resizeHandleRight:document.createElement("div"),resizeHandleBottom:document.createElement("div"),toolBar:document.createElement("div"),zoomer:document.createElement("input"),rotateLeft:document.createElement("button"),rotateRight:document.createElement("button")}}function i(t,e,i){return Math.round(Math.max(Math.min(t,e),i))}export default class{element;elements;options={mouseWheelZoom:"on",viewport:{width:0,height:0,borderRadius:"0px"},zoomerInputClass:"cr-slider",enableZoomSlider:!0,enableKeypress:!1,resizeBars:!1,enableRotateBtns:!1};#t=.85;#e=50;#i=50;#s=1;#n=0;#o=!1;#r="#fff";#a=new AbortController;#l=t(()=>{this.#h()},50);#d=t(()=>{this.#m()},16);constructor(t,i){if(t.classList.contains("cropt-container"))throw new Error("Cropt appears initialized (element has 'cropt-container' class). Aborting.");i.viewport&&(i.viewport={...this.options.viewport,...i.viewport},(!i.viewport?.width||i.viewport.width<100)&&(i.viewport.width=Math.max(100,t.clientWidth-60)),(!i.viewport?.height||i.viewport.height<100)&&(i.viewport.height=Math.max(100,t.clientHeight-60))),this.options={...this.options,...i},this.options.transparencyColor&&(this.#r=this.options.transparencyColor),this.element=t,this.element.classList.add("cropt-container"),this.elements=e(),this.elements.toolBar.classList.add("cr-toolbar-wrap"),this.elements.boundary.classList.add("cr-boundary"),this.elements.viewport.classList.add("cr-viewport"),this.elements.overlay.classList.add("cr-overlay"),this.elements.controls.classList.add("cr-controls"),this.elements.viewport.setAttribute("tabindex","0"),this.#p(this.elements.preview),this.elements.boundary.appendChild(this.elements.preview),this.elements.boundary.appendChild(this.elements.viewport),this.elements.boundary.appendChild(this.elements.overlay),this.elements.boundary.appendChild(this.elements.controls),this.#c(),this.options.enableRotateBtns&&(this.elements.rotateLeft.type="button",this.elements.rotateLeft.innerHTML="↺",this.elements.rotateLeft.setAttribute("aria-label","rotate left"),this.elements.rotateLeft.classList.add("cr-rotate-btn","cr-rotate-left"),this.elements.rotateRight.type="button",this.elements.rotateRight.innerHTML="↻",this.elements.rotateRight.setAttribute("aria-label","rotate right"),this.elements.rotateRight.classList.add("cr-rotate-btn","cr-rotate-right"),this.elements.toolBar.appendChild(this.elements.rotateLeft),this.elements.toolBar.appendChild(this.elements.rotateRight)),this.elements.zoomer.type="range",this.elements.zoomer.step="0.0001",this.elements.zoomer.value="1",this.options.enableZoomSlider&&(this.elements.zoomer.className=this.options.zoomerInputClass,this.elements.zoomer.setAttribute("aria-label","zoom"),this.elements.toolBar.appendChild(this.elements.zoomer)),this.element.appendChild(this.elements.boundary),this.element.appendChild(this.elements.toolBar),this.elements.toolBar.childNodes.length?this.element.style.setProperty("--cropt-toolbar","32px"):this.element.style.setProperty("--cropt-toolbar","0px"),this.#g(),this.#u(),this.#v(),this.#w()}bind(t,e){if(!t)throw new Error("src cannot be empty");return function(t){return new Promise((e,i)=>{const s=new Image;s.crossOrigin="anonymous",s.onload=()=>{e(s)},s.onerror=i,s.src=t})}(t).then(async t=>{if(this.#b(t),"object"==typeof e&&e?.transform)e?.viewport&&this.setOptions({viewport:e.viewport}),setTimeout(async()=>{e.transform?.rotate&&await this.setRotation(e.transform.rotate);const t=e.transform?.scale||null;this.#y(t),this.#f(e.transform),this.#h()},0);else{const t=Number(e)||null;this.#C(t)}})}#x(){const t=t=>Math.round(Math.max(0,t/this.#s)),e=this.elements.preview.getBoundingClientRect(),i=this.elements.viewport.getBoundingClientRect(),s=this.elements.viewport.offsetWidth,n=this.elements.viewport.offsetHeight,o=(i.width-s)/2,r=(i.height-n)/2,a=i.left-e.left,l=i.top-e.top;return{left:t(a),top:t(l),right:t(a+s+o),bottom:t(l+n+r),width:t(s+o),height:t(n+r)}}get(){const t=this.#x();let e={x:t.left,y:t.top,width:t.width,height:t.height};const i=this.elements.preview.naturalWidth,s=this.elements.preview.naturalHeight;return 90===this.#n||270===this.#n?(e.width=t.height,e.height=t.width,90===this.#n?(e.x=t.top,e.y=i-t.left-t.width):(e.x=s-t.top-t.height,e.y=t.left)):180===this.#n&&(e.x=i-t.left-t.width,e.y=s-t.top-t.height),e.x=Math.max(0,e.x),e.y=Math.max(0,e.y),{crop:e,transform:this.#f(),viewport:{width:Math.round(this.options.viewport.width),height:Math.round(this.options.viewport.height),borderRadius:this.options.viewport.borderRadius}}}toCanvas(t=null,e=""){const i=this.#x(),s=t&&t<0;t&&s&&(t=-t);let n=i.width,o=i.height;if(t&&(!s||n>t||o>t)){const e=this.elements.viewport.getBoundingClientRect(),i=e.width/e.height;i>1?(n=t,o=t/i):(o=t,n=t*i)}return Promise.resolve(this.#R(i,n,o,e))}toBlob(t=null,e="image/webp",i=1){return"image/webp"===e&&i<1&&!document.createElement("canvas").toDataURL("image/webp").startsWith("data:image/webp")&&(e="image/jpeg"),new Promise((s,n)=>{this.toCanvas(t,e).then(t=>{t.toBlob(e=>{null===e?n("Canvas blob is null"):(e.width=t.width,e.height=t.height,s(e))},e,i)})})}refresh(){this.#C()}setOptions(t){const e=this.options.viewport.width,i=this.options.viewport.height,s=this.options.viewport;t.viewport&&(t.viewport={...s,...t.viewport}),this.options={...this.options,...t},this.#g(),s.width===e&&s.height===i||this.#y()}setZoom(t){const e=this.elements.zoomer,i=parseFloat(e.min),s=parseFloat(e.max);e.value=Math.max(i,Math.min(s,t)).toFixed(4),this.#L()}async setRotation(t){if(void 0===t)return;const e=(t%360+360)%360,i=e-this.#n;0!==i&&(this.#n=e,await this.#E(i),this.#C())}async#E(t){const e=this.elements.preview,i=await createImageBitmap(e),s=90===Math.abs(t%180),n=document.createElement("canvas");n.width=s?i.height:i.width,n.height=s?i.width:i.height;const o=n.getContext("2d");if(!o)throw new Error("Could not get canvas context");o.translate(n.width/2,n.height/2),o.rotate(t*Math.PI/180),o.drawImage(i,-i.width/2,-i.height/2),i.close();const r=await new Promise((t,e)=>{n.toBlob(i=>i?t(i):e(new Error("Failed to create blob")),"image/webp",1)});this.#o&&URL.revokeObjectURL(e.src),e.src=URL.createObjectURL(r),await e.decode(),this.#o=!0}destroy(){this.#a.abort(),this.#o&&URL.revokeObjectURL(this.elements.preview.src),this.element.removeChild(this.elements.boundary),this.element.classList.remove("cropt-container"),this.element.removeChild(this.elements.toolBar),this.elements=e()}#f(t){const e=this.elements.preview,i=()=>{const[t,i]=(e.style.transformOrigin||"0px 0px").split(" ");return{x:parseFloat(t)||0,y:parseFloat(i)||0}};if(void 0!==t){const{x:s=0,y:n=0,scale:o=1}=t;if(e.style.transform=`translate(${s}px, ${n}px) scale(${o})`,void 0!==t.origin){const i=t.origin.x??0,s=t.origin.y??0;e.style.transformOrigin=`${i}px ${s}px`}return{x:s,y:n,scale:o,rotate:this.#n,origin:i()}}const s=e.style.transform||"";let n=0,o=0,r=1;for(const t of["translate","scale"]){const e=new RegExp(`${t}s*\\(([^)]+)\\)`),i=s.match(e);if(i){const e=i[1].trim();if("translate"===t){const[t,i]=e.split(",").map(t=>t.trim());n=Math.round(parseFloat(t))||0,o=void 0!==i?Math.round(parseFloat(i))||0:n}else"scale"===t&&(r=parseFloat(e)||1)}}return{x:n,y:o,scale:r,rotate:this.#n,origin:i()}}#g(t=!0){if(!this.elements?.viewport)return;const e=this.elements.viewport;e.style.borderRadius=this.options.viewport?.borderRadius||"50%",e.style.width=(this.options.viewport?.width||100)+"px",e.style.height=(this.options.viewport?.height||100)+"px",t?this.#m():this.#d()}#c(){if(!this.options.resizeBars)return;const{resizeHandleRight:t,resizeHandleBottom:e}=this.elements;t.classList.add("cr-resize-handle","cr-resize-handle-right");const i=document.createElement("div");i.classList.add("cr-resize-handle-grabber"),t.appendChild(i),e.classList.add("cr-resize-handle","cr-resize-handle-bottom");const s=document.createElement("div");s.classList.add("cr-resize-handle-grabber"),e.appendChild(s),this.elements.controls.appendChild(t),this.elements.controls.appendChild(e),this.#B(),setTimeout(()=>this.#m(),200)}#m(){if(!this.options.resizeBars)return;const{resizeHandleRight:t,resizeHandleBottom:e,viewport:i,boundary:s}=this.elements,n=this.options.viewport.width,o=this.options.viewport.height,r=i.getBoundingClientRect(),a=s.getBoundingClientRect(),l=r.left-a.left,h=r.top-a.top;t.style.left=l+n-22+"px",t.style.top=h+o/2-22+"px",e.style.left=l+n/2-22+"px",e.style.top=h+o-22+"px"}#B(){let t=0,e=0;const i=i=>{i.preventDefault();const s=i.pageX-t,n=Math.floor(.95*this.elements.boundary.clientWidth),o=Math.min(n,Math.max(this.#e,e+s));this.options.viewport.width=o,this.#g(!1),this.#l()},s=()=>{this.elements.resizeHandleRight.removeEventListener("pointermove",i),this.elements.resizeHandleRight.removeEventListener("pointerup",s),this.elements.resizeHandleRight.removeEventListener("lostpointercapture",s),this.elements.overlay.style.pointerEvents="",this.#g(!0),this.#h()};this.elements.resizeHandleRight.addEventListener("pointerdown",n=>{0===n.button&&(n.preventDefault(),n.stopPropagation(),this.elements.overlay.style.pointerEvents="none",this.elements.resizeHandleRight.setPointerCapture(n.pointerId),t=n.pageX,e=this.options.viewport.width,this.elements.resizeHandleRight.addEventListener("pointermove",i,{signal:this.#a.signal}),this.elements.resizeHandleRight.addEventListener("pointerup",s,{signal:this.#a.signal}),this.elements.resizeHandleRight.addEventListener("lostpointercapture",s,{signal:this.#a.signal}))},{signal:this.#a.signal});let n=0,o=0;const r=t=>{t.preventDefault();const e=t.pageY-n,i=Math.floor(.95*this.elements.boundary.clientHeight),s=Math.min(i,Math.max(this.#i,o+e));this.options.viewport.height=s,this.#g(!1),this.#l()},a=()=>{this.elements.resizeHandleBottom.removeEventListener("pointermove",r),this.elements.resizeHandleBottom.removeEventListener("pointerup",a),this.elements.resizeHandleBottom.removeEventListener("lostpointercapture",a),this.elements.overlay.style.pointerEvents="",this.#g(!0),this.#h()};this.elements.resizeHandleBottom.addEventListener("pointerdown",t=>{0===t.button&&(t.preventDefault(),t.stopPropagation(),this.elements.overlay.style.pointerEvents="none",this.elements.resizeHandleBottom.setPointerCapture(t.pointerId),n=t.pageY,o=this.options.viewport.height,this.elements.resizeHandleBottom.addEventListener("pointermove",r,{signal:this.#a.signal}),this.elements.resizeHandleBottom.addEventListener("pointerup",a,{signal:this.#a.signal}),this.elements.resizeHandleBottom.addEventListener("lostpointercapture",a,{signal:this.#a.signal}))},{signal:this.#a.signal})}#z(t){const e=document.createElement("canvas"),i=e.getContext("2d");if(null===i)throw new Error("Canvas context cannot be null");e.width=t.width,e.height=t.height;const s=this.elements.preview;return i.drawImage(s,t.left,t.top,t.width,t.height,0,0,e.width,e.height),e}#R(t,e,i,s){const n=this.#z(t),o=n.getContext("2d"),r=document.createElement("canvas"),a=r.getContext("2d"),l=document.createElement("canvas"),h=l.getContext("2d");if(l.width=e,l.height=i,null===h||null===o||null===a)throw new Error("Canvas context cannot be null");let d={width:n.width,height:n.height};for(;d.width>2*l.width;){let t=d.width,e=d.height;r.width=t,r.height=e,a.clearRect(0,0,r.width,r.height),a.drawImage(n,0,0),d={width:Math.floor(t/2),height:Math.floor(e/2)},o.clearRect(0,0,t,e),o.drawImage(r,0,0,t,e,0,0,d.width,d.height)}return"image/jpeg"===s&&(h.fillStyle=this.#r,h.fillRect(0,0,l.width,l.height)),h.drawImage(n,0,0,d.width,d.height,0,0,l.width,l.height),n.width=n.height=0,r.width=r.height=0,l}#H(){const t=this.#s,e=this.elements.viewport.getBoundingClientRect(),i=this.elements.boundary.clientWidth/2,s=this.elements.boundary.clientHeight/2,n=this.elements.preview.getBoundingClientRect(),o=e.width/2,r=e.height/2,a=-1*(o/t-i),l=-1*(r/t-s),h=1/t*o,d=1/t*r;return{translate:{maxX:a,minX:a-(n.width*(1/t)-e.width*(1/t)),maxY:l,minY:l-(n.height*(1/t)-e.height*(1/t))},origin:{maxX:n.width*(1/t)-h,minX:h,maxY:n.height*(1/t)-d,minY:d}}}#P(t,e){const s=this.elements.preview.getBoundingClientRect(),n=this.elements.viewport.getBoundingClientRect(),o=this.#f();o.y+=i(n.top-s.top,e,n.bottom-s.bottom),o.x+=i(n.left-s.left,t,n.right-s.right),this.#M(o),this.#l()}#u(){let t=0,e=0,i=[],s=0,n=n=>{n.preventDefault();const o=i.findIndex(t=>t.pointerId===n.pointerId);if(-1!==o){if(i[o]=n,2===i.length){let t=i[0],e=i[1],n=Math.hypot(t.pageX-e.pageX,t.pageY-e.pageY);return 0===s&&(s=n/this.#s),void this.setZoom(n/s)}0===s&&(this.#P(n.pageX-t,n.pageY-e),t=n.pageX,e=n.pageY)}},o=t=>{const e=i.findIndex(e=>e.pointerId===t.pointerId);-1!==e&&i.splice(e,1),0===i.length&&(this.elements.overlay.removeEventListener("pointermove",n),this.elements.overlay.removeEventListener("pointerup",o),this.elements.overlay.removeEventListener("pointerout",o),this.#I(!1,this.elements.preview),s=0)};this.elements.overlay.addEventListener("pointerdown",s=>{s.button||(s.preventDefault(),i.push(s),this.elements.overlay.setPointerCapture(s.pointerId),i.length>1||(t=s.pageX,e=s.pageY,this.#I(!0,this.elements.preview),this.elements.overlay.addEventListener("pointermove",n,{signal:this.#a.signal}),this.elements.overlay.addEventListener("pointerup",o,{signal:this.#a.signal}),this.elements.overlay.addEventListener("pointerout",o,{signal:this.#a.signal})))},{signal:this.#a.signal}),this.options.enableKeypress&&document.addEventListener("keydown",t=>{if(document.activeElement&&["INPUT","TEXTAREA","SELECT","BUTTON"].includes(document.activeElement.nodeName))return;const e=function(t){switch(t){case"ArrowLeft":return[2,0];case"ArrowUp":return[0,2];case"ArrowRight":return[-2,0];case"ArrowDown":return[0,-2];default:return null}}(t.key);if(null!==e)if(t.shiftKey&&e[1]){t.preventDefault();const i=parseFloat(this.elements.zoomer.value);this.setZoom(i+.005*e[1])}else t.preventDefault(),this.#P(e[0],e[1])},{signal:this.#a.signal})}#v(){this.options.enableZoomSlider&&this.elements.zoomer.addEventListener("input",()=>this.#L(),{signal:this.#a.signal}),"off"!==this.options.mouseWheelZoom&&this.elements.boundary.addEventListener("wheel",t=>{let e=0;("ctrl"!==this.options.mouseWheelZoom||t.ctrlKey)&&(t.deltaY&&(e=-1*t.deltaY/2e3),t.preventDefault(),this.setZoom(this.#s+e*this.#s))},{signal:this.#a.signal})}#L(){const t=this.#f();this.#s=parseFloat(this.elements.zoomer.value),t.scale=this.#s;const e=this.#H(),i=e.translate,s=e.origin;t.x>=i.maxX&&(t.origin.x=s.minX,t.x=i.maxX),t.x<=i.minX&&(t.origin.x=s.maxX,t.x=i.minX),t.y>=i.maxY&&(t.origin.y=s.minY,t.y=i.maxY),t.y<=i.minY&&(t.origin.y=s.maxY,t.y=i.minY),this.#f(t),this.#l()}#w(){this.options.enableRotateBtns&&(this.elements.rotateLeft.addEventListener("click",()=>this.setRotation(this.#n-90),{signal:this.#a.signal}),this.elements.rotateRight.addEventListener("click",()=>this.setRotation(this.#n+90),{signal:this.#a.signal}))}#b(t){this.#p(t),this.elements.preview.parentNode&&this.elements.preview.parentNode.replaceChild(t,this.elements.preview),this.elements.preview=t}#p(t){t.classList.add("cr-image"),t.style.background=this.#r,t.setAttribute("alt","preview"),this.#I(!1,t)}#I(t,e){e.setAttribute("aria-grabbed",t.toString()),this.elements.boundary.setAttribute("aria-dropeffect",t?"move":"none")}#D(){return null!==this.elements.preview.offsetParent}#h(){const t=this.elements.boundary.getBoundingClientRect(),e=this.elements.preview.getBoundingClientRect(),i=this.elements.overlay;i.style.width=e.width+"px",i.style.height=e.height+"px",i.style.top=e.top-t.top+"px",i.style.left=e.left-t.left+"px"}#C(t=null){if(!this.#D())return;const e={x:0,y:0,scale:1,origin:{x:0,y:0}};this.#f(e),this.#y(t),e.scale=this.#s,this.#f(e),this.#O(),this.#h()}#M(t){const e=this.elements.viewport.getBoundingClientRect(),i=this.elements.preview.getBoundingClientRect(),{origin:s}=this.#f(),n=e.top-i.top+e.height/2,o=e.left-i.left+e.width/2,r={x:Math.round(o/this.#s),y:Math.round(n/this.#s)};t.x=Math.round(t.x-(r.x-(s.x??0))*(1-this.#s)),t.y=Math.round(t.y-(r.y-(s.y??0))*(1-this.#s)),this.#f({...t,origin:r})}#y(t=null){const e=this.elements.preview,i=this.elements.viewport.getBoundingClientRect(),s=Math.max(i.width/e.naturalWidth,i.height/e.naturalHeight);let n=this.#t;if(s>=n&&(n+=s),this.elements.zoomer.min=s.toFixed(3),this.elements.zoomer.max=n.toFixed(3),null===t){const i=this.elements.boundary.getBoundingClientRect();t=Math.max(i.width/e.naturalWidth,i.height/e.naturalHeight)}this.setZoom(t)}#O(){const t=this.elements.preview.getBoundingClientRect(),e=this.elements.viewport.getBoundingClientRect(),i=this.elements.boundary.getBoundingClientRect(),s=e.left-i.left,n=e.top-i.top,o=s-(t.width-e.width)/2,r=n-(t.height-e.height)/2;this.#M({x:o,y:r,scale:this.#s})}}
|
package/dist/cropt.min.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.cropt-container .cr-image{left:0;max-height:none;max-width:none;pointer-events:none;position:absolute;top:0;transform-origin:0 0;z-index:-1}.cropt-container .cr-image,.cropt-container .cr-overlay{-webkit-user-select:none;user-select:none}.cropt-container .cr-boundary{height:calc(100% - var(--cropt-toolbar, 0px));min-height:100px;min-width:100px;overflow:hidden;position:relative;width:100%;z-index:1}.cropt-container .cr-toolbar-wrap{height:calc(var(--cropt-toolbar, 4px) - 8px)}.cropt-container .cr-viewport{border:2px solid #fff;bottom:0;box-shadow:0 0 2000px 2000px rgba(0,0,0,.5);box-sizing:border-box;left:0;margin:auto;position:absolute;right:0;top:0;z-index:0}.cropt-container .cr-overlay{cursor:move;position:absolute;touch-action:none;z-index:1}.cropt-container .cr-toolbar-wrap{align-items:center;display:flex;gap:6px;justify-content:space-between;margin:5px auto}.cropt-container .cr-slider{flex:1;margin:0 10px}.cropt-container .cr-
|
|
1
|
+
.cropt-container .cr-image{left:0;max-height:none;max-width:none;pointer-events:none;position:absolute;top:0;transform-origin:0 0;z-index:-1}.cropt-container .cr-image,.cropt-container .cr-overlay{-webkit-user-select:none;user-select:none}.cropt-container .cr-boundary{height:calc(100% - var(--cropt-toolbar, 0px));min-height:100px;min-width:100px;overflow:hidden;position:relative;width:100%;z-index:1}.cropt-container .cr-toolbar-wrap{height:calc(var(--cropt-toolbar, 4px) - 8px)}.cropt-container .cr-viewport{border:2px solid #fff;bottom:0;box-shadow:0 0 2000px 2000px rgba(0,0,0,.5);box-sizing:border-box;left:0;margin:auto;position:absolute;right:0;top:0;z-index:0}.cropt-container .cr-overlay{cursor:move;position:absolute;touch-action:none;z-index:1}.cropt-container .cr-toolbar-wrap{align-items:center;display:flex;gap:6px;justify-content:space-between;margin:5px auto}.cropt-container .cr-slider{flex:1;margin:0 10px}.cropt-container .cr-controls{height:100%;left:0;pointer-events:none;position:absolute;top:0;width:100%;z-index:2}.cropt-container .cr-resize-handle{align-items:center;display:flex;height:44px!important;justify-content:center;pointer-events:auto;position:absolute;touch-action:none;width:44px!important;z-index:100!important}.cropt-container .cr-resize-handle-grabber{background:#fff;border:1px solid rgba(0,0,0,.3);box-shadow:0 1px 3px rgba(0,0,0,.2);height:10px;pointer-events:none;width:10px}.cropt-container .cr-resize-handle-right{cursor:ew-resize}.cropt-container .cr-resize-handle-bottom{cursor:ns-resize}.cropt-container .cr-rotate-btn{background:transparent;border:2px solid #667;border-radius:25%;cursor:pointer}
|
package/dist/cropt.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function t(){return{boundary:document.createElement("div"),viewport:document.createElement("div"),preview:document.createElement("img"),overlay:document.createElement("div"),controls:document.createElement("div"),resizeHandleRight:document.createElement("div"),resizeHandleBottom:document.createElement("div"),toolBar:document.createElement("div"),zoomer:document.createElement("input"),rotateLeft:document.createElement("button"),rotateRight:document.createElement("button")}}function e(t,e,i){return Math.round(Math.max(Math.min(t,e),i))}class Cropt{element;elements;options={mouseWheelZoom:"on",viewport:{width:0,height:0,borderRadius:"0px"},zoomerInputClass:"cr-slider",enableZoomSlider:!0,enableKeypress:!1,resizeBars:!1,enableRotateBtns:!1};#t=.85;#e=50;#i=50;#o=1;#n=0;#s=!1;#r="#fff";#a=new AbortController;#l=function(t){let e;return(...i)=>{window.clearTimeout(e),e=window.setTimeout(()=>t(...i),100)}}(()=>{this.#h()});constructor(e,i){if(e.classList.contains("cropt-container"))throw new Error("Cropt appears initialized (element has 'cropt-container' class). Aborting.");i.viewport&&(i.viewport={...this.options.viewport,...i.viewport},(!i.viewport?.width||i.viewport.width<100)&&(i.viewport.width=Math.max(100,e.clientWidth-60)),(!i.viewport?.height||i.viewport.height<100)&&(i.viewport.height=Math.max(100,e.clientHeight-60))),this.options={...this.options,...i},this.options.transparencyColor&&(this.#r=this.options.transparencyColor),this.element=e,this.element.classList.add("cropt-container"),this.elements=t(),this.elements.toolBar.classList.add("cr-toolbar-wrap"),this.elements.boundary.classList.add("cr-boundary"),this.elements.viewport.classList.add("cr-viewport"),this.elements.overlay.classList.add("cr-overlay"),this.elements.controls.classList.add("cr-controls"),this.elements.viewport.setAttribute("tabindex","0"),this.#d(this.elements.preview),this.elements.boundary.appendChild(this.elements.preview),this.elements.boundary.appendChild(this.elements.viewport),this.elements.boundary.appendChild(this.elements.overlay),this.elements.boundary.appendChild(this.elements.controls),this.#m(),this.options.enableRotateBtns&&(this.elements.rotateLeft.type="button",this.elements.rotateLeft.innerHTML="↺",this.elements.rotateLeft.setAttribute("aria-label","rotate left"),this.elements.rotateLeft.classList.add("cr-rotate-btn","cr-rotate-left"),this.elements.rotateRight.type="button",this.elements.rotateRight.innerHTML="↻",this.elements.rotateRight.setAttribute("aria-label","rotate right"),this.elements.rotateRight.classList.add("cr-rotate-btn","cr-rotate-right"),this.elements.toolBar.appendChild(this.elements.rotateLeft),this.elements.toolBar.appendChild(this.elements.rotateRight)),this.elements.zoomer.type="range",this.elements.zoomer.step="0.0001",this.elements.zoomer.value="1",this.options.enableZoomSlider&&(this.elements.zoomer.className=this.options.zoomerInputClass,this.elements.zoomer.setAttribute("aria-label","zoom"),this.elements.toolBar.appendChild(this.elements.zoomer)),this.element.appendChild(this.elements.boundary),this.element.appendChild(this.elements.toolBar),this.elements.toolBar.childNodes.length?this.element.style.setProperty("--cropt-toolbar","32px"):this.element.style.setProperty("--cropt-toolbar","0px"),this.#p(),this.#c(),this.#g(),this.#u()}bind(t,e){if(!t)throw new Error("src cannot be empty");return function(t){return new Promise((e,i)=>{const o=new Image;o.crossOrigin="anonymous",o.onload=()=>{e(o)},o.onerror=i,o.src=t})}(t).then(async t=>{if(this.#w(t),"object"==typeof e&&e?.transform)e?.viewport&&this.setOptions({viewport:e.viewport}),setTimeout(async()=>{e.transform?.rotate&&await this.setRotation(e.transform.rotate);const t=e.transform?.scale||null;this.#v(t),this.#b(e.transform),this.#h()},0);else{const t=Number(e)||null;this.#f(t)}})}#y(){const t=t=>Math.round(Math.max(0,t/this.#o)),e=this.elements.preview.getBoundingClientRect(),i=this.elements.viewport.getBoundingClientRect(),o=this.elements.viewport.offsetWidth,n=this.elements.viewport.offsetHeight,s=(i.width-o)/2,r=(i.height-n)/2,a=i.left-e.left,l=i.top-e.top;return{left:t(a),top:t(l),right:t(a+o+s),bottom:t(l+n+r),width:t(o+s),height:t(n+r)}}get(){const t=this.#y();let e={x:t.left,y:t.top,width:t.width,height:t.height};const i=this.elements.preview.naturalWidth,o=this.elements.preview.naturalHeight;return 90===this.#n||270===this.#n?(e.width=t.height,e.height=t.width,90===this.#n?(e.x=t.top,e.y=i-t.left-t.width):(e.x=o-t.top-t.height,e.y=t.left)):180===this.#n&&(e.x=i-t.left-t.width,e.y=o-t.top-t.height),e.x=Math.max(0,e.x),e.y=Math.max(0,e.y),{crop:e,transform:this.#b(),viewport:{width:Math.round(this.options.viewport.width),height:Math.round(this.options.viewport.height),borderRadius:this.options.viewport.borderRadius}}}toCanvas(t=null,e=""){const i=this.#y(),o=t&&t<0;t&&o&&(t=-t);let n=i.width,s=i.height;if(t&&(!o||n>t||s>t)){const e=this.elements.viewport.getBoundingClientRect(),i=e.width/e.height;i>1?(n=t,s=t/i):(s=t,n=t*i)}return Promise.resolve(this.#C(i,n,s,e))}toBlob(t=null,e="image/webp",i=1){return"image/webp"===e&&i<1&&!document.createElement("canvas").toDataURL("image/webp").startsWith("data:image/webp")&&(e="image/jpeg"),new Promise((o,n)=>{this.toCanvas(t,e).then(t=>{t.toBlob(e=>{null===e?n("Canvas blob is null"):(e.width=t.width,e.height=t.height,o(e))},e,i)})})}refresh(){this.#f()}setOptions(t){const e=this.options.viewport.width,i=this.options.viewport.height,o=this.options.viewport;t.viewport&&(t.viewport={...o,...t.viewport}),this.options={...this.options,...t},this.#p(),o.width===e&&o.height===i||this.#v()}setZoom(t){const e=this.elements.zoomer,i=parseFloat(e.min),o=parseFloat(e.max);e.value=Math.max(i,Math.min(o,t)).toFixed(4),this.#x()}async setRotation(t){if(void 0===t)return;const e=(t%360+360)%360,i=e-this.#n;0!==i&&(this.#n=e,await this.#R(i),this.#f())}async#R(t){const e=this.elements.preview,i=await createImageBitmap(e),o=90===Math.abs(t%180),n=document.createElement("canvas");n.width=o?i.height:i.width,n.height=o?i.width:i.height;const s=n.getContext("2d");if(!s)throw new Error("Could not get canvas context");s.translate(n.width/2,n.height/2),s.rotate(t*Math.PI/180),s.drawImage(i,-i.width/2,-i.height/2),i.close();const r=await new Promise((t,e)=>{n.toBlob(i=>i?t(i):e(new Error("Failed to create blob")),"image/webp",1)});this.#s&&URL.revokeObjectURL(e.src),e.src=URL.createObjectURL(r),await e.decode(),this.#s=!0}destroy(){this.#a.abort(),this.#s&&URL.revokeObjectURL(this.elements.preview.src),this.element.removeChild(this.elements.boundary),this.element.classList.remove("cropt-container"),this.element.removeChild(this.elements.toolBar),this.elements=t()}#b(t){const e=this.elements.preview,i=()=>{const[t,i]=(e.style.transformOrigin||"0px 0px").split(" ");return{x:parseFloat(t)||0,y:parseFloat(i)||0}};if(void 0!==t){const{x:o=0,y:n=0,scale:s=1}=t;if(e.style.transform=`translate(${o}px, ${n}px) scale(${s})`,void 0!==t.origin){const i=t.origin.x??0,o=t.origin.y??0;e.style.transformOrigin=`${i}px ${o}px`}return{x:o,y:n,scale:s,rotate:this.#n,origin:i()}}const o=e.style.transform||"";let n=0,s=0,r=1;for(const t of["translate","scale"]){const e=new RegExp(`${t}s*\\(([^)]+)\\)`),i=o.match(e);if(i){const e=i[1].trim();if("translate"===t){const[t,i]=e.split(",").map(t=>t.trim());n=Math.round(parseFloat(t))||0,s=void 0!==i?Math.round(parseFloat(i))||0:n}else"scale"===t&&(r=parseFloat(e)||1)}}return{x:n,y:s,scale:r,rotate:this.#n,origin:i()}}#p(){if(!this.elements?.viewport)return;const t=this.elements.viewport;t.style.borderRadius=this.options.viewport?.borderRadius||"50%",t.style.width=(this.options.viewport?.width||100)+"px",t.style.height=(this.options.viewport?.height||100)+"px",this.#L()}#m(){if(!this.options.resizeBars)return;const{resizeHandleRight:t,resizeHandleBottom:e}=this.elements;t.classList.add("cr-resize-handle","cr-resize-handle-right");const i=document.createElement("div");i.classList.add("cr-resize-handle-grabber"),t.appendChild(i),e.classList.add("cr-resize-handle","cr-resize-handle-bottom");const o=document.createElement("div");o.classList.add("cr-resize-handle-grabber"),e.appendChild(o),this.elements.controls.appendChild(t),this.elements.controls.appendChild(e),this.#E(),setTimeout(()=>this.#L(),200)}#L(){if(!this.options.resizeBars)return;const{resizeHandleRight:t,resizeHandleBottom:e,viewport:i,boundary:o}=this.elements,n=this.options.viewport.width,s=this.options.viewport.height,r=i.getBoundingClientRect(),a=o.getBoundingClientRect(),l=r.left-a.left,h=r.top-a.top;t.style.left=l+n-22+"px",t.style.top=h+s/2-22+"px",e.style.left=l+n/2-22+"px",e.style.top=h+s-22+"px"}#E(){let t=0,e=0;const i=i=>{i.preventDefault();const o=i.pageX-t,n=Math.floor(.95*this.elements.boundary.clientWidth),s=Math.min(n,Math.max(this.#e,e+o));this.options.viewport.width=s,this.#p()},o=()=>{document.removeEventListener("pointermove",i),document.removeEventListener("pointerup",o)};this.elements.resizeHandleRight.addEventListener("pointerdown",n=>{0===n.button&&(n.preventDefault(),n.stopPropagation(),t=n.pageX,e=this.options.viewport.width,document.addEventListener("pointermove",i,{signal:this.#a.signal}),document.addEventListener("pointerup",o,{signal:this.#a.signal}))},{signal:this.#a.signal});let n=0,s=0;const r=t=>{t.preventDefault();const e=t.pageY-n,i=Math.floor(.95*this.elements.boundary.clientHeight),o=Math.min(i,Math.max(this.#i,s+e));this.options.viewport.height=o,this.#p()},a=()=>{document.removeEventListener("pointermove",r),document.removeEventListener("pointerup",a)};this.elements.resizeHandleBottom.addEventListener("pointerdown",t=>{0===t.button&&(t.preventDefault(),t.stopPropagation(),n=t.pageY,s=this.options.viewport.height,document.addEventListener("pointermove",r,{signal:this.#a.signal}),document.addEventListener("pointerup",a,{signal:this.#a.signal}))},{signal:this.#a.signal})}#B(t){const e=document.createElement("canvas"),i=e.getContext("2d");if(null===i)throw new Error("Canvas context cannot be null");e.width=t.width,e.height=t.height;const o=this.elements.preview;return i.drawImage(o,t.left,t.top,t.width,t.height,0,0,e.width,e.height),e}#C(t,e,i,o){const n=this.#B(t),s=n.getContext("2d"),r=document.createElement("canvas"),a=r.getContext("2d"),l=document.createElement("canvas"),h=l.getContext("2d");if(l.width=e,l.height=i,null===h||null===s||null===a)throw new Error("Canvas context cannot be null");let d={width:n.width,height:n.height};for(;d.width>2*l.width;){let t=d.width,e=d.height;r.width=t,r.height=e,a.clearRect(0,0,r.width,r.height),a.drawImage(n,0,0),d={width:Math.floor(t/2),height:Math.floor(e/2)},s.clearRect(0,0,t,e),s.drawImage(r,0,0,t,e,0,0,d.width,d.height)}return"image/jpeg"===o&&(h.fillStyle=this.#r,h.fillRect(0,0,l.width,l.height)),h.drawImage(n,0,0,d.width,d.height,0,0,l.width,l.height),n.width=n.height=0,r.width=r.height=0,l}#z(){const t=this.#o,e=this.elements.viewport.getBoundingClientRect(),i=this.elements.boundary.clientWidth/2,o=this.elements.boundary.clientHeight/2,n=this.elements.preview.getBoundingClientRect(),s=e.width/2,r=e.height/2,a=-1*(s/t-i),l=-1*(r/t-o),h=1/t*s,d=1/t*r;return{translate:{maxX:a,minX:a-(n.width*(1/t)-e.width*(1/t)),maxY:l,minY:l-(n.height*(1/t)-e.height*(1/t))},origin:{maxX:n.width*(1/t)-h,minX:h,maxY:n.height*(1/t)-d,minY:d}}}#M(t,i){const o=this.elements.preview.getBoundingClientRect(),n=this.elements.viewport.getBoundingClientRect(),s=this.#b();s.y+=e(n.top-o.top,i,n.bottom-o.bottom),s.x+=e(n.left-o.left,t,n.right-o.right),this.#P(s),this.#l()}#c(){let t=0,e=0,i=[],o=0,n=n=>{n.preventDefault();const s=i.findIndex(t=>t.pointerId===n.pointerId);if(-1!==s){if(i[s]=n,2===i.length){let t=i[0],e=i[1],n=Math.hypot(t.pageX-e.pageX,t.pageY-e.pageY);return 0===o&&(o=n/this.#o),void this.setZoom(n/o)}0===o&&(this.#M(n.pageX-t,n.pageY-e),t=n.pageX,e=n.pageY)}},s=t=>{const e=i.findIndex(e=>e.pointerId===t.pointerId);-1!==e&&i.splice(e,1),0===i.length&&(this.elements.overlay.removeEventListener("pointermove",n),this.elements.overlay.removeEventListener("pointerup",s),this.elements.overlay.removeEventListener("pointerout",s),this.#I(!1,this.elements.preview),o=0)};this.elements.overlay.addEventListener("pointerdown",o=>{o.button||(o.preventDefault(),i.push(o),this.elements.overlay.setPointerCapture(o.pointerId),i.length>1||(t=o.pageX,e=o.pageY,this.#I(!0,this.elements.preview),this.elements.overlay.addEventListener("pointermove",n,{signal:this.#a.signal}),this.elements.overlay.addEventListener("pointerup",s,{signal:this.#a.signal}),this.elements.overlay.addEventListener("pointerout",s,{signal:this.#a.signal})))},{signal:this.#a.signal}),this.options.enableKeypress&&document.addEventListener("keydown",t=>{if(document.activeElement&&["INPUT","TEXTAREA","SELECT","BUTTON"].includes(document.activeElement.nodeName))return;const e=function(t){switch(t){case"ArrowLeft":return[2,0];case"ArrowUp":return[0,2];case"ArrowRight":return[-2,0];case"ArrowDown":return[0,-2];default:return null}}(t.key);if(null!==e)if(t.shiftKey&&e[1]){t.preventDefault();const i=parseFloat(this.elements.zoomer.value);this.setZoom(i+.005*e[1])}else t.preventDefault(),this.#M(e[0],e[1])},{signal:this.#a.signal})}#g(){this.options.enableZoomSlider&&this.elements.zoomer.addEventListener("input",()=>this.#x(),{signal:this.#a.signal}),"off"!==this.options.mouseWheelZoom&&this.elements.boundary.addEventListener("wheel",t=>{let e=0;("ctrl"!==this.options.mouseWheelZoom||t.ctrlKey)&&(t.deltaY&&(e=-1*t.deltaY/2e3),t.preventDefault(),this.setZoom(this.#o+e*this.#o))},{signal:this.#a.signal})}#x(){const t=this.#b();this.#o=parseFloat(this.elements.zoomer.value),t.scale=this.#o;const e=this.#z(),i=e.translate,o=e.origin;t.x>=i.maxX&&(t.origin.x=o.minX,t.x=i.maxX),t.x<=i.minX&&(t.origin.x=o.maxX,t.x=i.minX),t.y>=i.maxY&&(t.origin.y=o.minY,t.y=i.maxY),t.y<=i.minY&&(t.origin.y=o.maxY,t.y=i.minY),this.#b(t),this.#l()}#u(){this.options.enableRotateBtns&&(this.elements.rotateLeft.addEventListener("click",()=>this.setRotation(this.#n-90),{signal:this.#a.signal}),this.elements.rotateRight.addEventListener("click",()=>this.setRotation(this.#n+90),{signal:this.#a.signal}))}#w(t){this.#d(t),this.elements.preview.parentNode&&this.elements.preview.parentNode.replaceChild(t,this.elements.preview),this.elements.preview=t}#d(t){t.classList.add("cr-image"),t.style.background=this.#r,t.setAttribute("alt","preview"),this.#I(!1,t)}#I(t,e){e.setAttribute("aria-grabbed",t.toString()),this.elements.boundary.setAttribute("aria-dropeffect",t?"move":"none")}#H(){return null!==this.elements.preview.offsetParent}#h(){const t=this.elements.boundary.getBoundingClientRect(),e=this.elements.preview.getBoundingClientRect(),i=this.elements.overlay;i.style.width=e.width+"px",i.style.height=e.height+"px",i.style.top=e.top-t.top+"px",i.style.left=e.left-t.left+"px"}#f(t=null){if(!this.#H())return;const e={x:0,y:0,scale:1,origin:{x:0,y:0}};this.#b(e),this.#v(t),e.scale=this.#o,this.#b(e),this.#Z(),this.#h()}#P(t){const e=this.elements.viewport.getBoundingClientRect(),i=this.elements.preview.getBoundingClientRect(),{origin:o}=this.#b(),n=e.top-i.top+e.height/2,s=e.left-i.left+e.width/2,r={x:Math.round(s/this.#o),y:Math.round(n/this.#o)};t.x=Math.round(t.x-(r.x-(o.x??0))*(1-this.#o)),t.y=Math.round(t.y-(r.y-(o.y??0))*(1-this.#o)),this.#b({...t,origin:r})}#v(t=null){const e=this.elements.preview,i=this.elements.viewport.getBoundingClientRect(),o=Math.max(i.width/e.naturalWidth,i.height/e.naturalHeight);let n=this.#t;if(o>=n&&(n+=o),this.elements.zoomer.min=o.toFixed(3),this.elements.zoomer.max=n.toFixed(3),null===t){const i=this.elements.boundary.getBoundingClientRect();t=Math.max(i.width/e.naturalWidth,i.height/e.naturalHeight)}this.setZoom(t)}#Z(){const t=this.elements.preview.getBoundingClientRect(),e=this.elements.viewport.getBoundingClientRect(),i=this.elements.boundary.getBoundingClientRect(),o=e.left-i.left,n=e.top-i.top,s=o-(t.width-e.width)/2,r=n-(t.height-e.height)/2;this.#P({x:s,y:r,scale:this.#o})}}if(typeof window!=='undefined')window.Cropt=Cropt;else if(typeof module!=='undefined'&&module.exports)module.exports=Cropt; else if(typeof define==='function'&&define.amd)define(()=>Cropt);
|
|
1
|
+
function t(t,e){let i;return(...s)=>{window.clearTimeout(i),i=window.setTimeout(()=>t(...s),e)}}function e(){return{boundary:document.createElement("div"),viewport:document.createElement("div"),preview:document.createElement("img"),overlay:document.createElement("div"),controls:document.createElement("div"),resizeHandleRight:document.createElement("div"),resizeHandleBottom:document.createElement("div"),toolBar:document.createElement("div"),zoomer:document.createElement("input"),rotateLeft:document.createElement("button"),rotateRight:document.createElement("button")}}function i(t,e,i){return Math.round(Math.max(Math.min(t,e),i))}class Cropt{element;elements;options={mouseWheelZoom:"on",viewport:{width:0,height:0,borderRadius:"0px"},zoomerInputClass:"cr-slider",enableZoomSlider:!0,enableKeypress:!1,resizeBars:!1,enableRotateBtns:!1};#t=.85;#e=50;#i=50;#s=1;#n=0;#o=!1;#r="#fff";#a=new AbortController;#l=t(()=>{this.#h()},50);#d=t(()=>{this.#m()},16);constructor(t,i){if(t.classList.contains("cropt-container"))throw new Error("Cropt appears initialized (element has 'cropt-container' class). Aborting.");i.viewport&&(i.viewport={...this.options.viewport,...i.viewport},(!i.viewport?.width||i.viewport.width<100)&&(i.viewport.width=Math.max(100,t.clientWidth-60)),(!i.viewport?.height||i.viewport.height<100)&&(i.viewport.height=Math.max(100,t.clientHeight-60))),this.options={...this.options,...i},this.options.transparencyColor&&(this.#r=this.options.transparencyColor),this.element=t,this.element.classList.add("cropt-container"),this.elements=e(),this.elements.toolBar.classList.add("cr-toolbar-wrap"),this.elements.boundary.classList.add("cr-boundary"),this.elements.viewport.classList.add("cr-viewport"),this.elements.overlay.classList.add("cr-overlay"),this.elements.controls.classList.add("cr-controls"),this.elements.viewport.setAttribute("tabindex","0"),this.#p(this.elements.preview),this.elements.boundary.appendChild(this.elements.preview),this.elements.boundary.appendChild(this.elements.viewport),this.elements.boundary.appendChild(this.elements.overlay),this.elements.boundary.appendChild(this.elements.controls),this.#c(),this.options.enableRotateBtns&&(this.elements.rotateLeft.type="button",this.elements.rotateLeft.innerHTML="↺",this.elements.rotateLeft.setAttribute("aria-label","rotate left"),this.elements.rotateLeft.classList.add("cr-rotate-btn","cr-rotate-left"),this.elements.rotateRight.type="button",this.elements.rotateRight.innerHTML="↻",this.elements.rotateRight.setAttribute("aria-label","rotate right"),this.elements.rotateRight.classList.add("cr-rotate-btn","cr-rotate-right"),this.elements.toolBar.appendChild(this.elements.rotateLeft),this.elements.toolBar.appendChild(this.elements.rotateRight)),this.elements.zoomer.type="range",this.elements.zoomer.step="0.0001",this.elements.zoomer.value="1",this.options.enableZoomSlider&&(this.elements.zoomer.className=this.options.zoomerInputClass,this.elements.zoomer.setAttribute("aria-label","zoom"),this.elements.toolBar.appendChild(this.elements.zoomer)),this.element.appendChild(this.elements.boundary),this.element.appendChild(this.elements.toolBar),this.elements.toolBar.childNodes.length?this.element.style.setProperty("--cropt-toolbar","32px"):this.element.style.setProperty("--cropt-toolbar","0px"),this.#g(),this.#u(),this.#v(),this.#w()}bind(t,e){if(!t)throw new Error("src cannot be empty");return function(t){return new Promise((e,i)=>{const s=new Image;s.crossOrigin="anonymous",s.onload=()=>{e(s)},s.onerror=i,s.src=t})}(t).then(async t=>{if(this.#b(t),"object"==typeof e&&e?.transform)e?.viewport&&this.setOptions({viewport:e.viewport}),setTimeout(async()=>{e.transform?.rotate&&await this.setRotation(e.transform.rotate);const t=e.transform?.scale||null;this.#y(t),this.#f(e.transform),this.#h()},0);else{const t=Number(e)||null;this.#C(t)}})}#x(){const t=t=>Math.round(Math.max(0,t/this.#s)),e=this.elements.preview.getBoundingClientRect(),i=this.elements.viewport.getBoundingClientRect(),s=this.elements.viewport.offsetWidth,n=this.elements.viewport.offsetHeight,o=(i.width-s)/2,r=(i.height-n)/2,a=i.left-e.left,l=i.top-e.top;return{left:t(a),top:t(l),right:t(a+s+o),bottom:t(l+n+r),width:t(s+o),height:t(n+r)}}get(){const t=this.#x();let e={x:t.left,y:t.top,width:t.width,height:t.height};const i=this.elements.preview.naturalWidth,s=this.elements.preview.naturalHeight;return 90===this.#n||270===this.#n?(e.width=t.height,e.height=t.width,90===this.#n?(e.x=t.top,e.y=i-t.left-t.width):(e.x=s-t.top-t.height,e.y=t.left)):180===this.#n&&(e.x=i-t.left-t.width,e.y=s-t.top-t.height),e.x=Math.max(0,e.x),e.y=Math.max(0,e.y),{crop:e,transform:this.#f(),viewport:{width:Math.round(this.options.viewport.width),height:Math.round(this.options.viewport.height),borderRadius:this.options.viewport.borderRadius}}}toCanvas(t=null,e=""){const i=this.#x(),s=t&&t<0;t&&s&&(t=-t);let n=i.width,o=i.height;if(t&&(!s||n>t||o>t)){const e=this.elements.viewport.getBoundingClientRect(),i=e.width/e.height;i>1?(n=t,o=t/i):(o=t,n=t*i)}return Promise.resolve(this.#R(i,n,o,e))}toBlob(t=null,e="image/webp",i=1){return"image/webp"===e&&i<1&&!document.createElement("canvas").toDataURL("image/webp").startsWith("data:image/webp")&&(e="image/jpeg"),new Promise((s,n)=>{this.toCanvas(t,e).then(t=>{t.toBlob(e=>{null===e?n("Canvas blob is null"):(e.width=t.width,e.height=t.height,s(e))},e,i)})})}refresh(){this.#C()}setOptions(t){const e=this.options.viewport.width,i=this.options.viewport.height,s=this.options.viewport;t.viewport&&(t.viewport={...s,...t.viewport}),this.options={...this.options,...t},this.#g(),s.width===e&&s.height===i||this.#y()}setZoom(t){const e=this.elements.zoomer,i=parseFloat(e.min),s=parseFloat(e.max);e.value=Math.max(i,Math.min(s,t)).toFixed(4),this.#L()}async setRotation(t){if(void 0===t)return;const e=(t%360+360)%360,i=e-this.#n;0!==i&&(this.#n=e,await this.#E(i),this.#C())}async#E(t){const e=this.elements.preview,i=await createImageBitmap(e),s=90===Math.abs(t%180),n=document.createElement("canvas");n.width=s?i.height:i.width,n.height=s?i.width:i.height;const o=n.getContext("2d");if(!o)throw new Error("Could not get canvas context");o.translate(n.width/2,n.height/2),o.rotate(t*Math.PI/180),o.drawImage(i,-i.width/2,-i.height/2),i.close();const r=await new Promise((t,e)=>{n.toBlob(i=>i?t(i):e(new Error("Failed to create blob")),"image/webp",1)});this.#o&&URL.revokeObjectURL(e.src),e.src=URL.createObjectURL(r),await e.decode(),this.#o=!0}destroy(){this.#a.abort(),this.#o&&URL.revokeObjectURL(this.elements.preview.src),this.element.removeChild(this.elements.boundary),this.element.classList.remove("cropt-container"),this.element.removeChild(this.elements.toolBar),this.elements=e()}#f(t){const e=this.elements.preview,i=()=>{const[t,i]=(e.style.transformOrigin||"0px 0px").split(" ");return{x:parseFloat(t)||0,y:parseFloat(i)||0}};if(void 0!==t){const{x:s=0,y:n=0,scale:o=1}=t;if(e.style.transform=`translate(${s}px, ${n}px) scale(${o})`,void 0!==t.origin){const i=t.origin.x??0,s=t.origin.y??0;e.style.transformOrigin=`${i}px ${s}px`}return{x:s,y:n,scale:o,rotate:this.#n,origin:i()}}const s=e.style.transform||"";let n=0,o=0,r=1;for(const t of["translate","scale"]){const e=new RegExp(`${t}s*\\(([^)]+)\\)`),i=s.match(e);if(i){const e=i[1].trim();if("translate"===t){const[t,i]=e.split(",").map(t=>t.trim());n=Math.round(parseFloat(t))||0,o=void 0!==i?Math.round(parseFloat(i))||0:n}else"scale"===t&&(r=parseFloat(e)||1)}}return{x:n,y:o,scale:r,rotate:this.#n,origin:i()}}#g(t=!0){if(!this.elements?.viewport)return;const e=this.elements.viewport;e.style.borderRadius=this.options.viewport?.borderRadius||"50%",e.style.width=(this.options.viewport?.width||100)+"px",e.style.height=(this.options.viewport?.height||100)+"px",t?this.#m():this.#d()}#c(){if(!this.options.resizeBars)return;const{resizeHandleRight:t,resizeHandleBottom:e}=this.elements;t.classList.add("cr-resize-handle","cr-resize-handle-right");const i=document.createElement("div");i.classList.add("cr-resize-handle-grabber"),t.appendChild(i),e.classList.add("cr-resize-handle","cr-resize-handle-bottom");const s=document.createElement("div");s.classList.add("cr-resize-handle-grabber"),e.appendChild(s),this.elements.controls.appendChild(t),this.elements.controls.appendChild(e),this.#B(),setTimeout(()=>this.#m(),200)}#m(){if(!this.options.resizeBars)return;const{resizeHandleRight:t,resizeHandleBottom:e,viewport:i,boundary:s}=this.elements,n=this.options.viewport.width,o=this.options.viewport.height,r=i.getBoundingClientRect(),a=s.getBoundingClientRect(),l=r.left-a.left,h=r.top-a.top;t.style.left=l+n-22+"px",t.style.top=h+o/2-22+"px",e.style.left=l+n/2-22+"px",e.style.top=h+o-22+"px"}#B(){let t=0,e=0;const i=i=>{i.preventDefault();const s=i.pageX-t,n=Math.floor(.95*this.elements.boundary.clientWidth),o=Math.min(n,Math.max(this.#e,e+s));this.options.viewport.width=o,this.#g(!1),this.#l()},s=()=>{this.elements.resizeHandleRight.removeEventListener("pointermove",i),this.elements.resizeHandleRight.removeEventListener("pointerup",s),this.elements.resizeHandleRight.removeEventListener("lostpointercapture",s),this.elements.overlay.style.pointerEvents="",this.#g(!0),this.#h()};this.elements.resizeHandleRight.addEventListener("pointerdown",n=>{0===n.button&&(n.preventDefault(),n.stopPropagation(),this.elements.overlay.style.pointerEvents="none",this.elements.resizeHandleRight.setPointerCapture(n.pointerId),t=n.pageX,e=this.options.viewport.width,this.elements.resizeHandleRight.addEventListener("pointermove",i,{signal:this.#a.signal}),this.elements.resizeHandleRight.addEventListener("pointerup",s,{signal:this.#a.signal}),this.elements.resizeHandleRight.addEventListener("lostpointercapture",s,{signal:this.#a.signal}))},{signal:this.#a.signal});let n=0,o=0;const r=t=>{t.preventDefault();const e=t.pageY-n,i=Math.floor(.95*this.elements.boundary.clientHeight),s=Math.min(i,Math.max(this.#i,o+e));this.options.viewport.height=s,this.#g(!1),this.#l()},a=()=>{this.elements.resizeHandleBottom.removeEventListener("pointermove",r),this.elements.resizeHandleBottom.removeEventListener("pointerup",a),this.elements.resizeHandleBottom.removeEventListener("lostpointercapture",a),this.elements.overlay.style.pointerEvents="",this.#g(!0),this.#h()};this.elements.resizeHandleBottom.addEventListener("pointerdown",t=>{0===t.button&&(t.preventDefault(),t.stopPropagation(),this.elements.overlay.style.pointerEvents="none",this.elements.resizeHandleBottom.setPointerCapture(t.pointerId),n=t.pageY,o=this.options.viewport.height,this.elements.resizeHandleBottom.addEventListener("pointermove",r,{signal:this.#a.signal}),this.elements.resizeHandleBottom.addEventListener("pointerup",a,{signal:this.#a.signal}),this.elements.resizeHandleBottom.addEventListener("lostpointercapture",a,{signal:this.#a.signal}))},{signal:this.#a.signal})}#z(t){const e=document.createElement("canvas"),i=e.getContext("2d");if(null===i)throw new Error("Canvas context cannot be null");e.width=t.width,e.height=t.height;const s=this.elements.preview;return i.drawImage(s,t.left,t.top,t.width,t.height,0,0,e.width,e.height),e}#R(t,e,i,s){const n=this.#z(t),o=n.getContext("2d"),r=document.createElement("canvas"),a=r.getContext("2d"),l=document.createElement("canvas"),h=l.getContext("2d");if(l.width=e,l.height=i,null===h||null===o||null===a)throw new Error("Canvas context cannot be null");let d={width:n.width,height:n.height};for(;d.width>2*l.width;){let t=d.width,e=d.height;r.width=t,r.height=e,a.clearRect(0,0,r.width,r.height),a.drawImage(n,0,0),d={width:Math.floor(t/2),height:Math.floor(e/2)},o.clearRect(0,0,t,e),o.drawImage(r,0,0,t,e,0,0,d.width,d.height)}return"image/jpeg"===s&&(h.fillStyle=this.#r,h.fillRect(0,0,l.width,l.height)),h.drawImage(n,0,0,d.width,d.height,0,0,l.width,l.height),n.width=n.height=0,r.width=r.height=0,l}#H(){const t=this.#s,e=this.elements.viewport.getBoundingClientRect(),i=this.elements.boundary.clientWidth/2,s=this.elements.boundary.clientHeight/2,n=this.elements.preview.getBoundingClientRect(),o=e.width/2,r=e.height/2,a=-1*(o/t-i),l=-1*(r/t-s),h=1/t*o,d=1/t*r;return{translate:{maxX:a,minX:a-(n.width*(1/t)-e.width*(1/t)),maxY:l,minY:l-(n.height*(1/t)-e.height*(1/t))},origin:{maxX:n.width*(1/t)-h,minX:h,maxY:n.height*(1/t)-d,minY:d}}}#P(t,e){const s=this.elements.preview.getBoundingClientRect(),n=this.elements.viewport.getBoundingClientRect(),o=this.#f();o.y+=i(n.top-s.top,e,n.bottom-s.bottom),o.x+=i(n.left-s.left,t,n.right-s.right),this.#M(o),this.#l()}#u(){let t=0,e=0,i=[],s=0,n=n=>{n.preventDefault();const o=i.findIndex(t=>t.pointerId===n.pointerId);if(-1!==o){if(i[o]=n,2===i.length){let t=i[0],e=i[1],n=Math.hypot(t.pageX-e.pageX,t.pageY-e.pageY);return 0===s&&(s=n/this.#s),void this.setZoom(n/s)}0===s&&(this.#P(n.pageX-t,n.pageY-e),t=n.pageX,e=n.pageY)}},o=t=>{const e=i.findIndex(e=>e.pointerId===t.pointerId);-1!==e&&i.splice(e,1),0===i.length&&(this.elements.overlay.removeEventListener("pointermove",n),this.elements.overlay.removeEventListener("pointerup",o),this.elements.overlay.removeEventListener("pointerout",o),this.#I(!1,this.elements.preview),s=0)};this.elements.overlay.addEventListener("pointerdown",s=>{s.button||(s.preventDefault(),i.push(s),this.elements.overlay.setPointerCapture(s.pointerId),i.length>1||(t=s.pageX,e=s.pageY,this.#I(!0,this.elements.preview),this.elements.overlay.addEventListener("pointermove",n,{signal:this.#a.signal}),this.elements.overlay.addEventListener("pointerup",o,{signal:this.#a.signal}),this.elements.overlay.addEventListener("pointerout",o,{signal:this.#a.signal})))},{signal:this.#a.signal}),this.options.enableKeypress&&document.addEventListener("keydown",t=>{if(document.activeElement&&["INPUT","TEXTAREA","SELECT","BUTTON"].includes(document.activeElement.nodeName))return;const e=function(t){switch(t){case"ArrowLeft":return[2,0];case"ArrowUp":return[0,2];case"ArrowRight":return[-2,0];case"ArrowDown":return[0,-2];default:return null}}(t.key);if(null!==e)if(t.shiftKey&&e[1]){t.preventDefault();const i=parseFloat(this.elements.zoomer.value);this.setZoom(i+.005*e[1])}else t.preventDefault(),this.#P(e[0],e[1])},{signal:this.#a.signal})}#v(){this.options.enableZoomSlider&&this.elements.zoomer.addEventListener("input",()=>this.#L(),{signal:this.#a.signal}),"off"!==this.options.mouseWheelZoom&&this.elements.boundary.addEventListener("wheel",t=>{let e=0;("ctrl"!==this.options.mouseWheelZoom||t.ctrlKey)&&(t.deltaY&&(e=-1*t.deltaY/2e3),t.preventDefault(),this.setZoom(this.#s+e*this.#s))},{signal:this.#a.signal})}#L(){const t=this.#f();this.#s=parseFloat(this.elements.zoomer.value),t.scale=this.#s;const e=this.#H(),i=e.translate,s=e.origin;t.x>=i.maxX&&(t.origin.x=s.minX,t.x=i.maxX),t.x<=i.minX&&(t.origin.x=s.maxX,t.x=i.minX),t.y>=i.maxY&&(t.origin.y=s.minY,t.y=i.maxY),t.y<=i.minY&&(t.origin.y=s.maxY,t.y=i.minY),this.#f(t),this.#l()}#w(){this.options.enableRotateBtns&&(this.elements.rotateLeft.addEventListener("click",()=>this.setRotation(this.#n-90),{signal:this.#a.signal}),this.elements.rotateRight.addEventListener("click",()=>this.setRotation(this.#n+90),{signal:this.#a.signal}))}#b(t){this.#p(t),this.elements.preview.parentNode&&this.elements.preview.parentNode.replaceChild(t,this.elements.preview),this.elements.preview=t}#p(t){t.classList.add("cr-image"),t.style.background=this.#r,t.setAttribute("alt","preview"),this.#I(!1,t)}#I(t,e){e.setAttribute("aria-grabbed",t.toString()),this.elements.boundary.setAttribute("aria-dropeffect",t?"move":"none")}#D(){return null!==this.elements.preview.offsetParent}#h(){const t=this.elements.boundary.getBoundingClientRect(),e=this.elements.preview.getBoundingClientRect(),i=this.elements.overlay;i.style.width=e.width+"px",i.style.height=e.height+"px",i.style.top=e.top-t.top+"px",i.style.left=e.left-t.left+"px"}#C(t=null){if(!this.#D())return;const e={x:0,y:0,scale:1,origin:{x:0,y:0}};this.#f(e),this.#y(t),e.scale=this.#s,this.#f(e),this.#O(),this.#h()}#M(t){const e=this.elements.viewport.getBoundingClientRect(),i=this.elements.preview.getBoundingClientRect(),{origin:s}=this.#f(),n=e.top-i.top+e.height/2,o=e.left-i.left+e.width/2,r={x:Math.round(o/this.#s),y:Math.round(n/this.#s)};t.x=Math.round(t.x-(r.x-(s.x??0))*(1-this.#s)),t.y=Math.round(t.y-(r.y-(s.y??0))*(1-this.#s)),this.#f({...t,origin:r})}#y(t=null){const e=this.elements.preview,i=this.elements.viewport.getBoundingClientRect(),s=Math.max(i.width/e.naturalWidth,i.height/e.naturalHeight);let n=this.#t;if(s>=n&&(n+=s),this.elements.zoomer.min=s.toFixed(3),this.elements.zoomer.max=n.toFixed(3),null===t){const i=this.elements.boundary.getBoundingClientRect();t=Math.max(i.width/e.naturalWidth,i.height/e.naturalHeight)}this.setZoom(t)}#O(){const t=this.elements.preview.getBoundingClientRect(),e=this.elements.viewport.getBoundingClientRect(),i=this.elements.boundary.getBoundingClientRect(),s=e.left-i.left,n=e.top-i.top,o=s-(t.width-e.width)/2,r=n-(t.height-e.height)/2;this.#M({x:o,y:r,scale:this.#s})}}if(typeof window!=='undefined')window.Cropt=Cropt;else if(typeof module!=='undefined'&&module.exports)module.exports=Cropt; else if(typeof define==='function'&&define.amd)define(()=>Cropt);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cropt2",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.20",
|
|
4
4
|
"description": "A lightweight but powerful JavaScript image cropper",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cropping",
|
|
@@ -40,13 +40,13 @@
|
|
|
40
40
|
],
|
|
41
41
|
"type": "module",
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"cssnano": "^7.1.
|
|
43
|
+
"cssnano": "^7.1.7",
|
|
44
44
|
"http-server": "^14.1.1",
|
|
45
|
-
"postcss": "^8.5.
|
|
45
|
+
"postcss": "^8.5.12",
|
|
46
46
|
"postcss-cli": "^11.0.1",
|
|
47
|
-
"prettier": "^3.
|
|
48
|
-
"sass": "^1.
|
|
49
|
-
"terser": "^5.
|
|
47
|
+
"prettier": "^3.8.3",
|
|
48
|
+
"sass": "^1.99.0",
|
|
49
|
+
"terser": "^5.46.2",
|
|
50
50
|
"typescript": "^5.9.3"
|
|
51
51
|
},
|
|
52
52
|
"scripts": {
|
|
@@ -66,4 +66,4 @@
|
|
|
66
66
|
},
|
|
67
67
|
"homepage": "https://mindflowgo.github.io/cropt/",
|
|
68
68
|
"packageManager": "pnpm@10.27.0+sha512.72d699da16b1179c14ba9e64dc71c9a40988cbdc65c264cb0e489db7de917f20dcf4d64d8723625f2969ba52d4b7e2a1170682d9ac2a5dcaeaab732b7e16f04a"
|
|
69
|
-
}
|
|
69
|
+
}
|