JavaScript – 必须刷新页面以显示粒子滑块徽标效果

我正在使用HTML 5 Blank Child Theme从Wordpress加载前端站点。 我有一个使用粒子滑块的徽标效果,当我的屏幕尺寸> 960px时; 对于屏幕尺寸<960px我有一个平面徽标图像。 这一切都很好但是当我在徽标之间重新调整大小时,必须手动刷新页面(即通过按cmd + r )才能再次显示PS效果。 如何纠正这个问题,以便在重新调整尺寸后自动显示效果?

这是我的代码 –

粒子slider.php

  
<div class="slide" data-src="https://stackoverflow.com/questions/46933391/javascript-page-has-to-be-refreshed-to-show-particle-slider-logo-effect//wp-content/uploads/2017/10/havoc_logohight.png">
var ps = new ParticleSlider({ 'width':'1400', 'height': '600' });

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;c1){var a=0;b.mx>=0&&b.mx0&&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.mx0&&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;d0&&(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=0&&a.mouseForce){var j=this.xa.mx,k=this.ya.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.mxa.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=~~jx,f=~~jy;for(g=e;g=0&&g<a.cw;g++)for(h=f;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;g0&&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=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;e0&&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)} ; 

TL;博士

替换此代码:

  

使用此代码:

  

说明:在resize上调用init()

可以在resize事件发生时添加回调(正如其他人提到的那样),并根据窗口的当前宽度调用init()方法。

建议将创建Particle Slider实例的代码移动到一个函数,该函数检查窗口的宽度是否大于或等于960像素(使用document.body的.clientWidth ),如果是,则检查实例已创建或未使用在函数外声明的变量ps 。 如果已创建实例,请调用init方法; 否则创建实例。 但如果宽度小于960像素,则将变量ps设置为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; } } 

然后,当页面加载时以及resize事件发生时,可以调用该函数:

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

请参阅此示例页面中的演示。 还添加了一些其他增强function:

  • 它等待DOM准备就绪,通过调用handlePS()并在使用document.addEventListener触发DOMContentLoaded事件后侦听resize事件
  • 它使用setTimeout进行去抖动效果,以便在滚动事件结束后250ms内调用init()方法,而不是在滚动事件期间连续调用。

所以具有这些增强function的代码如下所示:

 //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; } } }); 

因为你添加了jquery标签,jQuery可以用来简化一些事情:

代替

 window.addEventListener('resize', handlePS); 

使用:

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

并替换document.body.clientWidth width $(document).width()

更新

我在更新的示例页面中使用了您评论中的图像 。 我还减少了粒子滑块演示页面上使用的代码,并在该演示页面上添加了该图像。 当有resize时,它仍然会闪烁。

更新 (2017年10月30日)

所以问题似乎是因为你隐藏了ParticleSlider用于绘图的div ,它获得了大小为0x0的Canvas ,这导致了drawParticles方法中某个地方的exception,该方法由nextFrame 。 另一个重要的事实是, ParticleSlider的设计方式是,在构造函数启动的第一次调用之后, nextFrame使用requestAnimationFrame来自我调度。 所有其他方法(例如nextSlideresize )只是更改数据但不重新启动动画序列。 因此,第一次调用时exception会停止动画并修复它,您需要显式调用nextFrame

因此,基本思想是修补nextFrame以跟踪失败/成功,并在需要时从resize处理程序调用它。 这是一些代码:

 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; }); 

你可以看到这个plunker的现场演示。 在单独的窗口中打开演示。 然后你将有2秒的时间来设置初始大小大于或小于960px,这样你就可以模拟任何起始条件。 2秒后超时,主代码启动。

原始答案

看起来你缺少一段代码,当窗口大小改为> 960px时会重新混洗粒子。 我没有尝试过,但我希望这样的东西可以帮助你(如果你使用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; }); 

显然,你可以编写一个没有jQuery的等效代码,例如本SO答案中的建议

您可以在jquery smart resize中使用ParticleSlider的resize函数。 所以你将对这个function有更多的控制权。

 var ps = new ParticleSlider({ 'width': '1400', 'height': '600' }); $(window).on("debouncedresize", function( event ) { ps.resize(); }); 

您的用例有两个主要问题:

  • 在目标可见之前初始化粒子时,图像的大小无效(0x0)
  • 动画运行后,如果分辨率变小,动画将在后台运行

我尝试在以下脚本中处理这两个问题。

 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%; } } 
    ParticleSlider