Butterfly主题v3.4.0及其以后版本基本已经实现完全去jquery化,而本帖有使用到jquery,不想再次引入js的可以考虑使用站内的原生JS计时器

页脚翻页时钟计时

  1. 参考内容:jquery.flipcountdown翻页定时器倒计时插件支持时分秒倒计时时间表
  2. 改动范围:添加pjax重载,修复计算时间逻辑,避免出现负数的尴尬。

  3. 可以直接下载教程涉及的静态资源,按指示添加到相应目录。
  4. 虽然说是页脚计时器,但不一定非要放在页脚。位置取决于便签注入的位置。而且也不局限于博客,理论上任何静态页面都适用。
  5. 由于本教程的页脚计时器依赖于jquery,与Metro4框架有所冲突,所以不建议在使用了这个框架的页面上(例如本人的主页,说多了都是泪)使用。

修改步骤

  1. [Blogroot]\_config.butterfly.ymlfooter配置项添加时间栏,如果已经有在custom_text写入过内容的,可以在合适的位置插入span标签。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
        footer:
    owner:
    enable: true
    since: 2016
    - custom_text:
    + custom_text: <span id="runtime"></span>
    copyright: false # Copyright of theme and framework
    ICP: # Chinese ICP License
    enable: false
    url:
    text:
    icon: /img/icp.png
  2. [Blogroot]\themes\butterfly\source\css\目录下新建flipcountdown.css

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    .xdsoft_flipcountdown{display:inline-block;}

    .xdsoft_flipcountdown .xdsoft_digit{float:left;background-repeat:no-repeat;}
    .xdsoft_flipcountdown .xdsoft_clearex{clear:both;float:none;}


    .xdsoft_flipcountdown .xdsoft_digit{
    background-position:0px 0px;
    }
    .xdsoft_flipcountdown .xdsoft_digit.xdsoft_separator,.xdsoft_flipcountdown .xdsoft_digit.xdsoft_dot{
    opacity:0.9;
    }
    .xdsoft_flipcountdown.xdsoft_size_lg .xdsoft_digit{
    width:53px;
    height:76px;
    background-image:url(/img/digit-lg.png);
    }
    .xdsoft_flipcountdown.xdsoft_size_lg .xdsoft_digit.xdsoft_space,
    .xdsoft_flipcountdown.xdsoft_size_lg .xdsoft_digit.xdsoft_separator,
    .xdsoft_flipcountdown.xdsoft_size_lg .xdsoft_digit.xdsoft_dot{
    width:14px;
    background-position:-19px -4620px;
    }
    .xdsoft_flipcountdown.xdsoft_size_lg .xdsoft_digit.xdsoft_dot{
    background-position:-41px -4620px;
    }
    .xdsoft_flipcountdown.xdsoft_size_lg .xdsoft_digit.xdsoft_space{
    background-position:-100px -4620px;
    }

    .xdsoft_flipcountdown.xdsoft_size_md .xdsoft_digit{
    width:36px;
    height:51px;
    background-image:url(/img/digit-md.png);
    }
    .xdsoft_flipcountdown.xdsoft_size_md .xdsoft_digit.xdsoft_space,
    .xdsoft_flipcountdown.xdsoft_size_md .xdsoft_digit.xdsoft_separator,
    .xdsoft_flipcountdown.xdsoft_size_md .xdsoft_digit.xdsoft_dot{
    width:10px;
    background-position:-13px -3120px;
    }
    .xdsoft_flipcountdown.xdsoft_size_sm .xdsoft_digit{
    width:24px;
    height:34px;
    background-image:url(/img/digit-sm.png);
    }
    .xdsoft_flipcountdown.xdsoft_size_sm .xdsoft_digit.xdsoft_space,
    .xdsoft_flipcountdown.xdsoft_size_sm .xdsoft_digit.xdsoft_separator,
    .xdsoft_flipcountdown.xdsoft_size_sm .xdsoft_digit.xdsoft_dot{
    width:10px;
    background-position:-6px -2100px;
    }
    .xdsoft_flipcountdown.xdsoft_size_xs .xdsoft_digit{
    width:16px;
    height:23px;
    background-image:url(/img/digit-xs.png);
    }
    .xdsoft_flipcountdown.xdsoft_size_xs .xdsoft_digit.xdsoft_space,
    .xdsoft_flipcountdown.xdsoft_size_xs .xdsoft_digit.xdsoft_separator,
    .xdsoft_flipcountdown.xdsoft_size_xs .xdsoft_digit.xdsoft_dot{
    width:5px;
    background-position:-5px -1440px;
    }
  3. [Blogroot]\themes\butterfly\source\js\目录下新建flipcountdown.jsruntime.js

    • flipcountdown.js

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
      100
      101
      102
      103
      104
      105
      106
      107
      108
      109
      110
      111
      112
      113
      114
      115
      116
      117
      118
      119
      120
      121
      122
      123
      124
      125
      126
      127
      128
      129
      130
      131
      132
      133
      134
      135
      136
      137
      138
      139
      140
      141
      142
      143
      144
      145
      146
      147
      148
      149
      150
      151
      152
      153
      154
      155
      156
      157
      158
      159
      160
      161
      162
      163
      164
      165
      166
      167
      168
      169
      170
      171
      172
      173
      174
      175
      176
      177
      178
      179
      180
      181
      182
      183
      184
      185
      186
      187
      188
      189
      190
      /**
      * @preserve jQuery flipcountdown plugin v3.0.4
      * @homepage http://xdsoft.net/jqplugins/flipcountdown/
      * (c) 2013, Chupurnov Valeriy.
      */
      (function($){
      jQuery.fn.flipCountDown = jQuery.fn.flipcountdown = function( _options ){
      var default_options = {
      showHour :true,
      showMinute :true,
      showSecond :true,
      am :false,

      tzoneOffset :0,
      speedFlip :60,
      period :1000,
      tick :function(){
      return new Date();
      },
      autoUpdate :true,
      size :'md'
      },

      sizes = {
      lg:77,
      md:52,
      sm:35,
      xs:24
      },

      createFlipCountDown = function( $box ){
      var $flipcountdown = $('<div class="xdsoft_flipcountdown"></div>'),
      $clearex = $('<div class="xdsoft_clearex"></div>'),

      options = $.extend({},default_options),

      timer = 0,

      _animateRange = function( box,a,b ){
      _animateOne( box,a,(a>b&&!(a==9&&b==0))?-1:1,!(a==9&&b==0)?Math.abs(a-b):1 );
      },

      _animateOne = function( box,a,arrow,range ){
      if( range<1 )
      return;

      _setMargin(box,-(a*6*sizes[options.size]+1),1,arrow,function(){
      _animateOne(box,a+arrow,arrow,range-1);
      },range);
      },

      _setMargin = function( box, marginTop, rec, arrow,callback,range){
      if( marginTop<=-sizes[options.size]*60 )
      marginTop = -1;
      box.css('background-position','0px '+marginTop+'px' );
      if( rec<=6 ){
      setTimeout(function(){
      _setMargin(box, marginTop-arrow*sizes[options.size], ++rec, arrow, callback,range);
      },parseInt(options.speedFlip/range));
      }else
      callback();
      },

      blocks = [],

      _typeCompare = function ( a,b ){
      return a&&b&&(
      (a==b)||
      (/^[0-9]+$/.test(a+''+b))||
      (/^[:.\s]+$/.test(a+''+b))
      );
      },

      _generate = function( chars ){
      if( !(chars instanceof Array) || !chars.length )
      return false;
      for( var i = 0, n = chars.length;i<n;i++ ){
      if( !blocks[i] ){
      blocks[i] = $('<div class="xdsoft_digit"></div>');
      $clearex.before(blocks[i]);
      }
      if( blocks[i].data('value')!=chars[i] ){
      if( !_typeCompare(blocks[i].data('value'),chars[i]) ){
      blocks[i]
      .removeClass('xdsoft_separator')
      .removeClass('xdsoft_dot');
      switch( chars[i] ){
      case ':':blocks[i].addClass('xdsoft_separator');break;
      case '.':blocks[i].addClass('xdsoft_dot');break;
      case ' ':blocks[i].addClass('xdsoft_space');break;
      }
      }
      if( !isNaN(chars[i]) ){
      var old = parseInt(blocks[i].data('value')),
      ii = parseInt(blocks[i].data('i')),
      crnt = parseInt(chars[i]);
      if( isNaN(old)||i!=ii ){
      old = (crnt-1)<0?9:crnt-1;
      }
      _animateRange(blocks[i],old,crnt);
      }
      blocks[i].data('value',chars[i]);
      blocks[i].data('i',i);
      }
      }
      if( blocks.length>chars.length ){
      for(;i<blocks.length;i++ ){
      blocks[i][0].parentNode.removeChild(blocks[i][0]);
      delete blocks[i];
      }
      blocks.splice(chars.length);
      }

      },

      counter = 0,

      _calcMoment = function(){
      var value = '1',chars = [];
      if(options.tick)
      value = (options.tick instanceof Function)?options.tick.call($box,counter):options.tick;

      if( typeof value!=='undefined' ){
      switch( value.constructor ){
      case Date:
      var h = (value.getHours()+options.tzoneOffset)%(options.am?12:24);

      if( options.showHour ){
      chars.push(parseInt(h/10));
      chars.push(h%10);
      }

      if( options.showHour && (options.showMinute || options.showSecond) )
      chars.push(':');

      if( options.showMinute ){
      chars.push(parseInt(value.getMinutes()/10));
      chars.push(value.getMinutes() % 10);
      }

      if( options.showMinute && options.showSecond )
      chars.push(':');

      if( options.showSecond ){
      chars.push(parseInt(value.getSeconds()/10));
      chars.push(value.getSeconds() % 10);
      }
      break;
      case String:
      chars = value.replace(/[^0-9\:\.\s]/g,'').split('');
      break;
      case Number:
      chars = value.toString().split('');
      break;
      }
      _generate(chars);
      }
      };

      $flipcountdown
      .append($clearex)
      .on('xdinit.xdsoft',function(){
      clearInterval(timer);
      if( options.autoUpdate )
      timer = setInterval( _calcMoment,options.period );
      _calcMoment();
      });

      $box.data('setOptions',function( _options ){
      options = $.extend({},options,_options);
      if( !sizes[options.size] )
      options.size = 'lg';
      $flipcountdown
      .addClass('xdsoft_size_'+options.size)
      .trigger('xdinit.xdsoft');
      });
      $box.append($flipcountdown);
      };
      return this.each(function(){
      var $box = $(this);
      if( !$box.data('setOptions') ){
      $box.addClass('xdsoft')
      createFlipCountDown($box);
      }
      $box.data('setOptions')&&
      $.isFunction($box.data('setOptions'))&&
      $box.data('setOptions')(_options);
      });
      }
      })(jQuery);
    • runtime.js

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      $(function(){
      var NY = Math.round((new Date('4/17/2019 00:00:00')).getTime()/1000); //Date修改为你的建站时间。
      $('#runtime').flipcountdown({
      size:"xs",//可以自定义翻页计时器大小。从大到小依次是lg、md、sm、xs。
      tick:function(){
      var nol = function(h){
      return h>9?h:'0'+h;
      }
      var range = Math.abs(Math.round((new Date()).getTime()/1000)-NY),
      secday = 86400, sechour = 3600,
      days = parseInt(range/secday),
      hours = parseInt((range%secday)/sechour),
      min = parseInt(((range%secday)%sechour)/60),
      sec = ((range%secday)%sechour)%60;
      return nol(days)+' '+nol(hours)+' '+nol(min)+' '+nol(sec);
      }
      });
      });
  4. 将下载的翻页时钟图片添加到[Blogroot]\themes\butterfly\source\img\目录下。

  5. [Blogroot]\_config.butterfly.ymlinject引入文件。

    • 其中jquery为依赖。最新版butterfly主题的CDN中自带,无需添加。
    • runtime.js依赖于flipcountdown.js,所以flipcountdown.js必须在runtime.js之前引入。
    • data-pjax属性为butterfly的pjax.pug中自带的重载函数。由于这里起重载作用的关键类只有runtime.js,其他都是依赖项,所以只要给runtime.js添加data-pjax属性即可。
    1
    2
    3
    4
    5
    6
    7
        inject:
    head:
    + - <link rel="stylesheet" href="/css/flipcountdown.css">
    bottom:
    + - <script src="https://npm.elemecdn.com/jquery@latest/dist/jquery.min.js"></script>
    + - <script src="/js/flipcountdown.js"></script>
    + - <script data-pjax src="/js/runtime.js"></script>