diff --git a/assets/gaussholder.js b/assets/gaussholder.js index 3cad36c..e22fd8b 100644 --- a/assets/gaussholder.js +++ b/assets/gaussholder.js @@ -70,6 +70,10 @@ window.Gaussholder = (function (header) { * @param {HTMLImageElement} element Element to render placeholder for */ var handleElement = function (element) { + if ( element.complete ) { + return; + } + if ( ! ( 'gaussholder' in element.dataset ) ) { return; } @@ -77,127 +81,54 @@ window.Gaussholder = (function (header) { var canvas = document.createElement('canvas'); var final = element.dataset.gaussholderSize.split(','); - // Set the dimensions... - element.style.width = final[0] + 'px'; - element.style.height = final[1] + 'px'; - - // ...then recalculate based on what it actually renders as - var original = [ final[0], final[1] ]; - if ( element.width < final[0] ) { - // Rescale, keeping the aspect ratio - final[0] = element.width; - final[1] = final[1] * ( final[0] / original[0] ); - } else if ( element.height < final[1] ) { - // Rescale, keeping the aspect ratio - final[1] = element.height; - final[0] = final[0] * ( final[1] / original[1] ); - } - - // Set dimensions, _again_ - element.style.width = final[0] + 'px'; - element.style.height = final[1] + 'px'; - render(canvas, element.dataset.gaussholder.split(','), final, function () { // Load in as our background image - element.style.backgroundImage = 'url("' + canvas.toDataURL() + '")'; element.style.backgroundRepeat = 'no-repeat'; + element.style.backgroundSize = 'cover'; + element.style.backgroundImage = 'url("' + canvas.toDataURL() + '")'; }); + + element.onload = function () { + loadOriginal(element); + }; }; var loadOriginal = function (element) { - if ( ! ( 'originalsrc' in element.dataset ) && ! ( 'originalsrcset' in element.dataset ) ) { - return; - } - var data = element.dataset.gaussholderSize.split(','), radius = parseInt( data[2] ); - // Load our image now - var img = new Image(); + // Filter property to use + var filterProp = ( 'webkitFilter' in element.style ) ? 'webkitFilter' : 'filter'; + element.style[ filterProp ] = 'blur(' + radius * 0.5 + 'px)'; + + // Ensure blur doesn't bleed past image border + element.style.clipPath = 'url(#gaussclip)'; // Current FF + element.style.clipPath = 'inset(0)'; // Standard + element.style.webkitClipPath = 'inset(0)'; // WebKit + + // Clear placeholder temporary image + // (We do this after setting the source, as doing it before can + // cause a tiny flicker) + element.style.backgroundImage = ''; + element.style.backgroundRepeat = ''; + + var start = 0; + var anim = function (ts) { + if ( ! start ) start = ts; + var diff = ts - start; + if ( diff > fadeDuration ) { + element.style[ filterProp ] = ''; + element.style.clipPath = ''; + element.style.webkitClipPath = ''; + return; + } - if ( element.dataset.originalsrc ) { - img.src = element.dataset.originalsrc; - } - if ( element.dataset.originalsrcset ) { - img.srcset = element.dataset.originalsrcset; - } + var effectiveRadius = radius * ( 1 - ( diff / fadeDuration ) ); - img.onload = function () { - // Filter property to use - var filterProp = ( 'webkitFilter' in element.style ) ? 'webkitFilter' : 'filter'; - element.style[ filterProp ] = 'blur(' + radius * 0.5 + 'px)'; - - // Ensure blur doesn't bleed past image border - element.style.clipPath = 'url(#gaussclip)'; // Current FF - element.style.clipPath = 'inset(0)'; // Standard - element.style.webkitClipPath = 'inset(0)'; // WebKit - - // Set the actual source - element.src = img.src; - element.srcset = img.srcset; - - // Cleaning source - element.dataset.originalsrc = ''; - element.dataset.originalsrcset = ''; - - // Clear placeholder temporary image - // (We do this after setting the source, as doing it before can - // cause a tiny flicker) - element.style.backgroundImage = ''; - element.style.backgroundRepeat = ''; - - var start = 0; - var anim = function (ts) { - if ( ! start ) start = ts; - var diff = ts - start; - if ( diff > fadeDuration ) { - element.style[ filterProp ] = ''; - element.style.clipPath = ''; - element.style.webkitClipPath = ''; - return; - } - - var effectiveRadius = radius * ( 1 - ( diff / fadeDuration ) ); - - element.style[ filterProp ] = 'blur(' + effectiveRadius * 0.5 + 'px)'; - window.requestAnimationFrame(anim); - }; + element.style[ filterProp ] = 'blur(' + effectiveRadius * 0.5 + 'px)'; window.requestAnimationFrame(anim); }; - }; - - var loadLazily = []; - var threshold = 1200; - var lastRun = 0, - loopTimeout = null; - - var scrollHandler = function () { - var now = Date.now(); - if ( ( lastRun + 40 ) > now ) { - if ( loopTimeout ) { - return; - } - loopTimeout = window.setTimeout(scrollHandler, 40); - return; - } - lastRun = now; - loopTimeout && (loopTimeout = null); - - var next = []; - for (var i = loadLazily.length - 1; i >= 0; i--) { - var img = loadLazily[i]; - var shouldShow = img.getBoundingClientRect().top <= ( window.innerHeight + threshold ); - if ( ! shouldShow ) { - next.push(img); - continue; - } - - loadOriginal(img); - } - loadLazily = next; - if (loadLazily.length < 1) { - window.removeEventListener('scroll', scrollHandler); - } + window.requestAnimationFrame(anim); }; /** @@ -207,23 +138,7 @@ window.Gaussholder = (function (header) { var images = document.getElementsByTagName('img'); for (var i = images.length - 1; i >= 0; i--) { - var img = images[i]; - - // Ensure the blank GIF has loaded first - if ( img.complete ) { - handleElement(img); - } else { - img.onload = function () { - handleElement(this); - } - } - } - - loadLazily = images; - scrollHandler(); - - if (loadLazily.length > 0) { - window.addEventListener('scroll', scrollHandler); + handleElement(images[i]); } }; diff --git a/assets/gaussholder.min.js b/assets/gaussholder.min.js index c24b542..08a6b08 100644 --- a/assets/gaussholder.min.js +++ b/assets/gaussholder.min.js @@ -1 +1 @@ -var StackBlur=function(){function a(a,b,c,d,e){if("string"==typeof a)var a=document.getElementById(a);else if(!a instanceof HTMLCanvasElement)return;var f,g=a.getContext("2d");try{f=g.getImageData(b,c,d,e)}catch(a){throw new Error("unable to access image data: "+a)}return f}function b(b,d,e,f,g,h){if(!(isNaN(h)||h<1)){h|=0;var i=a(b,d,e,f,g);i=c(i,d,e,f,g,h),b.getContext("2d").putImageData(i,d,e)}}function c(a,b,c,g,h,i){var j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D=a.data,E=i+i+1,F=g-1,G=h-1,H=i+1,I=H*(H+1)/2,J=new d,K=J;for(l=1;l>P,D[o+1]=r*O>>P,D[o+2]=s*O>>P,q-=t,r-=u,s-=v,t-=M.r,u-=M.g,v-=M.b,m=p+((m=j+i+1)>P,D[m+1]=r*O>>P,D[m+2]=s*O>>P,q-=t,r-=u,s-=v,t-=M.r,u-=M.g,v-=M.b,m=j+((m=k+H)>8&255,h[a.height_offset+1]=255&f,h[a.length_offset]=e>>8&255,h[a.length_offset+1]=255&e,c(h)},e=function(b,c,e,f){var g=b.getContext("2d"),h=parseInt(e[0]),i=parseInt(e[1]),j=parseInt(e[2]);g.mozImageSmoothingEnabled=!1,g.webkitImageSmoothingEnabled=!1,g.msImageSmoothingEnabled=!1,g.imageSmoothingEnabled=!1;var k=new Image;k.src="data:image/jpg;base64,"+d(a,c),k.onload=function(){b.width=h,b.height=i,g.drawImage(k,0,0,h,i),StackBlur.canvasRGB(b,0,0,h,i,j),f()}},f=function(a){if("gaussholder"in a.dataset){var b=document.createElement("canvas"),c=a.dataset.gaussholderSize.split(",");a.style.width=c[0]+"px",a.style.height=c[1]+"px";var d=[c[0],c[1]];a.widthb)return a.style[c]="",a.style.clipPath="",void(a.style.webkitClipPath="");var i=d*(1-h/b);a.style[c]="blur("+.5*i+"px)",window.requestAnimationFrame(g)};window.requestAnimationFrame(g)}}},h=[],i=1200,j=0,k=null,l=function(){var a=Date.now();if(j+40>a){if(k)return;return void(k=window.setTimeout(l,40))}j=a,k&&(k=null);for(var b=[],c=h.length-1;c>=0;c--){var d=h[c],e=d.getBoundingClientRect().top<=window.innerHeight+i;e?g(d):b.push(d)}h=b,h.length<1&&window.removeEventListener("scroll",l)},m=function(){for(var a=document.getElementsByTagName("img"),b=a.length-1;b>=0;b--){var c=a[b];c.complete?f(c):c.onload=function(){f(this)}}h=a,l(),h.length>0&&window.addEventListener("scroll",l)};return m}(window.GaussholderHeader); \ No newline at end of file +var StackBlur=function(){var q=[512,512,456,512,328,456,335,512,405,328,271,456,388,335,292,512,454,405,364,328,298,271,496,456,420,388,360,335,312,292,273,512,482,454,428,405,383,364,345,328,312,298,284,271,259,496,475,456,437,420,404,388,374,360,347,335,323,312,302,292,282,273,265,512,497,482,468,454,441,428,417,405,394,383,373,364,354,345,337,328,320,312,305,298,291,284,278,271,265,259,507,496,485,475,465,456,446,437,428,420,412,404,396,388,381,374,367,360,354,347,341,335,329,323,318,312,307,302,297,292,287,282,278,273,269,265,261,512,505,497,489,482,475,468,461,454,447,441,435,428,422,417,411,405,399,394,389,383,378,373,368,364,359,354,350,345,341,337,332,328,324,320,316,312,309,305,301,298,294,291,287,284,281,278,274,271,268,265,262,259,257,507,501,496,491,485,480,475,470,465,460,456,451,446,442,437,433,428,424,420,416,412,408,404,400,396,392,388,385,381,377,374,370,367,363,360,357,354,350,347,344,341,338,335,332,329,326,323,320,318,315,312,310,307,304,302,299,297,294,292,289,287,285,282,280,278,275,273,271,269,267,265,263,261,259],H=[9,11,12,13,13,14,14,15,15,15,15,16,16,16,16,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19,19,19,19,19,19,19,19,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24];function T(){this.r=0,this.g=0,this.b=0,this.a=0,this.next=null}return{canvasRGB:function(t,e,n,a,r,o){if(!(isNaN(o)||o<1)){o|=0;var i=function(t,e,n,a,r){if("string"==typeof t)t=document.getElementById(t);else if(!t instanceof HTMLCanvasElement)return;var o,i=t.getContext("2d");try{o=i.getImageData(e,n,a,r)}catch(t){throw new Error("unable to access image data: "+t)}return o}(t,e,n,a,r);i=function(t,e,n,a,r,o){var i,s,l,g,u,f,c,d,h,b,m,v,p,w,y,x,I,k,S,C,E=t.data,B=o+o+1,A=a-1,P=r-1,R=o+1,z=R*(R+1)/2,F=new T,G=F;for(l=1;l>U,E[f+1]=h*N>>U,E[f+2]=b*N>>U,d-=m,h-=v,b-=p,m-=D.r,v-=D.g,p-=D.b,g=c+((g=i+o+1)>U,E[g+1]=h*N>>U,E[g+2]=b*N>>U,d-=m,h-=v,b-=p,m-=D.r,v-=D.g,p-=D.b,g=i+((g=s+R)>8&255,i[t.height_offset+1]=255&r,i[t.length_offset]=a>>8&255,i[t.length_offset+1]=255&a,function(t){for(var e="",n=new Uint8Array(t),a=n.byteLength,r=0;r