0

I'm loading a front-end site from Wordpress using a HTML 5 Blank Child Theme. I have a logo effect using particle slider for when I have a screen size of >960px; for screen sizes <960px I have a flat logo image. It all works fine but when I re-size between logos the page has to be refreshed manually (i.e. by pressing cmd+r) before the PS effect shows again. How can I rectify this so the effect shows automatically after re-sizing?

Here's my code -

particle-slider.php

<?php /* Template Name: particle-slider */ ?>
<!-- particle-slider template -->

    <div id="particle-slider">
        <div class="slides">
            <div class="slide" data-src="<?php echo home_url(); ?>/wp-content/uploads/2017/10/havoc_logohight.png"></div>
        </div>
        <canvas class="draw" style="width: 100%; height: 100%;"></canvas>
     </div>
     <script type="text/javascript">
        var ps = new ParticleSlider({ 'width':'1400', 'height': '600' });
     </script>
  <div id="logo"> <img src="<?php echo home_url(); ?>/wp-content/uploads/2017/10/havoc_logo.png"> </div>

  <!-- particle-slider template -->

style.css

/* RWD for logo */

@media screen and (max-width: 960px) {


    #particle-slider {
        display: none;
    }   


}

@media screen and (min-width: 960px) and (max-width: 1300px) {

    #particle-slider canvas {

                    width: 70%;
                    height: 30%;
                    position: relative;
                    top: 50px;
                    padding-bottom: 50px;


    }
}

@media screen and (min-width: 960px) {

     #logo img {

        display: none;
    } 

}

ps.js

// ┌────────────────────────────────────────────────────────────────────┐ \\
// │ ParticleSlider                   |                     Version 0.9 │ \\
// ├────────────────────────────────────────────────────────────────────┤ \\
// │ Copyright © 2013 Tamino Martinius (http://zaku.eu)                 │ \\
// │ Copyright © 2013 Particleslider.com (http://particleslider.com)    │ \\
// ├────────────────────────────────────────────────────────────────────┤ \\
// │ Terms of usage: (http://particleslider.com/legal/license)            │ \\
// └────────────────────────────────────────────────────────────────────┘ \\
;
function ParticleSlider(a){var b=this;b.sliderId="particle-slider",b.color="#fff",b.hoverColor="#88f",b.width=0,b.height=20,b.ptlGap=0,b.ptlSize=1,b.slideDelay=10,b.arrowPadding=10,b.showArrowControls=!0,b.onNextSlide=null,b.onWidthChange=null,b.onHeightChange=null,b.onSizeChange=null,b.monochrome=!1,b.mouseForce=1e4,b.restless=!0,b.imgs=[];if(a){var c=["color","hoverColor","width","height","ptlGap","ptlSize","slideDelay","arrowPadding","sliderId","showArrowControls","onNextSlide","monochrome","mouseForce","restless","imgs","onSizeChange","onWidthChange","onHeightChange"];for(var d=0,e=c.length;d<e;d++)a[c[d]]&&(b[c[d]]=a[c[d]])}b.$container=b.$("#"+b.sliderId),b.$$children=b.$container.childNodes,b.$controlsContainer=b.$(".controls"),b.$$slides=b.$(".slide",b.$(".slides").childNodes,!0),b.$controlLeft=null,b.$controlRight=null,b.$canv=b.$(".draw"),b.$srcCanv=document.createElement("canvas"),b.$srcCanv.style.display="none",b.$container.appendChild(b.$srcCanv),b.$prevCanv=document.createElement("canvas"),b.$prevCanv.style.display="none",b.$container.appendChild(b.$prevCanv),b.$nextCanv=document.createElement("canvas"),b.$nextCanv.style.display="none",b.$container.appendChild(b.$nextCanv),b.$overlay=document.createElement("p"),b.$container.appendChild(b.$overlay),b.imgControlPrev=null,b.imgControlNext=null,b.$$slides.length<=1&&(b.showArrowControls=!1),b.$controlsContainer&&b.$controlsContainer.childNodes&&b.showArrowControls==!0?(b.$controlLeft=b.$(".left",b.$controlsContainer.childNodes),b.$controlRight=b.$(".right",b.$controlsContainer.childNodes),b.imgControlPrev=new Image,b.imgControlNext=new Image,b.imgControlPrev.onload=function(){b.$prevCanv.height=this.height,b.$prevCanv.width=this.width,b.loadingStep()},b.imgControlNext.onload=function(){b.$nextCanv.height=this.height,b.$nextCanv.width=this.width,b.loadingStep()},b.imgControlPrev.src=b.$controlLeft.getAttribute("data-src"),b.imgControlNext.src=b.$controlRight.getAttribute("data-src")):b.showArrowControls=!1,b.width<=0&&(b.width=b.$container.clientWidth),b.height<=0&&(b.height=b.$container.clientHeight),b.mouseDownRegion=0,b.colorArr=b.parseColor(b.color),b.hoverColorArr=b.parseColor(b.hoverColor),b.mx=-1,b.my=-1,b.swipeOffset=0,b.cw=b.getCw(),b.ch=b.getCh(),b.frame=0,b.nextSlideTimer=!1,b.currImg=0,b.lastImg=0,b.imagesLoaded=0,b.pxlBuffer={first:null},b.recycleBuffer={first:null},b.ctx=b.$canv.getContext("2d"),b.srcCtx=b.$srcCanv.getContext("2d"),b.prevCtx=b.$prevCanv.getContext("2d"),b.nextCtx=b.$nextCanv.getContext("2d"),b.$canv.width=b.cw,b.$canv.height=b.ch,b.shuffle=function(){var a,b;for(var c=0,d=this.length;c<d;c++)b=Math.floor(Math.random()*d),a=this[c],this[c]=this[b],this[b]=a},Array.prototype.shuffle=b.shuffle,b.$canv.onmouseout=function(){b.mx=-1,b.my=-1,b.mouseDownRegion=0},b.$canv.onmousemove=function(a){function c(a){var c=0,d=0,e=typeof a=="string"?b.$(a):a;if(e){c=e.offsetLeft,d=e.offsetTop;var f=document.getElementsByTagName("body")[0];while(e.offsetParent&&e!=f)c+=e.offsetParent.offsetLeft,d+=e.offsetParent.offsetTop,e=e.offsetParent}this.x=c,this.y=d}var d=new c(b.$container);b.mx=a.clientX-d.x+document.body.scrollLeft+document.documentElement.scrollLeft,b.my=a.clientY-d.y+document.body.scrollTop+document.documentElement.scrollTop},b.$canv.onmousedown=function(){if(b.imgs.length>1){var a=0;b.mx>=0&&b.mx<b.arrowPadding*2+b.$prevCanv.width?a=-1:b.mx>0&&b.mx>b.cw-(b.arrowPadding*2+b.$nextCanv.width)&&(a=1),b.mouseDownRegion=a}},b.$canv.onmouseup=function(){if(b.imgs.length>1){var a="";b.mx>=0&&b.mx<b.arrowPadding*2+b.$prevCanv.width?a=-1:b.mx>0&&b.mx>b.cw-(b.arrowPadding*2+b.$nextCanv.width)&&(a=1),a!=0&&b.mouseDownRegion!=0&&(a!=b.mouseDownRegion&&(a*=-1),b.nextSlideTimer&&clearTimeout(b.nextSlideTimer),b.nextSlide(a)),b.mouseDownRegion=0}};if(b.imgs.length==0)for(var d=0,e=b.$$slides.length;d<e;d++){var f=new Image;b.imgs.push(f),f.src=b.$$slides[d].getAttribute("data-src")}b.imgs.length>0&&(b.imgs[0].onload=function(){b.loadingStep()}),b.requestAnimationFrame(function(){b.nextFrame()})}var psParticle=function(a){this.ps=a,this.ttl=null,this.color=a.colorArr,this.next=null,this.prev=null,this.gravityX=0,this.gravityY=0,this.x=Math.random()*a.cw,this.y=Math.random()*a.ch,this.velocityX=Math.random()*10-5,this.velocityY=Math.random()*10-5};psParticle.prototype.move=function(){var a=this.ps,b=this;if(this.ttl!=null&&this.ttl--<=0)a.swapList(b,a.pxlBuffer,a.recycleBuffer),this.ttl=null;else{var c=this.gravityX+a.swipeOffset-this.x,d=this.gravityY-this.y,e=Math.sqrt(Math.pow(c,2)+Math.pow(d,2)),f=Math.atan2(d,c),g=e*.01;a.restless==!0?g+=Math.random()*.1-.05:g<.01&&(this.x=this.gravityX+.25,this.y=this.gravityY+.25);var h=0,i=0;if(a.mx>=0&&a.mouseForce){var j=this.x-a.mx,k=this.y-a.my;h=Math.min(a.mouseForce/(Math.pow(j,2)+Math.pow(k,2)),a.mouseForce),i=Math.atan2(k,j),typeof this.color=="function"&&(i+=Math.PI,h*=.001+Math.random()*.1-.05)}else h=0,i=0;this.velocityX+=g*Math.cos(f)+h*Math.cos(i),this.velocityY+=g*Math.sin(f)+h*Math.sin(i),this.velocityX*=.92,this.velocityY*=.92,this.x+=this.velocityX,this.y+=this.velocityY}},ParticleSlider.prototype.Particle=psParticle,ParticleSlider.prototype.swapList=function(a,b,c){var d=this;a==null?a=new d.Particle(d):b.first==a?a.next!=null?(a.next.prev=null,b.first=a.next):b.first=null:a.next==null?a.prev.next=null:(a.prev.next=a.next,a.next.prev=a.prev),c.first==null?(c.first=a,a.prev=null,a.next=null):(a.next=c.first,c.first.prev=a,c.first=a,a.prev=null)},ParticleSlider.prototype.parseColor=function(a){var b,a=a.replace(" ","");if(b=/^#([\da-fA-F]{2})([\da-fA-F]{2})([\da-fA-F]{2})/.exec(a))b=[parseInt(b[1],16),parseInt(b[2],16),parseInt(b[3],16)];else if(b=/^#([\da-fA-F])([\da-fA-F])([\da-fA-F])/.exec(a))b=[parseInt(b[1],16)*17,parseInt(b[2],16)*17,parseInt(b[3],16)*17];else if(b=/^rgba\(([\d]+),([\d]+),([\d]+),([\d]+|[\d]*.[\d]+)\)/.exec(a))b=[+b[1],+b[2],+b[3],+b[4]];else if(b=/^rgb\(([\d]+),([\d]+),([\d]+)\)/.exec(a))b=[+b[1],+b[2],+b[3]];else return null;isNaN(b[3])&&(b[3]=1),b[3]*=255;return b},ParticleSlider.prototype.loadingStep=function(){var a=this;a.imagesLoaded++;if(a.imagesLoaded>=3||a.showArrowControls==!1)a.resize(),a.slideDelay>0&&(a.nextSlideTimer=setTimeout(function(){a.nextSlide()},1e3*a.slideDelay))},ParticleSlider.prototype.$=function(a,b,c){var d=this;if(a[0]=="."){var e=a.substr(1);b||(b=d.$$children);var f=[];for(var g=0,h=b.length;g<h;g++)b[g].className&&b[g].className==e&&f.push(b[g]);return f.length==0?null:f.length==1&&!c?f[0]:f}return document.getElementById(a.substr(1))},ParticleSlider.prototype.nextFrame=function(){var a=this;a.mouseDownRegion==1&&a.mx<a.cw/2||a.mouseDownRegion==-1&&a.mx>a.cw/2?a.swipeOffset=a.mx-a.cw/2:a.swipeOffset=0;var b=a.pxlBuffer.first,c=null;while(b!=null)c=b.next,b.move(),b=c;a.drawParticles();if(a.frame++%25==0&&(a.cw!=a.getCw()||a.ch!=a.getCh())){var d=a.getCh(),e=a.getCw();a.ch!=e&&typeof a.onWidthChange=="function"&&a.onWidthChange(a,e),a.ch!=d&&typeof a.onHeightChange=="function"&&a.onHeightChange(a,d),typeof a.onSizeChange=="function"&&a.onSizeChange(a,e,d),a.resize()}setTimeout(function(){a.requestAnimationFrame(function(){a.nextFrame()})},15)},ParticleSlider.prototype.nextSlide=function(a){var b=this;b.nextSlideTimer!=null&&b.imgs.length>1?(b.currImg=(b.currImg+b.imgs.length+(a?a:1))%b.imgs.length,b.resize(),b.slideDelay>0&&(b.nextSlideTimer=setTimeout(function(){b.nextSlide()},1e3*b.slideDelay))):b.slideDelay>0&&(b.nextSlideTimer=setTimeout(function(){b.nextSlide()},1e3*b.slideDelay)),typeof b.onNextSlide=="function"&&b.onNextSlide(b.currImg)},ParticleSlider.prototype.drawParticles=function(){var a=this,b=a.ctx.createImageData(a.cw,a.ch),c=b.data,d,e,f,g,h,i,j=a.pxlBuffer.first;while(j!=null){e=~~j.x,f=~~j.y;for(g=e;g<e+a.ptlSize&&g>=0&&g<a.cw;g++)for(h=f;h<f+a.ptlSize&&h>=0&&h<a.ch;h++)d=(h*b.width+g)*4,i=typeof j.color=="function"?j.color():j.color,c[d+0]=i[0],c[d+1]=i[1],c[d+2]=i[2],c[d+3]=i[3];j=j.next}b.data=c,a.ctx.putImageData(b,0,0)},ParticleSlider.prototype.getPixelFromImageData=function(a,b,c){var d=this,e=[];for(var f=0;f<a.width;f+=d.ptlGap+1)for(var g=0;g<a.height;g+=d.ptlGap+1)i=(g*a.width+f)*4,a.data[i+3]>0&&e.push({x:b+f,y:c+g,color:d.monochrome==!0?[d.colorArr[0],d.colorArr[1],d.colorArr[2],d.colorArr[3]]:[a.data[i],a.data[i+1],a.data[i+2],a.data[i+3]]});return e},ParticleSlider.prototype.init=function(a){var b=this;if(b.imgs.length>0){b.$srcCanv.width=b.imgs[b.currImg].width,b.$srcCanv.height=b.imgs[b.currImg].height,b.srcCtx.clearRect(0,0,b.$srcCanv.width,b.$srcCanv.height),b.srcCtx.drawImage(b.imgs[b.currImg],0,0);var c=b.getPixelFromImageData(b.srcCtx.getImageData(0,0,b.$srcCanv.width,b.$srcCanv.height),~~(b.cw/2-b.$srcCanv.width/2),~~(b.ch/2-b.$srcCanv.height/2));if(b.showArrowControls==!0){b.prevCtx.clearRect(0,0,b.$prevCanv.width,b.$prevCanv.height),b.prevCtx.drawImage(b.imgControlPrev,0,0);var d=b.getPixelFromImageData(b.prevCtx.getImageData(0,0,b.$prevCanv.width,b.$prevCanv.height),b.arrowPadding,~~(b.ch/2-b.$prevCanv.height/2));for(var e=0,f=d.length;e<f;e++)d[e].color=function(){return b.mx>=0&&b.mx<b.arrowPadding*2+b.$prevCanv.width?b.hoverColorArr:b.colorArr},c.push(d[e]);b.nextCtx.clearRect(0,0,b.$nextCanv.width,b.$nextCanv.height),b.nextCtx.drawImage(b.imgControlNext,0,0);var g=b.getPixelFromImageData(b.nextCtx.getImageData(0,0,b.$nextCanv.width,b.$nextCanv.height),b.cw-b.arrowPadding-b.$nextCanv.width,~~(b.ch/2-b.$nextCanv.height/2));for(var e=0,f=g.length;e<f;e++)g[e].color=function(){return b.mx>0&&b.mx>b.cw-(b.arrowPadding*2+b.$nextCanv.width)?b.hoverColorArr:b.colorArr},c.push(g[e])}if(b.currImg!=b.lastImg||a==!0)c.shuffle(),b.lastImg=b.currImg;var h=b.pxlBuffer.first;for(var e=0,f=c.length;e<f;e++){var i=null;h!=null?(i=h,h=h.next):(b.swapList(b.recycleBuffer.first,b.recycleBuffer,b.pxlBuffer),i=b.pxlBuffer.first),i.gravityX=c[e].x,i.gravityY=c[e].y,i.color=c[e].color}while(h!=null)h.ttl=~~(Math.random()*10),h.gravityY=~~(b.ch*Math.random()),h.gravityX=~~(b.cw*Math.random()),h=h.next;b.$overlay.innerHTML=b.$$slides[b.currImg].innerHTML}},ParticleSlider.prototype.getCw=function(){var a=this;return Math.min(document.body.clientWidth,a.width,a.$container.clientWidth)},ParticleSlider.prototype.getCh=function(){var a=this;return Math.min(document.body.clientHeight,a.height,a.$container.clientHeight)},ParticleSlider.prototype.resize=function(){var a=this;a.cw=a.getCw(),a.ch=a.getCh(),a.$canv.width=a.cw,a.$canv.height=a.ch,a.init(!0)},ParticleSlider.prototype.setColor=function(a){var b=this;b.colorArr=b.parseColor(a)},ParticleSlider.prototype.setHoverColor=function(a){var b=this;b.hoverColorArr=b.parseColor(a)},ParticleSlider.prototype.requestAnimationFrame=function(a){var b=this,c=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){window.setTimeout(a,1e3/60)};c(a)}
;
matisetorm
  • 847
  • 8
  • 21
Mike.Whitehead
  • 738
  • 13
  • 38

5 Answers5

5

tl;dr

replace this code:

<script type="text/javascript">
    var ps = new ParticleSlider({ 'width':'1400', 'height': '600' });
</script>

with this code:

<script type="text/javascript">
//wait until the DOM is ready to be queried
document.addEventListener('DOMContentLoaded', function() { //DOM-ready callback
    var ps, timeout;
    handlePS();
    window.addEventListener('resize', function() {
        if (timeout) { //check if the timer has been set
            clearTimeout(timeout); //clear the timer
        }
        //set a timer
        timeout = setTimeout(handlePS, 250);
    });

    function handlePS() {
        if (document.body.clientWidth >= 960) {
            //check if ps is assigned as an instance of the ParticleSlider 
            if (window.ps && typeof ps !== null) {
                ps.init(); //refresh the particle slider since it exists
            } else {
                //otherwise create a new instance of the particle slider
                ps = new ParticleSlider({
                    'width': '1400', 
                    'height': '600'
                });
            }
        }
        else {
            //when the flat logo is displayed, get rid of the particle slider instance
            ps = null;
        }
    }
});
</script>

Explanation: Call init() on resize

One can add a callback for when the resize event occurs (as others have mentioned) and call the init() method depending on the current width of the window.

It might be advisable to move the code that creates the Particle Slider instance to a function, which checks if the width of the window is greater than or equal to 960 pixels (using .clientWidth of document.body) and if so, if the instance has been created or not using a variable ps declared outside the function. If the instance has been created, call the init method; Otherwise create the instance. But if the width is less than 960 pixels then set the variable ps to null.

var ps; //declare out here for use in multiple functions
function handlePS() {
    if (document.body.clientWidth > 960) {
        if (window.ps && typeof ps !== null) {
            ps.init();
        } else {
            ps = new ParticleSlider({'width': '1400', 'height': '600'});
        }
    }
    else {
            ps = null;
    }
}

Then that function can be called when the page loads as well as when the resize event occurs:

handlePS();
window.addEventListener('resize', handlePS);

See a demonstration in this sample page. There are a few other enhancements added:

  • it waits for the DOM to be ready by calling handlePS() and listening for the resize event after the DOMContentLoaded event has been fired by using document.addEventListener
  • it uses setTimeout for a debounce effect so that the init() method is called 250ms after the scroll event ends instead of continuously during a scroll event.

So the code with those enhancements looks like below:

//wait until the DOM is ready to be queried
document.addEventListener('DOMContentLoaded', function() { //DOM-ready callback
    var ps, timeout;
    handlePS();
    window.addEventListener('resize', function() {
        //https://davidwalsh.name/javascript-debounce-function
        if (timeout) { //check if the timer has been set
                clearTimeout(timeout); //clear the timer
        }
        //set a timer
        timeout = setTimeout(handlePS, 250);
    });

    function handlePS() {
        if (document.body.clientWidth >= 960) {
            //check if ps is assigned as an instance of the ParticleSlider 
            if (window.ps && typeof ps !== null) {
                ps.init(); //refresh the particle slider since it exists
            } else {
                //otherwise create a new instance of the particle slider
                ps = new ParticleSlider({
                    'width': '1400', 
                    'height': '600'
                });
            }
        }
        else {
            //when the flat logo is displayed, get rid of the particle slider instance
            ps = null;
        }
    }
});

And because you added the tag, jQuery could be used to simplify things a bit:

instead of

window.addEventListener('resize', handlePS);

use:

$(window).on('resize, handlePS);

And replace document.body.clientWidth width $(document).width().

Update

I used the image from your comment in the updated sample page. I also pared down the code used on the Particle Slider demo page and added in that image on this demo page. It still suffers from flashing when there is a resize.

Sᴀᴍ Onᴇᴌᴀ
  • 7,491
  • 8
  • 27
  • 56
  • The actual ps effect isn't working very well when I implement your code. When I start re-sizing the page the logo effect starts flickering like a light switch. I note on the sample page the logo appears quite large. – Mike.Whitehead Oct 31 '17 at 10:10
  • Well I reused the same logo image for the flat logo but I updated it to have smaller dimensions; which browser do you see the flickering in? – Sᴀᴍ Onᴇᴌᴀ Oct 31 '17 at 11:56
  • It was happening in all of them. – Mike.Whitehead Oct 31 '17 at 11:58
  • I wonder if PS is having issues with that larger image... I tried paring down the sample from the website and using that logo image found in one of your other questions - it still had issues, even after compressing the PNG (from 285 KB to 75 KB) and converting to GIF (which was 82 KB)... http://samonela.scienceontheweb.net/javascript/ps.html – Sᴀᴍ Onᴇᴌᴀ Nov 01 '17 at 16:16
  • I can send you the image used in the ps file - will that help? I’m out at the moment but I can send it over in a couple of hours. – Mike.Whitehead Nov 01 '17 at 16:19
  • Here's a link to the exact image file used for the ps.js effect - http://res.cloudinary.com/mrmw1974/image/upload/v1509566686/havoc_logohight_bmdycw.png – Mike.Whitehead Nov 01 '17 at 20:07
  • I feel like we're close on this if I can get the image to work properly. – Mike.Whitehead Nov 01 '17 at 20:09
  • Any more thoughts on this, Sam? It basically works - as in the logo effect comes back on when I re-size the page it's just that the logo image starts flickering until I refresh the page. – Mike.Whitehead Nov 04 '17 at 15:37
  • Like I mentioned in my [update yesterday](https://stackoverflow.com/revisions/47023356/7) I used that image you shared and got it closer but I am not sure what to do about the flickering... have you contacted the PS support about it? – Sᴀᴍ Onᴇᴌᴀ Nov 04 '17 at 16:14
  • No, I didn't do the ps.js code - I had it done for me via an illustrator on Upworks. I guess that's the next step. – Mike.Whitehead Nov 04 '17 at 16:17
1

Update (30 Oct 2017)

So the issue appeared to be the fact that since you hide the div that is used by ParticleSlider for drawing, it gets Canvas with size 0x0 and this leads to an exception somewhere inside drawParticles method which is called by nextFrame. Another important fact is that ParticleSlider is designed in such a way that after the first call initiated from constructor, nextFrame uses requestAnimationFrame to schedule itself. All other methods (such as nextSlide or resize) just change data but do not re-start animation sequence. Thus exception at the first call stops animation and to fix it, you need to call nextFrame explicitly.

So the basic idea is that you patch nextFrame to track failure/success and call it from resize handler if needed. Here is some code:

var ps = new ParticleSlider({ 'width': '1400', 'height': '600' });

// patch nextFrame to track failure/success
var nextFrameCalled = false;
ps.oldNextFrame = ps.nextFrame;
ps.nextFrame = function () {
    try {
        ps.oldNextFrame.apply(this, arguments);
        nextFrameCalled = true;
    } catch (e) {
        console.log(e);
        nextFrameCalled = false;
    }
};

var addEvent = function (object, type, callback) {
    if (object.addEventListener) {
        object.addEventListener(type, callback, false);
    } else if (object.attachEvent) {
        object.attachEvent("on" + type, callback);
    } else {
        object["on" + type] = callback;
    }
};
var oldWidth = window.innerWidth;
addEvent(window, 'resize', function () {
    var newWidth = window.innerWidth;
    if (newWidth >= 960 && oldWidth < 960) {
        console.log("Restarting particle slider " + newWidth);
        ps.resize();
        if (!nextFrameCalled)
            ps.nextFrame();  // force restart animation
        else {
            // ensure that nextFrameCalled is not still true from previous cycle
            nextFrameCalled = false;
            setTimeout(function () {
                if (!nextFrameCalled)
                    ps.nextFrame();  // force restart animation
            }, 100);
        }
    }
    oldWidth = newWidth;
});

You can see live demo at this plunker. Open demo in a separate window. Then you'll have 2 seconds to set initial size more or less than 960px so you can simulate any starting conditions. After 2 seconds timeout the main code starts.

Original answer

It looks like you lack a piece of code that would re-shuffle particles when window size is changed to >960px. I haven't tried it, but I expect that something like this should help you (if you use jQuery):

var ps = new ParticleSlider({ 'width': '1400', 'height': '600' });

var oldWidth = $(window).width();
$(window).resize(function () {
    var newWidth = $(window).width();
    if (newWidth >= 960 && oldWidth < 960)
        ps.resize(); // this should call init() which in turn should re-shuffle particles
    oldWidth = newWidth;
});

Obviously you can write an equivalent code without jQuery for example as suggested in this SO answer

SergGr
  • 22,842
  • 2
  • 25
  • 49
  • Sorry, that hasn't worked. Did I have to make some changes to the code above? I'm not that familiar with jQuery so wasn't sure if this code was ready to just be lifted straight up and put into my text file. – Mike.Whitehead Oct 30 '17 at 09:08
  • I've looked at the link - there's no doubt that the resize code is the way forward but I haven't got the first clue how to do that as I'm simply not versed in javascript. – Mike.Whitehead Oct 30 '17 at 09:11
  • @Mike.Whitehead, I think I've found the reason of the failure. See my updated answer and the demo. – SergGr Oct 30 '17 at 20:07
  • Thank you for the amount of detail and time you've gone to, I really appreciate it. It works perfectly on Chrome, almost works perfectly on Firefox ( the flat logo >960px appears squashed as though it is being pushed upwards to make space for the blank canvas) but still doesn't work at all on Safari. – Mike.Whitehead Oct 30 '17 at 23:15
  • @Mike.Whitehead, when you say "_still doesn't work at all on Safari_", do you mean my Plunker demo or your real site? The thing is that Safari has stronger cross-origin policy for image/canvas and I don't know any images hosted by run.plnkr.co so I can't put safe URL to this demo. I've update the demo with the image encoded into the HTML. Take a look. – SergGr Oct 31 '17 at 01:24
  • Hi, sorry, missed this last night. I mean your code didn't make the image re-appear in my site. It works in Chrome and kind-of works in Firefox except the replacement image is appearing squashed when it switches >960px. – Mike.Whitehead Oct 31 '17 at 09:41
  • @Mike.Whitehead, does it work for you in Safari in my updated demo with image encoded into HTML? Which version of Safari do you use? When it doesn't work, do you have any errors in the Console? It is hard to troubleshoot this because the updated demo works for me in Safari. – SergGr Oct 31 '17 at 12:13
  • @Mike.Whitehead, you mean even update Plunker demo doesn't work for you in Safari? Does it not work only for resizing or does it show nothing even if you start with wide (>960px) window? – SergGr Oct 31 '17 at 13:34
  • To be honest I don't really understand the plunker example - I've read your instructions below but before I get a chance to look at anything an arrow image appears. I've copied your code example above into my code - should I not be doing that? – Mike.Whitehead Oct 31 '17 at 14:14
  • @SergeGr The logo works in Safari but won't re-appear when I re-size the page. – Mike.Whitehead Oct 31 '17 at 14:15
  • @Mike.Whitehead, I don't know how to troubleshoot it further. I've installed Safari Version 11.0 (12604.1.38.1.7) and my demo works fine for me both 1) when I start wide and then shrink and extend and 2) when I start narrow and extend. Do you do something tricky? Do you have some steps to reproduce? As for my demo, steps are: 1) Open the link 2) Click the blue "expand" button in the top-right ("Launch the preview in a separate window") 3) Optionally move the new tab to a separate window 4) Set it any initial size you want 4) Refresh that tab 5) Wait 3 secs. 6) Change width again as you want. – SergGr Oct 31 '17 at 15:02
  • Okay, I got the demo working (my fault) and it works in Safari. I'm not sure how to troubleshoot either as this is now a cross-browser issue - Firefox/Chrome/Safari are all producing different results. – Mike.Whitehead Oct 31 '17 at 15:34
0

You can use the resize function of ParticleSlider in jquery smart resize. So you will have more control on the function.

var ps = new ParticleSlider({ 'width': '1400', 'height': '600' });
$(window).on("debouncedresize", function( event ) {
    ps.resize();
});
Rijo
  • 1,711
  • 1
  • 13
  • 24
0

The Problem is the following: The slider draws with js into the canvas, seems like the script is loaded once on page load... The slider shall be responsive as the athors say on their site, but in fact the slider is just resized and not replayed on window resize...

To me it seems like calling

ps.nextSlide(0);

on $(window).resize() could help. This reloads the current slide!

If this does not work too, try to reload the whole slider with the init() function or maybe the loadingStep() function! (The documentation is sadly not that clear to me at some points...)

i.e.:

$(window).resize(function(){
    ps.nextSlide(0);
});

You can see the functions availeble here:

http://particleslider.com/documentation/reference

ToTaTaRi
  • 311
  • 1
  • 8
  • if you have no Jquery installed you could use pure JS like this: window.onresize = function(event) { ... }; – ToTaTaRi Oct 30 '17 at 09:33
0

Your use case has two major issues:

  • When you init the Particles before the target is visible the image has an invalid size (0x0)
  • Once the Animation is running and you make the resolution smaller the animation keeps running in the background

I tried to handle both issues in the following script.

var ps = null

function init(){
  var isVisible = window.innerWidth >= 960;
  if (!ps && isVisible) {
    // create and init
    ps = new ParticleSlider({
      ptlGap: 1,
      ptlSize: 1,
      width: 1e9,
      height: 100,
    });

    ps.init(false);
  } else if (ps && !isVisible) {
    // stop and remove
    ps.requestAnimationFrame = function() {}; // Stop render loop
    ps = null;
  }
}

window.addEventListener('load', init, false)
window.onload = init;
window.addEventListener('resize', init, false);
window.onresize = init;
html, body {
  background-color: black;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  color: #fff;
  text-align: center;
}

.slides, & > .dg {
  display: none;
}

.low-res {
  display: none;
}

@media screen and (max-width: 959px) {
  .draw {
    display: none;
  }

  .low-res {
    display: inline;
    width: 50%;
  }
}
<html>
  <head>
    <meta name="viewport" content="width=device-width" />
    <title>ParticleSlider</title>
    <script src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/23500/ps-0.9.js"></script>
  </head>
  <body id="particle-slider">
    <div class="slides">
      <div id="first-slide" class="slide" data-src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGkAAAAgCAMAAAAmC6asAAAAMFBMVEX19vf19vft7u/19vfp6uv19vfx8vP19vf19vf19vf19vfm5+j19vcAAAD19vfl5udu+MchAAAADnRSTlOIVcIz10StZneZEewiAMEzGswAAAF/SURBVHja7ZXZbsQwCEXjneXa/P/fFntm0uRpVGkaqVX8YAW4cMCxkq1ftW7STbpJP1sJb0lFPkJiekuq4TMkfkti+gxpe0uivRmB9LQOlHraNixnYErPONAfcYZntYfv9aDtJTmUO5OCeukGR5paqZtbGaSVzYWIlZ9DI6vVpC6shJw5TzdlZk47qZpldAkteBVToxNJrLGqoil6MPE9A1bSNorUXPYWvbLUjbg37lwRNPYW6x6eJK4ilB2hVmChJw2nWx4He3Map1exMVFvQyMVN78rlexbY7Gk0tWUm7gsHUnikQ6dwzLRLM/tRKIlGMMFoijmpthqBocLFTLWO41GnhrFXZIGTiTz5pIyA9G4uqSeSV3W4bSsqvycg0x9RTpcKHaHHybNOZBXfPa41jNjLCeqjRopzgI4kXYcsDqVZWJaZwVWHpYBTOuoACCvEpjTC3DFd6/oVV9YmPw+CWsb+H1SxVWkkgkoV5B6ijasXnMjBPIf/u436e+TvgDCaqPX6lO5yQAAAABJRU5ErkJggg==">
      </div>
    </div>
    <canvas class="draw"></canvas>
    <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/23500/codepen-white.png" class="low-res"/>
  </body>
</html>
Community
  • 1
  • 1
  • This works and looks great but I think the ps.requestAnimationFrame function may be preventing the canvas to resize in Safari? – Mike.Whitehead Dec 13 '17 at 13:58