Skip to content

optional "snow falling" theme

Solved Customisation
6 4 2.4k 1
  • wrote on last edited by
    #1

    Hi @phenomlab , around Christmas time, we use this “custom header” which basically creates a snow effect on the screen.

    <script src="https://cdn.jsdelivr.net/gh/nextapps-de/snowflake@master/snowflake.min.js"></script>
    

    However, last year some users who were on desktops using Windows and Google chrome were complaining that this custom header increased CPU usage a lot.

    I wonder if it is possible to create a button switch on the navigation bar which will be on as default, and if users want, they can turn it off, and snow falling can stop.

    Of course, this will be a temporary button. I am not looking for a permanent change since we will remove the snow-falling effect right after the new year.

  • wrote on last edited by DownPW
    #2

    I’m doing this last year but for another JS script.

    I leave the code. Maybe you can take inspiration from it (or not)

    You can add button with HTML widget like this (adapt the code for your JS script) :

    HTML :

    <!-- Start/Stop button  -->
    <button id='fall'>Start/Stop Animation</button>
    <br>
    
    <!--Add DIV for CSS Snow -->
    <div class='snowc'></div>
    

    CSS:

    /*----------------------------------------------*/
    /* ---- Snow fall animation -*/
    /*----------------------------------------------*/
    
    /*Snow fall animation */
    .snowc {
        position: fixed;
        overflow: hidden;
        z-index: 0;
        height: 100%;
        width: 100%;
        pointer-events: none;
    }
      
    .snowc.paused .snow {
        -webkit-animation-play-state: paused;
        animation-play-state: paused;
    }
    
    .snow {
        position: absolute;
        top: -3%;
    }
    
    .snow-div {
        border-radius: 50%;
        background:#fff;
        height: 5px;
        width: 5px;
    }
    
    .snow svg {
        fill: #fff;
        height: 15px;
        width: 15px;
    }
    
    /*Start/Stop button */
    #fall {
        position: absolute;
        border: 1px solid lightgrey;
        border-radius: 5px;
        Background: #F5F5F5;
        top: 64px;
        left: 15px;
        z-index: 1;
        /*cursor: pointer;*/
        /*cursor: url(https://i.imgur.com/lIuoq3t.png) , pointer;*/
        cursor: url(https://i.imgur.com/Wx9mLm2.png) , pointer;
        font-weight: normal;
        /*background: #FF9700;*/
         opacity: 1;
         
    }
    
    .fall {border-radius: 15px;}
    
    /* Rotation */
    @keyframes snow-rotate{
        from{
            transform: rotate(0deg);
        }
        to{
            transform: rotate(360deg);
        }
    }
    

    JS :

    /*----------------------------------------------*/
    /* ---- Snow fall animation -*/
    /*----------------------------------------------*/
    var snow = {
        animate: true,
        containerSelector: '.snowc',
        particleCount: 0,
        particles: [300, 300],
        sizes: [25, 40],
        svgHeights: [15, 30], // Tailles pour les SVG
        svgWidths: [15, 30], // Tailles pour les SVG
        heights: [4, 6],
        widths: [4, 6],
        speeds: [12, 15],
        delay: [0, 11],
    
        rotate: true, // Rotation à la tombée
    
        useWind: true,
        windBlowingEast: true,
        windLinear: true, // Le vent dérive en tombant ou file tout droit jusqu'au point final
        windStrength: 1,
    
        useSvg: false, // Utilise SVG au lieu de div stylisée
        SVG: '<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="36.073px" height="36.073px" viewBox="0 0 36.073 36.073" style="enable-background:new 0 0 36.073 36.073;" xml:space="preserve"><g><path d="M33.526,19.58l-8.045,2.153l-6.404-3.697l6.404-3.698l8.045,2.155c0.045,0.013,0.091,0.018,0.136,0.018 c0.23,0,0.44-0.153,0.501-0.387c0.074-0.278-0.09-0.563-0.368-0.638l-7.038-1.885l6.708-3.874c0.248-0.144,0.333-0.462,0.19-0.711 c-0.146-0.25-0.464-0.334-0.712-0.19l-6.705,3.873l1.886-7.037c0.073-0.278-0.091-0.563-0.368-0.638 c-0.277-0.073-0.562,0.09-0.638,0.369l-2.155,8.042l-6.404,3.698V9.739l5.887-5.889c0.204-0.203,0.204-0.533,0-0.737 c-0.202-0.203-0.533-0.203-0.736,0l-5.151,5.153V0.521C18.558,0.234,18.324,0,18.037,0c-0.287,0-0.521,0.234-0.521,0.521v7.745 l-5.151-5.153c-0.204-0.203-0.534-0.203-0.737,0c-0.203,0.204-0.203,0.534,0,0.737l5.888,5.889v7.396l-6.405-3.698L8.956,5.394 C8.88,5.116,8.596,4.952,8.318,5.025C8.04,5.099,7.875,5.385,7.949,5.663l1.885,7.037L3.128,8.826 C2.88,8.683,2.561,8.767,2.417,9.017c-0.144,0.249-0.058,0.568,0.19,0.711l6.708,3.874l-7.039,1.885 C2,15.561,1.834,15.847,1.909,16.124c0.062,0.233,0.272,0.387,0.502,0.387c0.045,0,0.09-0.005,0.135-0.018l8.045-2.155l6.404,3.698 l-6.403,3.697l-8.045-2.154c-0.275-0.071-0.563,0.091-0.637,0.368C1.835,20.225,2,20.51,2.278,20.585l7.039,1.884l-6.708,3.874 c-0.249,0.145-0.334,0.462-0.19,0.712c0.097,0.167,0.272,0.261,0.452,0.261c0.088,0,0.178-0.021,0.26-0.069l6.708-3.874 L7.952,30.41c-0.074,0.278,0.091,0.563,0.369,0.637c0.045,0.013,0.091,0.019,0.136,0.019c0.229,0,0.439-0.153,0.502-0.387 l2.155-8.042l6.404-3.699v7.396l-5.887,5.89c-0.204,0.202-0.204,0.533,0,0.737c0.203,0.201,0.533,0.201,0.736,0l5.151-5.153v7.746 c0,0.286,0.233,0.521,0.521,0.521c0.287,0,0.521-0.234,0.521-0.521v-7.746l5.15,5.153c0.103,0.102,0.236,0.151,0.369,0.151 c0.135,0,0.268-0.052,0.368-0.151c0.204-0.204,0.204-0.535,0-0.737l-5.89-5.89v-7.394l6.403,3.697l2.155,8.044 c0.062,0.232,0.273,0.385,0.502,0.385c0.045,0,0.09-0.004,0.136-0.017c0.278-0.075,0.442-0.36,0.368-0.639l-1.888-7.035 l6.708,3.872c0.083,0.049,0.172,0.071,0.261,0.071c0.18,0,0.354-0.095,0.452-0.261c0.144-0.25,0.059-0.567-0.19-0.713l-6.708-3.873 l7.038-1.886c0.279-0.073,0.443-0.36,0.368-0.637C34.09,19.668,33.806,19.505,33.526,19.58z"/></g></svg>',
    
        init: function(){
            this.generateParticleCount();
    
            this.appendHTML();
            this.appendCSS();
        },
    
        generateParticleCount: function(){
            this.particleCount = this.particles[0] + (Math.round(Math.random() * (snow.particles[1] - snow.particles[0])));
        },
    
        appendHTML: function(jqselector){
            var html = this.generateHTML();
    
            jQuery(this.containerSelector).append(html);
        },
    
        generateHTML: function(){
            var html = '';
            for(var i=0; i<this.particleCount;i++)
            {
                if(this.useSvg){
                    html += '<div class="snow snow-particle-'+i+'">';
                    html += this.SVG;
                    html += '</div>';
                }else{
                
                    html += '<div class="snow snow-div snow-particle-'+i+'"></div>';
                };
            }
            return html;
        },
    
        appendCSS: function(){
            var css = this.generateCSS();
            css = '<style>' + css + '</style>';
            jQuery('head').append(css);
        },
    
    
        generateCSS: function(){
            var css = '';
            for(var i=0;i<this.particleCount;i++)
            {
                width  = this.widths[0]  + Math.round(Math.random()  * (this.widths[1] - this.widths[0]));
                height = this.heights[0] + Math.round(Math.random() * (this.heights[1] - this.heights[0]));
                time = this.speeds[0] + Math.random() * (this.speeds[1] - this.speeds[0]);
                delay = this.delay[0] + Math.random() * (this.delay[1] - this.delay[0]);
                rotateTime = Math.random() + 1;
    
                if(!this.useWind)
                    startingLeft = Math.round(Math.random() * 100);
                else
                    if(this.windBlowingEast){   
                        startingLeft = Math.round(Math.random() * 200) - 100;
                        endLeftPos = startingLeft + (Math.round(Math.random() * (this.windStrength * 50)));
                    }
                    else{
                        startingLeft = Math.round(Math.random() * 200) + 100;
                        endLeftPos = startingLeft - (Math.round(Math.random() * (this.windStrength * 50)));
                    }
    
                css += '.snow-particle-' + i + '{';
                css += 'left:' + startingLeft + '%;';
                if(!this.useSvg){
                    css += 'width: ' + width  + 'px;';
                    css += 'height: '+ height + 'px;';
                }
              
                if(this.animate){
                  css += 'animation: '+time+'s infinite ease-in anim-snow-particle-' + i + ', snow-rotate infinite '+rotateTime+'s linear;';
                  css += 'animation-delay: ' + delay + 's;';
                }else{
                  css += 'top:'  + endLeft + 'vh;';
                }
                css += '}';
    
                if(this.useSvg){
                    svgWidth  = this.svgWidths[0]  + Math.round(Math.random()  * (this.svgWidths[1] - this.svgWidths[0]));
                    svgHeight = this.svgHeights[0] + Math.round(Math.random() * (this.svgHeights[1] - this.svgHeights[0]));
    
                    css += '.snow-particle-' + i + ' svg{';
                    css + 'height: ' + svgHeight;
                    css + 'width: ' + svgWidth;
                    css += '}';
                }
    
                if(this.animate){
                  css += '@keyframes anim-snow-particle-'+i+'{';
                  css += '100%{';
                  css += 'top: 101%;';
                  if(this.useWind)
                      css += 'left: '+endLeftPos+'%';
                  css += '}';
                  css += '}';
                }
            }
            return css;
        }
    
    };
    
    snow.init();
    jQuery('#fall').click(function(){
      jQuery(snow.containerSelector).toggleClass('paused');
    });
    

    🤞

  • Hi @phenomlab , around Christmas time, we use this “custom header” which basically creates a snow effect on the screen.

    <script src="https://cdn.jsdelivr.net/gh/nextapps-de/snowflake@master/snowflake.min.js"></script>
    

    However, last year some users who were on desktops using Windows and Google chrome were complaining that this custom header increased CPU usage a lot.

    I wonder if it is possible to create a button switch on the navigation bar which will be on as default, and if users want, they can turn it off, and snow falling can stop.

    Of course, this will be a temporary button. I am not looking for a permanent change since we will remove the snow-falling effect right after the new year.

    wrote on last edited by phenomlab
    #3

    @crazycells the problem with JS scripts that execute animations is that they are being run in continuous loop. This presents the unwanted artifact of increasing the CPU cycles required to run it. In addition, with increasing CPU cycles will also come with increasing RAM which is being used to buffer in order to not overwhelm the CPU completely.

    There are two mechanisms you can use to prevent this. The “cheap” way is to include a pause function in the loop, or another statement that forces the current loop to close and be replaced with another (but with a very low time threshold to make it look like it’s not there at all).

    The other way is to “convince” the browser that it is supposed to be rendering 3D animation, which in turn, will then use hardware acceleration (unless the user disabled this) and offload the processing to the GPU instead. Traditionally, you’d use this css element to perform that

    transform: translateZ(0);
    

    There’s a more in depth explanation here

    https://stackoverflow.com/questions/13176746/css-keyframe-animation-cpu-usage-is-high-should-it-be-this-way

    In general, animations using JS can be quite unforgiving when it comes to performance. Executing onFocus is perfectly feasible as the process is killed onLeave or onMouseOut.

    Having an “on/off” button on the header or footer should ideally have a way of killing the loop - otherwise, it’ll continue to run without the animation giving you the false sense that everything is fine whilst it merrily chews CPU cycles in the background.

    Having completed the scripts that @DownPW and yourself have provided, my preference would be to use @DownPW version as it contains better coding methodology and gives you direct control over the CSS.

  • I’m doing this last year but for another JS script.

    I leave the code. Maybe you can take inspiration from it (or not)

    You can add button with HTML widget like this (adapt the code for your JS script) :

    HTML :

    <!-- Start/Stop button  -->
    <button id='fall'>Start/Stop Animation</button>
    <br>
    
    <!--Add DIV for CSS Snow -->
    <div class='snowc'></div>
    

    CSS:

    /*----------------------------------------------*/
    /* ---- Snow fall animation -*/
    /*----------------------------------------------*/
    
    /*Snow fall animation */
    .snowc {
        position: fixed;
        overflow: hidden;
        z-index: 0;
        height: 100%;
        width: 100%;
        pointer-events: none;
    }
      
    .snowc.paused .snow {
        -webkit-animation-play-state: paused;
        animation-play-state: paused;
    }
    
    .snow {
        position: absolute;
        top: -3%;
    }
    
    .snow-div {
        border-radius: 50%;
        background:#fff;
        height: 5px;
        width: 5px;
    }
    
    .snow svg {
        fill: #fff;
        height: 15px;
        width: 15px;
    }
    
    /*Start/Stop button */
    #fall {
        position: absolute;
        border: 1px solid lightgrey;
        border-radius: 5px;
        Background: #F5F5F5;
        top: 64px;
        left: 15px;
        z-index: 1;
        /*cursor: pointer;*/
        /*cursor: url(https://i.imgur.com/lIuoq3t.png) , pointer;*/
        cursor: url(https://i.imgur.com/Wx9mLm2.png) , pointer;
        font-weight: normal;
        /*background: #FF9700;*/
         opacity: 1;
         
    }
    
    .fall {border-radius: 15px;}
    
    /* Rotation */
    @keyframes snow-rotate{
        from{
            transform: rotate(0deg);
        }
        to{
            transform: rotate(360deg);
        }
    }
    

    JS :

    /*----------------------------------------------*/
    /* ---- Snow fall animation -*/
    /*----------------------------------------------*/
    var snow = {
        animate: true,
        containerSelector: '.snowc',
        particleCount: 0,
        particles: [300, 300],
        sizes: [25, 40],
        svgHeights: [15, 30], // Tailles pour les SVG
        svgWidths: [15, 30], // Tailles pour les SVG
        heights: [4, 6],
        widths: [4, 6],
        speeds: [12, 15],
        delay: [0, 11],
    
        rotate: true, // Rotation à la tombée
    
        useWind: true,
        windBlowingEast: true,
        windLinear: true, // Le vent dérive en tombant ou file tout droit jusqu'au point final
        windStrength: 1,
    
        useSvg: false, // Utilise SVG au lieu de div stylisée
        SVG: '<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="36.073px" height="36.073px" viewBox="0 0 36.073 36.073" style="enable-background:new 0 0 36.073 36.073;" xml:space="preserve"><g><path d="M33.526,19.58l-8.045,2.153l-6.404-3.697l6.404-3.698l8.045,2.155c0.045,0.013,0.091,0.018,0.136,0.018 c0.23,0,0.44-0.153,0.501-0.387c0.074-0.278-0.09-0.563-0.368-0.638l-7.038-1.885l6.708-3.874c0.248-0.144,0.333-0.462,0.19-0.711 c-0.146-0.25-0.464-0.334-0.712-0.19l-6.705,3.873l1.886-7.037c0.073-0.278-0.091-0.563-0.368-0.638 c-0.277-0.073-0.562,0.09-0.638,0.369l-2.155,8.042l-6.404,3.698V9.739l5.887-5.889c0.204-0.203,0.204-0.533,0-0.737 c-0.202-0.203-0.533-0.203-0.736,0l-5.151,5.153V0.521C18.558,0.234,18.324,0,18.037,0c-0.287,0-0.521,0.234-0.521,0.521v7.745 l-5.151-5.153c-0.204-0.203-0.534-0.203-0.737,0c-0.203,0.204-0.203,0.534,0,0.737l5.888,5.889v7.396l-6.405-3.698L8.956,5.394 C8.88,5.116,8.596,4.952,8.318,5.025C8.04,5.099,7.875,5.385,7.949,5.663l1.885,7.037L3.128,8.826 C2.88,8.683,2.561,8.767,2.417,9.017c-0.144,0.249-0.058,0.568,0.19,0.711l6.708,3.874l-7.039,1.885 C2,15.561,1.834,15.847,1.909,16.124c0.062,0.233,0.272,0.387,0.502,0.387c0.045,0,0.09-0.005,0.135-0.018l8.045-2.155l6.404,3.698 l-6.403,3.697l-8.045-2.154c-0.275-0.071-0.563,0.091-0.637,0.368C1.835,20.225,2,20.51,2.278,20.585l7.039,1.884l-6.708,3.874 c-0.249,0.145-0.334,0.462-0.19,0.712c0.097,0.167,0.272,0.261,0.452,0.261c0.088,0,0.178-0.021,0.26-0.069l6.708-3.874 L7.952,30.41c-0.074,0.278,0.091,0.563,0.369,0.637c0.045,0.013,0.091,0.019,0.136,0.019c0.229,0,0.439-0.153,0.502-0.387 l2.155-8.042l6.404-3.699v7.396l-5.887,5.89c-0.204,0.202-0.204,0.533,0,0.737c0.203,0.201,0.533,0.201,0.736,0l5.151-5.153v7.746 c0,0.286,0.233,0.521,0.521,0.521c0.287,0,0.521-0.234,0.521-0.521v-7.746l5.15,5.153c0.103,0.102,0.236,0.151,0.369,0.151 c0.135,0,0.268-0.052,0.368-0.151c0.204-0.204,0.204-0.535,0-0.737l-5.89-5.89v-7.394l6.403,3.697l2.155,8.044 c0.062,0.232,0.273,0.385,0.502,0.385c0.045,0,0.09-0.004,0.136-0.017c0.278-0.075,0.442-0.36,0.368-0.639l-1.888-7.035 l6.708,3.872c0.083,0.049,0.172,0.071,0.261,0.071c0.18,0,0.354-0.095,0.452-0.261c0.144-0.25,0.059-0.567-0.19-0.713l-6.708-3.873 l7.038-1.886c0.279-0.073,0.443-0.36,0.368-0.637C34.09,19.668,33.806,19.505,33.526,19.58z"/></g></svg>',
    
        init: function(){
            this.generateParticleCount();
    
            this.appendHTML();
            this.appendCSS();
        },
    
        generateParticleCount: function(){
            this.particleCount = this.particles[0] + (Math.round(Math.random() * (snow.particles[1] - snow.particles[0])));
        },
    
        appendHTML: function(jqselector){
            var html = this.generateHTML();
    
            jQuery(this.containerSelector).append(html);
        },
    
        generateHTML: function(){
            var html = '';
            for(var i=0; i<this.particleCount;i++)
            {
                if(this.useSvg){
                    html += '<div class="snow snow-particle-'+i+'">';
                    html += this.SVG;
                    html += '</div>';
                }else{
                
                    html += '<div class="snow snow-div snow-particle-'+i+'"></div>';
                };
            }
            return html;
        },
    
        appendCSS: function(){
            var css = this.generateCSS();
            css = '<style>' + css + '</style>';
            jQuery('head').append(css);
        },
    
    
        generateCSS: function(){
            var css = '';
            for(var i=0;i<this.particleCount;i++)
            {
                width  = this.widths[0]  + Math.round(Math.random()  * (this.widths[1] - this.widths[0]));
                height = this.heights[0] + Math.round(Math.random() * (this.heights[1] - this.heights[0]));
                time = this.speeds[0] + Math.random() * (this.speeds[1] - this.speeds[0]);
                delay = this.delay[0] + Math.random() * (this.delay[1] - this.delay[0]);
                rotateTime = Math.random() + 1;
    
                if(!this.useWind)
                    startingLeft = Math.round(Math.random() * 100);
                else
                    if(this.windBlowingEast){   
                        startingLeft = Math.round(Math.random() * 200) - 100;
                        endLeftPos = startingLeft + (Math.round(Math.random() * (this.windStrength * 50)));
                    }
                    else{
                        startingLeft = Math.round(Math.random() * 200) + 100;
                        endLeftPos = startingLeft - (Math.round(Math.random() * (this.windStrength * 50)));
                    }
    
                css += '.snow-particle-' + i + '{';
                css += 'left:' + startingLeft + '%;';
                if(!this.useSvg){
                    css += 'width: ' + width  + 'px;';
                    css += 'height: '+ height + 'px;';
                }
              
                if(this.animate){
                  css += 'animation: '+time+'s infinite ease-in anim-snow-particle-' + i + ', snow-rotate infinite '+rotateTime+'s linear;';
                  css += 'animation-delay: ' + delay + 's;';
                }else{
                  css += 'top:'  + endLeft + 'vh;';
                }
                css += '}';
    
                if(this.useSvg){
                    svgWidth  = this.svgWidths[0]  + Math.round(Math.random()  * (this.svgWidths[1] - this.svgWidths[0]));
                    svgHeight = this.svgHeights[0] + Math.round(Math.random() * (this.svgHeights[1] - this.svgHeights[0]));
    
                    css += '.snow-particle-' + i + ' svg{';
                    css + 'height: ' + svgHeight;
                    css + 'width: ' + svgWidth;
                    css += '}';
                }
    
                if(this.animate){
                  css += '@keyframes anim-snow-particle-'+i+'{';
                  css += '100%{';
                  css += 'top: 101%;';
                  if(this.useWind)
                      css += 'left: '+endLeftPos+'%';
                  css += '}';
                  css += '}';
                }
            }
            return css;
        }
    
    };
    
    snow.init();
    jQuery('#fall').click(function(){
      jQuery(snow.containerSelector).toggleClass('paused');
    });
    

    🤞

    wrote on last edited by
    #4

    @DownPW thanks for the codes. 👍

  • @DownPW thanks for the codes. 👍

    wrote on last edited by
    #5

    If it were me, I would have created snowflake.min.js file and add this code

    /*
     Source: https://github.com/nextapps-de/snowflake
     License: Apache License 2.0
    */
    (function(h,l){function p(){this.x=e(f);this.y=e(-1*g);this.r=.5+e(3);this.a=.3+e(.7);this.c=1+e(3);this.b=.5-e()}function q(){h.requestAnimationFrame(q);c.clearRect(0,0,f,g);for(var b=0;b<m;b++)a=n[b],a.y+=a.c,a.x+=a.b,a.y>g||a.x>f||0>a.x?n[b]=new p:0<a.y&&(c.globalAlpha=a.a,c.beginPath(),c.arc(a.x,a.y,a.r,0,2*Math.PI,!1),c.closePath(),c.fill())}function r(){var b=l.documentElement,a=l.body;f=h.innerWidth||b.clientWidth||a.clientWidth;g=h.innerHeight||b.clientHeight||a.clientHeight;m=f*g/7500>>0;k.width=f;k.height=g;c.fillStyle="#FFF";n=Array(m);for(b=0;b<m;b++)n[b]=new p}function e(a){return Math.random()*(a||1)}function t(a,c,d){a.addEventListener?a.addEventListener(c,d,!1):a.attachEvent("on"+c,d)}var k=l.createElement("canvas"),c=k.getContext("2d"),d=k.style,f,g,m,n,a;d.position="fixed";d.top="0";d.left="0";d.width="100%";d.height="100%";d.zIndex="999999";d.pointerEvents="none";t(h,"load",function(){r();q();l.body.appendChild(k)});t(h,"resize",r)})(window,document);
    

    Then change my html code to point to the Js file I hosted, just to reduce the amount of lookups

  • If it were me, I would have created snowflake.min.js file and add this code

    /*
     Source: https://github.com/nextapps-de/snowflake
     License: Apache License 2.0
    */
    (function(h,l){function p(){this.x=e(f);this.y=e(-1*g);this.r=.5+e(3);this.a=.3+e(.7);this.c=1+e(3);this.b=.5-e()}function q(){h.requestAnimationFrame(q);c.clearRect(0,0,f,g);for(var b=0;b<m;b++)a=n[b],a.y+=a.c,a.x+=a.b,a.y>g||a.x>f||0>a.x?n[b]=new p:0<a.y&&(c.globalAlpha=a.a,c.beginPath(),c.arc(a.x,a.y,a.r,0,2*Math.PI,!1),c.closePath(),c.fill())}function r(){var b=l.documentElement,a=l.body;f=h.innerWidth||b.clientWidth||a.clientWidth;g=h.innerHeight||b.clientHeight||a.clientHeight;m=f*g/7500>>0;k.width=f;k.height=g;c.fillStyle="#FFF";n=Array(m);for(b=0;b<m;b++)n[b]=new p}function e(a){return Math.random()*(a||1)}function t(a,c,d){a.addEventListener?a.addEventListener(c,d,!1):a.attachEvent("on"+c,d)}var k=l.createElement("canvas"),c=k.getContext("2d"),d=k.style,f,g,m,n,a;d.position="fixed";d.top="0";d.left="0";d.width="100%";d.height="100%";d.zIndex="999999";d.pointerEvents="none";t(h,"load",function(){r();q();l.body.appendChild(k)});t(h,"resize",r)})(window,document);
    

    Then change my html code to point to the Js file I hosted, just to reduce the amount of lookups

    wrote on last edited by
    #6

    @Sala ok, but that’s still the same loop which is going to have an impact on the CPU.

  • phenomlab phenomlab has marked this topic as solved on

Did this solution help you?
Did you find the suggested solution useful? Support 💗 Sudonix with a coffee ☕
If your organisation needs deeper expertise around infrastructure, security, or technology leadership, learn more about Phenomlab Ltd. Many of the deeper technical guides behind Sudonix are published there.

Related Topics
  • What’s going on with NodeBB?

    Performance nodebb script die
    20
    8 Votes
    20 Posts
    5k Views
    phenomlab
    @cagatay The most reliable way to upgrade Node.js on Ubuntu depends on how you originally installed it. Method 1: Using NVM (Recommended) If you already use Node Version Manager (NVM), upgrading is simple. NVM allows you to keep both versions and switch between them if needed. Install Node 22: nvm install 22 Switch to Node 22: nvm use 22 Set it as your default: nvm alias default 22 Verify the change: node -v Method 2: Using NodeSource (PPA) If you installed Node.js via apt using the NodeSource repository, you need to update the repository script to point to the new version. Remove the old NodeSource list (optional but cleaner): sudo rm /etc/apt/sources.list.d/nodesource.list Download and run the NodeSource setup script for Node 22: curl -fsSL [https://deb.nodesource.com/setup_22.x](https://deb.nodesource.com/setup_22.x) | sudo -E bash - Install/Upgrade Node.js: sudo apt-get install -y nodejs Verify the installation: node -v Method 3: Using the ‘n’ Package If you have npm installed, you can use the n interactive manager. Clear the npm cache: sudo npm cache clean -f Install the ‘n’ helper: sudo npm install -g n Install Node 22: sudo n 22 Update your shell: hash -r Troubleshooting Permission Denied: If you see permission errors using Method 2 or 3, ensure you are using sudo. Path Issues: If node -v still shows version 20 after upgrading via NVM, restart your terminal or run source ~/.bashrc. Conflicts: Avoid mixing these methods. If you switch from apt to nvm, it is best to sudo apt remove nodejs first to avoid path conflicts.
  • 3 Votes
    1 Posts
    1k Views
    No one has replied
  • TNG + Nodebb

    General tng genealogy nodebb plugin
    4
    0 Votes
    4 Posts
    2k Views
    phenomlab
    @Madchatthew said in TNG + Nodebb: you have to try and use duck tape and super glue to change something to make it do what you want it to do I couldn’t have put that better myself.
  • What plugins are being used here on Sudonix?

    Solved General nodebb plugins development
    6
    5 Votes
    6 Posts
    2k Views
    phenomlab
    @Roki-Antic Welcome! This site isn’t running Persona, but Harmony - a very heavily customised version at that. Do you have a URL where your site is currently located that is publicly accessible? Feel free to PM this info if you do not want to disclose here. Happy to help with any customisation needs.
  • Collapsing blockquotes on Harmony

    General nodebb harmony collapsible quotes
    2
    1
    2 Votes
    2 Posts
    980 Views
    phenomlab
    @dave1904 that’s a really good point actually. I know it was there previously on Persona, but you’re right - no such function exists on harmony. However, putting something in place to mimick the behaviour of Persona won’t be hard from the js standpoint, although I wonder if perhaps we should ask the NodeBB developers is this feature was overlooked?
  • Q&A Plugin Changes NodeBB

    Solved Customisation nodebb q&a plugin
    25
    1
    6 Votes
    25 Posts
    11k Views
    cagatay
    @phenomlab said in Q&A Plugin Changes NodeBB: float: right; left: 10px; } worked thank you
  • Link vs Refresh

    Solved Customisation nodebb blog customization
    20
    2
    8 Votes
    20 Posts
    7k Views
    phenomlab
    @pobojmoks Do you see any errors being reported in the console ? At first guess (without seeing the actual code or the site itself), I’d say that this is AJAX callback related
  • Recent Cards plugin customization

    Solved Customisation nodebb
    21
    1
    13 Votes
    21 Posts
    12k Views
    phenomlab
    @pobojmoks that’s easily done by modifying the code provided here so that it targets background rather than border In essence, the below should work $(document).ready(function() { $(window).on('action:ajaxify.end', function(data) { $('.recent-card-container').each(function(i) { var dataId = $(this).attr("data-cid"); var color = $('[role="presentation"]', this).css("background-color"); console.log("data-cid " + dataId + " is " + color); $('[data-cid="' + dataId + '"] .recent-card').attr("style", "background-color: " + color); }); }); });