เอฟเฟคตัวเลขวิ่ง ด้วย JavaScript

วันก่อนช่วยทีมงานไทยรอดทำเว็บข้อมูลกล่องยังชีพและรับบริจาค ที่ www.thairod.care ซึ่งทำด้วย WB Small ที่เป็นเว็บสำเร็จรูปของเรา มีส่วนหนึ่งเป็นเอฟเฟคตัวเลขวิ่ง หรือที่ฝรั่งเรียกว่า Coutup / CouterUp ซึ่งใช้ JavaScript จาก CountUp.js

แต่ว่าตัวเลขจะรันทันทีที่โหลดหน้าเว็บเสร็จ ซึ่งผมคิดว่าน่าจะต้องปรับอีกนิด สั่งให้เริ่มวิ่งเมื่อ scroll หน้าจอมาถึงจะดีกว่า

โค้ดตรวจสอบว่าชิ้นส่วนมาแสดงในจอหรือยัง

เว็บ Go Make Things (คอร์สเรียนดีมาก) เค้าอธิบายและมีตัวอย่างพร้อมใช้ให้ ที่

ส่วนตัวอย่างโค้ดพร้อมใช้ ที่

อ่านค่าจาก HTML มาใช้ จะได้แก้ตัวเลขง่ายๆ

โค้ด CountUp.js นั้นให้เราระบุเลขไปในโค้ด JavaScript เลย ซึ่งถ้านำไปอัปเดตผ่านเว็บ จะยุ่งยากไปหน่อย เว็บจริงผมใช้ ACF ช่วยสร้างฟีลด์ให้ทีมงานอัปเดตง่าย แต่โค้ดตัวอย่าง ขอเป็นแค่ HTML ละกันนะครับ

ผมฝาก data ไว้ที่ data-value ด้วยโค้ด HTML ดังนี้

<b id="c1" class="s-counter" data-value="1000">1,000</b>

และเข้าถึงด้วยคำสั่ง JS

dataset.value

(HTML ต้องระบุ ID เพราะ countup.js ต้องใช้ ID เรียก ส่วนคลาส ผมตั้งเป็น s-counter ไว้ หากต้องการเปลี่ยนก็ทำได้)

ดูตัวอย่างด้วย CodePen

โค้ดนี้ ผมสั่งให้โหลด JS จากลิงก์ https://cdnjs.cloudflare.com/ajax/libs/countup.js/2.0.8/countUp.umd.min.js แล้วเขียนโค้ด JS เพิ่มอีกนิดหน่อย ลองคลิกแล้ว Scroll ดูได้ครับ เนื้อหาล่างๆ เมื่อเริ่มแสดง ตัวเลขก็จะวิ่งทันที และเขียนเพิ่มอีกนิดว่า หากเลขนั้นๆ วิ่งแล้ว ก็ไม่ต้องวิ่งใหม่แล้ว (ด้วยตัวแปร done[] )

See the Pen CountUp on Scroll by Seed Webs (@seedwebs) on CodePen.

ถ้าอยากรวมเป็น JS ชุดเดียวกัน

เว็บไทยรอดลงปลั๊กอิน WPCodeBox ไว้ ก็เพิ่ม JS ไป แต่จริงๆ ถ้าไม่ใช้ปลั๊กอิน จะสร้างด้วย HTML Block แล้วใส่ JS ไปตามนี้ก็ได้เช่นกัน

โค้ดทั้งหมด

!function(t,i){"object"==typeof exports&&"undefined"!=typeof module?i(exports):"function"==typeof define&&define.amd?define(["exports"],i):i((t="undefined"!=typeof globalThis?globalThis:t||self).countUp={})}(this,function(t){"use strict";var s=function(){return(s=Object.assign||function(t){for(var i,a=1,s=arguments.length;a<s;a++)for(var n in i=arguments[a])Object.prototype.hasOwnProperty.call(i,n)&&(t[n]=i[n]);return t}).apply(this,arguments)},i=(a.prototype.determineDirectionAndSmartEasing=function(){var t=this.finalEndVal||this.endVal;this.countDown=this.startVal>t;var i=t-this.startVal;Math.abs(i)>this.options.smartEasingThreshold?(this.finalEndVal=t,i=this.countDown?1:-1,this.endVal=t+i*this.options.smartEasingAmount,this.duration=this.duration/2):(this.endVal=t,this.finalEndVal=null),this.finalEndVal?this.useEasing=!1:this.useEasing=this.options.useEasing},a.prototype.start=function(t){this.error||(this.callback=t,0<this.duration?(this.determineDirectionAndSmartEasing(),this.paused=!1,this.rAF=requestAnimationFrame(this.count)):this.printValue(this.endVal))},a.prototype.pauseResume=function(){this.paused?(this.startTime=null,this.duration=this.remaining,this.startVal=this.frameVal,this.determineDirectionAndSmartEasing(),this.rAF=requestAnimationFrame(this.count)):cancelAnimationFrame(this.rAF),this.paused=!this.paused},a.prototype.reset=function(){cancelAnimationFrame(this.rAF),this.paused=!0,this.resetDuration(),this.startVal=this.validateValue(this.options.startVal),this.frameVal=this.startVal,this.printValue(this.startVal)},a.prototype.update=function(t){cancelAnimationFrame(this.rAF),this.startTime=null,this.endVal=this.validateValue(t),this.endVal!==this.frameVal&&(this.startVal=this.frameVal,this.finalEndVal||this.resetDuration(),this.finalEndVal=null,this.determineDirectionAndSmartEasing(),this.rAF=requestAnimationFrame(this.count))},a.prototype.printValue=function(t){t=this.formattingFn(t);"INPUT"===this.el.tagName?this.el.value=t:"text"===this.el.tagName||"tspan"===this.el.tagName?this.el.textContent=t:this.el.innerHTML=t},a.prototype.ensureNumber=function(t){return"number"==typeof t&&!isNaN(t)},a.prototype.validateValue=function(t){var i=Number(t);return this.ensureNumber(i)?i:(this.error="[CountUp] invalid start or end value: "+t,null)},a.prototype.resetDuration=function(){this.startTime=null,this.duration=1e3*Number(this.options.duration),this.remaining=this.duration},a);function a(t,i,a){var r=this;this.target=t,this.endVal=i,this.options=a,this.version="2.0.8",this.defaults={startVal:0,decimalPlaces:0,duration:2,useEasing:!0,useGrouping:!0,smartEasingThreshold:999,smartEasingAmount:333,separator:",",decimal:".",prefix:"",suffix:""},this.finalEndVal=null,this.useEasing=!0,this.countDown=!1,this.error="",this.startVal=0,this.paused=!0,this.count=function(t){r.startTime||(r.startTime=t);t-=r.startTime;r.remaining=r.duration-t,r.useEasing?r.countDown?r.frameVal=r.startVal-r.easingFn(t,0,r.startVal-r.endVal,r.duration):r.frameVal=r.easingFn(t,r.startVal,r.endVal-r.startVal,r.duration):r.countDown?r.frameVal=r.startVal-(r.startVal-r.endVal)*(t/r.duration):r.frameVal=r.startVal+(r.endVal-r.startVal)*(t/r.duration),r.countDown?r.frameVal=r.frameVal<r.endVal?r.endVal:r.frameVal:r.frameVal=r.frameVal>r.endVal?r.endVal:r.frameVal,r.frameVal=Number(r.frameVal.toFixed(r.options.decimalPlaces)),r.printValue(r.frameVal),t<r.duration?r.rAF=requestAnimationFrame(r.count):null!==r.finalEndVal?r.update(r.finalEndVal):r.callback&&r.callback()},this.formatNumber=function(t){var i=t<0?"-":"",t=Math.abs(t).toFixed(r.options.decimalPlaces),t=(t+="").split("."),a=t[0],t=1<t.length?r.options.decimal+t[1]:"";if(r.options.useGrouping){for(var s="",n=0,e=a.length;n<e;++n)0!==n&&n%3==0&&(s=r.options.separator+s),s=a[e-n-1]+s;a=s}return r.options.numerals&&r.options.numerals.length&&(a=a.replace(/[0-9]/g,function(t){return r.options.numerals[+t]}),t=t.replace(/[0-9]/g,function(t){return r.options.numerals[+t]})),i+r.options.prefix+a+t+r.options.suffix},this.easeOutExpo=function(t,i,a,s){return a*(1-Math.pow(2,-10*t/s))*1024/1023+i},this.options=s(s({},this.defaults),a),this.formattingFn=this.options.formattingFn||this.formatNumber,this.easingFn=this.options.easingFn||this.easeOutExpo,this.startVal=this.validateValue(this.options.startVal),this.frameVal=this.startVal,this.endVal=this.validateValue(i),this.options.decimalPlaces=Math.max(this.options.decimalPlaces),this.resetDuration(),this.options.separator=String(this.options.separator),this.useEasing=this.options.useEasing,""===this.options.separator&&(this.options.useGrouping=!1),this.el="string"==typeof t?document.getElementById(t):t,this.el?this.printValue(this.startVal):this.error="[CountUp] target is null or undefined"}t.CountUp=i,Object.defineProperty(t,"__esModule",{value:!0})});


let done = [];

function isComing(el) {
  const rect = el.getBoundingClientRect();
  return (
    rect.top <= (window.innerHeight || document.documentElement.clientHeight)
  );
}

function s_counters() {
  const s_counters = document.querySelectorAll(".s-counter");
  s_counters.forEach(function (cntr) {
    if (isComing(cntr)) {
      var cntr_id = cntr.id;
      if (!done[cntr_id]) {
        var cntr_val = cntr.dataset.value;
        var cntr_run = new countUp.CountUp(cntr_id, cntr_val);
        cntr_run.start();
        done[cntr_id] = true;
      }
    }
  });
}

document.addEventListener("DOMContentLoaded", s_counters);
window.addEventListener("scroll", s_counters, { passive: true });

สร้าง HTML ตามตัวอย่าง แล้วนำโค้ด JS ใส่ ก็จะเห็นว่าตัวเลขเริ่มวิ่งได้ละครับ

ตัวอย่างเว็บไทยรอด

ดูตัวอย่าง www.thairod.care หรือคลิกบริจาคได้เลยนะคร้าบ 😀

Subscribe
Notify of
0 Comments
Inline Feedbacks
View all comments