ストップウォッチを作ってみる[Aura]

概要

Auraでストップウォッチを作成します。
スタートの時間とストップの時間の差分を計算します。
ミリ秒単位で計測します。

ソースコード

StopwatchAura.cmp

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId" access="global" >
    <aura:attribute name="startTime" type="Integer" default="0"/>
    <aura:attribute name="timeToAdd" type="Integer" default="0"/>
    <aura:attribute name="measuringTime" type="Integer" default="0"/>
    <aura:attribute name="timerId" type="String"/>
    <aura:attribute name="disableStartButton" type="Boolean" default="false"/>
    <aura:attribute name="disableStopButton" type="Boolean" default="true"/>
    
    <lightning:card>
        <div class="slds-grid slds-einstein-header slds-card__header">
            <header class="slds-media slds-media_center slds-has-flexi-truncate">
                <div class="slds-grid slds-grid_vertical-align-center slds-size_3-of-4 slds-medium-size_2-of-3">
                    <h1 class="slds-truncate" title="ストップウォッチAura">
                        <span class="slds-text-heading_large">ストップウォッチAura</span>
                    </h1>
                </div>
                <div class="slds-einstein-header__figure slds-size_1-of-4 slds-medium-size_1-of-3"></div>
            </header>
        </div>
        <div class="slds-align_absolute-center">
            <div class="slds-m-top_large">
            <header class="slds-col slds-size_1-of-1 slds-align_absolute-center" >
                <div aura:id="curentTime" class="slds-text-heading_large">00:00:000</div>
            </header>
            <div class="slds-align_absolute-center">
                <div class="slds-button-group slds-m-vertical_medium" role="group">
                    <lightning:button variant="neutral" label="スタート" onclick="{!c.startApp}" class="slds-text-heading_medium slds-p-around_small" disabled="{!v.disableStartButton}"></lightning:button>
                    <lightning:button variant="neutral" label="ストップ" onclick="{!c.startApp}" class="slds-text-heading_medium slds-p-around_small" disabled="{!v.disableStopButton}"></lightning:button>
                    <lightning:button variant="neutral" label="リセット" onclick="{!c.startApp}" class="slds-button_text-destructive slds-text-heading_medium slds-p-around_small"></lightning:button>
                </div>
            </div>
            </div>
        </div>
    </lightning:card>
</aura:component>

StopwatchAuraController.js

({    
    // 押されたボタンを判定する
    startApp : function(component, event, helper) {
      const clickedButtonlabel = event.getSource().get("v.label");
      if(clickedButtonlabel === 'スタート') {
          // 計測開始 
          helper.startTimmer(component);
      } else if(clickedButtonlabel === 'ストップ') {
          // 計測終了
          helper.stopTimmer(component);
      } else {
          // 計測リセット
          helper.resetTimmer(component);
      }
    }
})

StopwatchAuraHelper.js

({
    // 計測開始
    startTimmer : function(component, event) {
        component.set("v.disableStartButton", true);       
        component.set("v.disableStopButton", false);
        component.set("v.startTime", Date.now());
        // 10ミリ秒毎に計測する
        this.countUp(component);
    },
    
    // 計測終了
    stopTimmer : function(component, event) {
        component.set("v.disableStartButton", false);       
        component.set("v.disableStopButton", true);
        clearTimeout(component.get("v.timerId"));
        let timeToAdd = component.get("v.timeToAdd");
        const startTime = component.get("v.startTime");
        timeToAdd += Date.now() - startTime; // 経過時間を記録
        component.set("v.timeToAdd", timeToAdd);
    },

    // 計測リセット
    resetTimmer : function(component) {
        component.set("v.disableStartButton", false);       
        component.set("v.disableStopButton", true);
        clearTimeout(component.get("v.timerId"));

        component.set("v.timeToAdd", 0);
        component.set("v.measuringTime", 0);
        // 計測時間を分に変換する
        this.convertTime(component);
    },
    
    // 計測時間を分に変換する    
    convertTime : function(component) {
        const measuringTime = component.get("v.measuringTime");
        let min = Math.floor(measuringTime / 60000); // 分
        let sec = Math.floor(measuringTime % 60000 / 1000); // 秒
        let ms = measuringTime % 1000; // ミリ秒
        
        // 桁数を固定
        min = ('0' + min).slice(-2); 
        sec = ('0' + sec).slice(-2);
        ms = ('00' + ms).slice(-3);
        
        // 計測時間を表示
        const curentTimeText = component.find('curentTime').getElement();
        curentTimeText.textContent = min + ':' + sec + ':' + ms;
    },
    
    // 10ミリ秒毎に計測する
    countUp : function(component) {
        const timerId = setTimeout(function(){
            const startTime = component.get("v.startTime");
            const timeToAdd = component.get("v.timeToAdd");
            let measuringTime = component.get("v.measuringTime");
            measuringTime = Date.now() - startTime + timeToAdd; // 経過時間を記録
            component.set("v.measuringTime", measuringTime);
            
            // 計測時間を分に変換する   
            this.convertTime(component);
                        
            // 1秒毎に計測する
            this.countUp(component);
        }.bind(this),10);
        component.set("v.timerId", timerId);
    }
})