Live2D

封装小程序倒计时组件

适用范围:支付宝,淘宝小程序

效果:

 组件目录结构:

详情:
 index.axml

<!-- [{"value":["3","5"],"style":"","isTime":true},{"value":"秒","style":""}] -->
<view class="countdown-main-wrapper">
    <block a:for="{{parsedTime}}">
      <view style="{{item.style}}">
        <block a:if="{{item && item.value && item.value[0]}}">
          <!-- render time, eg. {"value":["3","5"],"style":"","isTime":true} -->
          <block a:if="{{item.isTime}}" >
            <block a:for="{{item.value}}" a:for-item="time" a:for-index="idx">
              <!-- set style for second -->
              <text a:if="{{idx == item.value.length - 1 && index == parsedTime.length - 2}}" style="{{secondStyle || timeStyle}}">{{time}}</text>
              <text a:else style="{{timeStyle}}">{{time}}</text>
            </block>
          </block>
          <!-- render text, eg, {"value":"秒","style":""} -->
          <text a:else style="{{textStyle}}" class="rax-countdown-main-wrapper-colon">{{item.value[0]}}</text>
        </block>
      </view>
    </block>
</view>

index.acss

.countdown-main-wrapper {
  display: flex;
  flex-direction: row;
  align-items: center;
}

.countdown-main-wrapper view:nth-child(2n-1)::after{ //冒号样式
  display:flex;
  justify-content: center;
  align-items: center;
  content:':';
  color:#3A3A3A;
  font-size:16rpx;
  font-family: PingFangSC-Medium;
  margin-top: -2rpx;
}

.countdown-main-wrapper view:nth-child(2n){ // 数字样式
  font-size:16rpx;
  color:#3A3A3A;
  font-family: PingFangSC-Medium;
  border-radius:3rpx;
  padding:0;
  background-color: transparent;
}

.countdown-main-wrapper view:nth-child(1)::after{
  content: '';
}

.countdown-main-wrapper view:last-child::after{
  content: '';
}

index.js

"use strict";

var _utils = require("./utils");

Component({
  data: {
    count: 0
  },
  props: {
    timeRemaining: 0,
    interval: 1000,
    timeWrapStyle: '',
    textStyle: '',
    timeStyle: '',
    secondStyle: '',
    tpl: '{d}天{h}时{m}分{s}秒',
    onFormatFunc: null,
    onTick: null,
    onComplete: null
  },
  onInit: function () {
    this.setTimes();
  },
  didUnmount: function () {
    if (this.counter) clearInterval(this.counter);
  },
  methods: {
    setTimes() {
      var _this = this;
      var funcToExecute = this.props.onFormatFunc && typeof this.props.onFormatFunc === 'function' ? this.props.onFormatFunc : this.msToTime;
      this.funcToExecute = funcToExecute.bind(this);
      this.counter = setInterval(function () {
        _this.funcToExecute();
      }, this.props.interval);
    },
    msToTime: function msToTime() {
      var _this2 = this;

      var count = this.data.count;
      var timeDuration = (this.data.leftTime || this.props.timeRemaining) - count * this.props.interval;
      this.setData({
        count: count + 1
      });

      if (!timeDuration || timeDuration <= 0) {
        if (this.counter) clearInterval(this.counter);
      } // parameter type of `parseInt` is 'string', so need to convert time to string first.

      let days = parseInt((timeDuration / (1000 * 60 * 60 * 24)).toString());

      const oneSeconds = 1000;
      const oneMinutes = oneSeconds * 60;
      const oneHours = oneMinutes * 60;

      // 计算相差小时数
      let hours = Math.floor(timeDuration / oneHours);
      // 计算相差分钟数
      let minutes = Math.floor((timeDuration % oneHours) / oneMinutes);
      // 计算相差秒数
      let seconds = Math.floor((timeDuration % oneMinutes) / oneSeconds);

      var timeType = {
        'd': days < 10 ? '0' + days : days + '',
        'h': hours < 10 ? '0' + hours : hours + '',
        'm': minutes < 10 ? '0' + minutes : minutes + '',
        's': seconds < 10 ? '0' + seconds : seconds + ''
      }; // format time

      var tpl = this.props.tpl || _utils.DEFAULT_TPL;
      var rule = new RegExp('\{[d,h,m,s]\}', 'g'); // used to matched all template item, which includes 'd', 'h', 'm' and 's'.

      var matchlist = [];
      var tmp = null;
      var _this$props = this.props,
        textStyle = _this$props.textStyle,
        timeWrapStyle = _this$props.timeWrapStyle;

      while ((tmp = rule.exec(tpl)) !== null) {
        matchlist.push(tmp.index, tmp.index);
      }

      if (matchlist.length !== 0) {
        // used to detect the last element
        matchlist.push(-1);
      }

      var lastPlaintextIndex = 0;
      var parsedTime = matchlist.map(function (val, index) {
        if (val === -1) {
          // don't forget the potential plain text after last matched item
          var lastPlaintext = tpl.slice(lastPlaintextIndex);
          return {
            value: lastPlaintext,
            style: textStyle
          };
        }

        var matchedCharacter = tpl[val + 1];

        switch (matchedCharacter) {
          case 'd':
          case 'h':
          case 'm':
          case 's':
            if (index % 2 === 0) {
              // insert plain text before current matched item
              return {
                value: tpl.slice(lastPlaintextIndex, val),
                style: textStyle
              };
            } else {
              // replace current matched item to realtime string
              lastPlaintextIndex = val + 3;
              return {
                value: _this2.splitTime(timeType[matchedCharacter]),
                style: timeWrapStyle,
                isTime: true
              };
            }

          default:
            return null;
        }
      });
      parsedTime = parsedTime.filter(function (item) {
        return item;
      }); // check if the onTick function needs to be called

      var callOnTick = this.props.onTick && typeof this.props.onTick === 'function';
      this.setData({
        parsedTime: parsedTime
      }, callOnTick ? this.props.onTick : null); // check if onComplete function needs to be called
      if (timeDuration <= 0 && this.props.onComplete && typeof this.props.onComplete === 'function') {
        this.props.onComplete();
      }
    },
    splitTime: function splitTime(time) {
      if (time === void 0) {
        time = '00';
      }

      return time.split('');
    }
  }
});

index.json

{
    "component": true
}

utils.js

"use strict";

exports.__esModule = true;
exports.DEFAULT_TPL = void 0;
var DEFAULT_TPL = '{d}天{h}时{m}分{s}秒';
exports.DEFAULT_TPL = DEFAULT_TPL;

 

用法:

 <count-down timeRemaining="{{123456}}"   tpl='{h}{m}{s}' />

 

 

posted @ 2023-04-20 19:00  喻佳文  阅读(85)  评论(0编辑  收藏  举报