中瑞 發表於 2022-10-20 17:32:00

前端开发日常——CSS动画无限轮播

<p>  近来没有什么值得写的东西,空闲的时候帮前端的同学做了些大屏上的展示模块,就放在这里写写吧,手把手“需求-&gt;设计-&gt; 实现”,受众偏新手向。</p>
<p>  <img src="https://img2022.cnblogs.com/blog/2753310/202210/2753310-20221020150358127-489119677.gif"></p>
<p>  为了直观便于理解, 直接把结果贴在上面。</p>
<p>  如上所示,<strong>基本需求比较简单明了, “分页显示供应商、供应占比列表,自动轮播”。</strong></p>
<p>&nbsp;</p>
<p><strong>  一、需求评审</strong></p>
<p><strong>  </strong>该有的环节还是要有,<strong>尽管需求简单,评审不能省略,无论形式。</strong>开发的同学千万不要真的相信需求就这么简单,否则南辕北辙,出力不讨好,那必定是日常-_-||。</p>
<p>  于是有丰富填坑经验的开发同学,对于这个<strong>简单的</strong>模块需求,可能会提出如下的一些问题</p>
<p>  1. 如果只有一页,要不要轮播?</p>
<p>  2.每页的轮播间隔频率是多少?</p>
<p>  3.如果列表没有数据,如何显示这个模块?</p>
<p>  4.数据的刷新时机?是翻页刷新,轮播一圈刷新,还是其他?</p>
<p>  5.这个绿色的比值是什么含义? 是不是还有红色?</p>
<p>  6.百分比的小数位?</p>
<p>  7.如果接口异常比如网络不通,如何表示这种异常?</p>
<p>  8.供应商的名字会不会有500字那么长? 放不下如何布局?</p>
<p>  ……等等</p>
<p>  以上任何一个未明确的需求,都可能成为你编码完成后的一个bug或优化建议。 o(* ̄︶ ̄*)o。</p>
<p>&nbsp;</p>
<p><strong>  二、设计评审</strong>  </p>
<p>  关于上面待确认的每一个问题,我们伟大的产品经理都一一耐心的给出了“<strong>令人信服的”</strong>回答后。还是不能马上开始编码。下面我们需要进行一些技术方案的设计讨论,由技术leader把关。例如:</p>
<p>  1. 数据流,这个列表的数据,是从数据库中的哪几个表取出的? 确认下查询逻辑。</p>
<p>  2.接口设计,是一次返回前端所有数据,还是支持分页查询。</p>
<p>  3.性能考虑,查询频率是不是较高,并发是不是大,缺不缺索引,要不要上缓存?</p>
<p>  4.轮播如何实现? 有没有已经集成的轮播控件,是否满足要求,还是需要自己写一个。</p>
<p>  5.如何进行模块化开发,作为一个模块集成嵌入到整体页面中。</p>
<p>  ……等等</p>
<p>  明确了以上的问题后,作为前端同学的我,是不是可以开始撸代码了?</p>
<p>   </p>
<p><strong>  三、想清楚再写</strong></p>
<p>  说到这里,</p>
<p>  一类同学已经开始着手编码了, 第一个想到需要写的方法可能是,ajax 去后台请求数据列表的接口。</p>
<p>  另一类同学,可能仍在构思,如何组织代码,提炼主要的数据结构和功能方法。</p>
<p>  这里我们显然应该向“另外一类”同学学习。<strong>想清楚再写,是一个毫无疑问的好习惯</strong>。</p>
<p>  <strong>技术预研</strong></p>
<p><strong>  </strong>实现一个功能,首先要扫除其中的未知技术点,扫除了所有未知之后,才能够优化的组织实现方案<strong>。</strong></p>
<p><strong>  </strong>上面的需求对于我这种半吊子前端来说,比较关键的两个技术问题是。</p>
<p> <strong> 1)用什么方案来实现滑动动画。 2)如何实现“无限滚动”。</strong></p>
<p>&nbsp;</p>
<p>  <strong>滑动动画</strong>——经过一番百度,总结下动画可能的实现方案,包括用JS实现或者用CSS实现。 各有优劣,js 兼容性好,控制灵活;CSS性能高,平滑流畅。因为我们的动画非常线性,简单,于是这里我们决定采用CSS动画作为动画的实现方案。</p>
<p>  通过简单的研究,我们已经弄清楚了, 想让一个页面元素具有一个动画效果,可以通过向他添加一个包含了动画关键真的选择器来实现,比如定义一个滑出动画类,把这个css类加到元素上,元素就可以实现滑出的动画效果。</p>
<p>&nbsp;</p>
<p>  <strong>无限滚动</strong>——思考下滚动页面,虽然对于数据来说可能会分成很多页,但对于屏幕展示来说,实际上最多同时出现两个页面,一个是前一页,一个是当前页。在不滚动的时候只有当前页需要显示。</p>
<p>  顺着这个思路, 滚动这个动作对应,“当前页飞入”“前一页飞出”这两个细分动作,特别的情况是,初始显示时,是没有“前一页”的。</p>
<p>  那么滚动这个动作大概思路就是,</p>
<p>  1. 根据当前页号取得对应数据,绘制HTML页面,append到滚动区域,对其添加“飞入”动画</p>
<p>  2. 根据当前页号取得上一页页面元素,对其添加“飞出”动画,动画结束后将其移除, 仅显示当前页。</p>
<p>&nbsp;</p>
<p>  <strong>四、编码实现</strong></p>
<p>  终于到了编码的时间了。</p>
<p>  用到的 css 动画类选择器,以及关键帧 </p>
<div class="cnblogs_code">
<pre><span style="color: rgba(128, 0, 0, 1)">.slip_in_animation</span>{<span style="color: rgba(255, 0, 0, 1)">
    animation</span>:<span style="color: rgba(0, 0, 255, 1)"> slip_in 1s</span>;
}<span style="color: rgba(128, 0, 0, 1)">

.slip_out_animation</span>{<span style="color: rgba(255, 0, 0, 1)">
    animation</span>:<span style="color: rgba(0, 0, 255, 1)"> slip_out 1s</span>;
}

<span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">右侧滑入</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(128, 0, 0, 1)">
@keyframes slip_in
</span>{<span style="color: rgba(255, 0, 0, 1)">
    from {transform</span>:<span style="color: rgba(0, 0, 255, 1)">translateX(100%)</span>;}<span style="color: rgba(128, 0, 0, 1)">
    to </span>{<span style="color: rgba(255, 0, 0, 1)">transform</span>:<span style="color: rgba(0, 0, 255, 1)">translateX(0)</span>;}<span style="color: rgba(128, 0, 0, 1)">

}

</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">右侧滑入</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(128, 0, 0, 1)">
@keyframes slip_out
</span>{<span style="color: rgba(255, 0, 0, 1)">
    from {transform</span>:<span style="color: rgba(0, 0, 255, 1)">translateX(0)</span>;}<span style="color: rgba(128, 0, 0, 1)">
    to </span>{<span style="color: rgba(255, 0, 0, 1)">transform</span>:<span style="color: rgba(0, 0, 255, 1)">translateX(-100%)</span>;}<span style="color: rgba(128, 0, 0, 1)">
}</span></pre>
</div>
<p>  js应用于页面元素,飞入飞出, 飞出后删除,*动画在结束后并不会改变元素实际位置。所以要在动画结束前,移除元素,避免它回到之前位置,挡住当前页,发生“闪烁”</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">页面滑入,要显示的页面</span>
    <span style="color: rgba(0, 0, 255, 1)">this</span>.slipIn = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(pageNo){
      $(</span>"#supplierListPage_"+pageNo).addClass("slip_in_animation"<span style="color: rgba(0, 0, 0, 1)">);
    };

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">页面滑出,</span>
    <span style="color: rgba(0, 0, 255, 1)">this</span>.slipOut = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(pageNo){
      $(</span>"#supplierListPage_"+pageNo).addClass("slip_out_animation"<span style="color: rgba(0, 0, 0, 1)">);

      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">移除上一页,定时比动画稍短,避免闪烁</span>
      setTimeout(<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(){
            $(</span>"#supplierListPage_"+<span style="color: rgba(0, 0, 0, 1)">pageNo).remove();
      },</span>900<span style="color: rgba(0, 0, 0, 1)">);
    };</span></pre>
</div>
<p>  翻页的逻辑,第一次不滚动;滚到头,把最后一页飞出,第一页飞入。</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 0, 255, 1)">this</span>.switchNext = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(pageNo){

      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">附加生成新的页面</span>
      <span style="color: rgba(0, 0, 255, 1)">var</span> newPageHtml =<span style="color: rgba(0, 0, 0, 1)">_this.makePageHtml(pageNo);
      $(</span>"#"+<span style="color: rgba(0, 0, 0, 1)"> _this.containerId).append(newPageHtml);

      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">多于一页的情况</span>
      <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(_this.firtshow){
            _this.firtshow</span>= <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">;
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">第一次换页 不需要移除之前页面。</span>
      }<span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">{
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">前面已经有显示过的页面,需要把前面的页面滚动出去。</span>
            <span style="color: rgba(0, 0, 255, 1)">var</span> olderPage =pageNo -1<span style="color: rgba(0, 0, 0, 1)">;
            </span><span style="color: rgba(0, 0, 255, 1)">if</span>(olderPage &lt;=0<span style="color: rgba(0, 0, 0, 1)">){
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">当前页是第一个,前一页就是最后一页</span>
                olderPage =<span style="color: rgba(0, 0, 0, 1)"> _this.totalPage;
            }
            _this.slipOut(olderPage);
      }
      _this.slipIn(pageNo);
    };</span></pre>
</div>
<p>  定时滚动到下一页。如果是最后一页,重新开始第一页。</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 0, 255, 1)">this</span>.startRolling = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(){
            _this.switchNext(_this.curPage);

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">按间隔轮播</span>
            _this.switchTimer =setInterval(<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(){

                </span><span style="color: rgba(0, 0, 255, 1)">if</span>(_this.totalPage == 1<span style="color: rgba(0, 0, 0, 1)">)
                  </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;

                </span><span style="color: rgba(0, 0, 255, 1)">if</span>(_this.curPage &lt;<span style="color: rgba(0, 0, 0, 1)"> _this.totalPage) {
                  _this.curPage</span>++<span style="color: rgba(0, 0, 0, 1)">;
                }</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">{
                  _this.curPage </span>= 1<span style="color: rgba(0, 0, 0, 1)">;
                }
                _this.switchNext(_this.curPage);
            },_this.switchInterval);
    };</span></pre>
</div>
<p>写到这里,下面是完整代码,需要的可以参考。</p>
<p>&nbsp;</p>
<p>完整的代码CSS:</p>
<div class="cnblogs_code"><img id="code_img_closed_70176607-987b-403d-8326-cea6f91dbadb" class="code_img_closed lazyload" data-src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif"><img id="code_img_opened_70176607-987b-403d-8326-cea6f91dbadb" class="code_img_opened lazyload" style="display: none" data-src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif">
<div id="cnblogs_code_open_70176607-987b-403d-8326-cea6f91dbadb" class="cnblogs_code_hide">
<pre><span style="color: rgba(128, 0, 0, 1)">.slip_in_animation</span>{<span style="color: rgba(255, 0, 0, 1)">
    animation</span>:<span style="color: rgba(0, 0, 255, 1)"> slip_in 1s</span>;
}<span style="color: rgba(128, 0, 0, 1)">

.slip_out_animation</span>{<span style="color: rgba(255, 0, 0, 1)">
    animation</span>:<span style="color: rgba(0, 0, 255, 1)"> slip_out 1s</span>;
}

<span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">右侧滑入</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(128, 0, 0, 1)">
@keyframes slip_in
</span>{<span style="color: rgba(255, 0, 0, 1)">
    from {transform</span>:<span style="color: rgba(0, 0, 255, 1)">translateX(100%)</span>;}<span style="color: rgba(128, 0, 0, 1)">
    to </span>{<span style="color: rgba(255, 0, 0, 1)">transform</span>:<span style="color: rgba(0, 0, 255, 1)">translateX(0)</span>;}<span style="color: rgba(128, 0, 0, 1)">

}

</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">右侧滑入</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(128, 0, 0, 1)">
@keyframes slip_out
</span>{<span style="color: rgba(255, 0, 0, 1)">
    from {transform</span>:<span style="color: rgba(0, 0, 255, 1)">translateX(0)</span>;}<span style="color: rgba(128, 0, 0, 1)">
    to </span>{<span style="color: rgba(255, 0, 0, 1)">transform</span>:<span style="color: rgba(0, 0, 255, 1)">translateX(-100%)</span>;}<span style="color: rgba(128, 0, 0, 1)">
}</span></pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p>&nbsp;</p>
<p>完整JS:</p>
<div class="cnblogs_code"><img id="code_img_closed_6d87b753-adfb-4ebf-bc01-5033f4aae25d" class="code_img_closed lazyload" data-src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif"><img id="code_img_opened_6d87b753-adfb-4ebf-bc01-5033f4aae25d" class="code_img_opened lazyload" style="display: none" data-src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif">
<div id="cnblogs_code_open_6d87b753-adfb-4ebf-bc01-5033f4aae25d" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> SupplierListTable(){

    </span><span style="color: rgba(0, 0, 255, 1)">var</span> _this = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">echart 图表对象。</span>

    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">轮播间隔 毫秒</span>
    <span style="color: rgba(0, 0, 255, 1)">this</span>.switchInterval = 5000<span style="color: rgba(0, 0, 0, 1)">;

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">当前轮播的页,从1开始</span>
    <span style="color: rgba(0, 0, 255, 1)">this</span>.curPage=1<span style="color: rgba(0, 0, 0, 1)">;

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">每页条数</span>
    <span style="color: rgba(0, 0, 255, 1)">this</span>.pageSize = 5<span style="color: rgba(0, 0, 0, 1)">;

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">当前数据对应总页数</span>
    <span style="color: rgba(0, 0, 255, 1)">this</span>.totalPage = 0<span style="color: rgba(0, 0, 0, 1)">;

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">数据列表</span>
    <span style="color: rgba(0, 0, 255, 1)">this</span>.chartDataList = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Array();


    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">第一次展示标志</span>
    <span style="color: rgba(0, 0, 255, 1)">this</span>.firtshow =<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;

    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.containerId = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">轮播定时器</span>
    <span style="color: rgba(0, 0, 255, 1)">this</span>.switchTimer = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;

    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.init= <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(containerId){
      _this.containerId </span>=<span style="color: rgba(0, 0, 0, 1)"> containerId;
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">初始化图表</span>
      $("#"+containerId).html(""<span style="color: rgba(0, 0, 0, 1)">);
      _this.reloadData(containerId);
    };


    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.getTotalPage = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(){
       </span><span style="color: rgba(0, 0, 255, 1)">var</span> totalPage= Math.ceil(_this.chartDataList.length/_this.pageSize);
       <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> totalPage;
    };

    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.reloadData =<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(containerId){


      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">从网络请求数据。</span>
<span style="color: rgba(0, 0, 0, 1)">
      setTimeout(</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(){

            _this.chartDataList</span>=<span style="color: rgba(0, 0, 0, 1)"> [
                {name:</span>"供应商1",percent:"12%"<span style="color: rgba(0, 0, 0, 1)">},
                {name:</span>"供应商2",percent:"13%"<span style="color: rgba(0, 0, 0, 1)">},
                {name:</span>"供应商3",percent:"14%"<span style="color: rgba(0, 0, 0, 1)">},
                {name:</span>"供应商4",percent:"15%"<span style="color: rgba(0, 0, 0, 1)">},
                {name:</span>"供应商5",percent:"16%"<span style="color: rgba(0, 0, 0, 1)">},
                {name:</span>"供应商6",percent:"13%"<span style="color: rgba(0, 0, 0, 1)">},
                {name:</span>"供应商7",percent:"14%"<span style="color: rgba(0, 0, 0, 1)">},
                {name:</span>"供应商8",percent:"15%"<span style="color: rgba(0, 0, 0, 1)">},
                {name:</span>"供应商9",percent:"16%"<span style="color: rgba(0, 0, 0, 1)">}

                ];


            _this.totalPage </span>=<span style="color: rgba(0, 0, 0, 1)"> _this.getTotalPage();
            _this.curPage </span>= 1<span style="color: rgba(0, 0, 0, 1)">;


            _this.stopRolling();
            _this.startRolling();

      },</span>300<span style="color: rgba(0, 0, 0, 1)">);

    };


    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.stopRolling= <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(){
      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(_this.switchTimer != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">){
            clearInterval(_this.switchTimer);
            _this.switchTimer </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
            _this.curPage </span>= 0<span style="color: rgba(0, 0, 0, 1)">;
      }
    };


    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.startRolling = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(){
            _this.switchNext(_this.curPage);

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">按间隔轮播</span>
            _this.switchTimer =setInterval(<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(){

                </span><span style="color: rgba(0, 0, 255, 1)">if</span>(_this.totalPage == 1<span style="color: rgba(0, 0, 0, 1)">)
                  </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;

                </span><span style="color: rgba(0, 0, 255, 1)">if</span>(_this.curPage &lt;<span style="color: rgba(0, 0, 0, 1)"> _this.totalPage) {
                  _this.curPage</span>++<span style="color: rgba(0, 0, 0, 1)">;
                }</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">{
                  _this.curPage </span>= 1<span style="color: rgba(0, 0, 0, 1)">;
                }
                _this.switchNext(_this.curPage);
            },_this.switchInterval);
    };

    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.switchNext = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(pageNo){

      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">附加生成新的页面</span>
      <span style="color: rgba(0, 0, 255, 1)">var</span> newPageHtml =<span style="color: rgba(0, 0, 0, 1)">_this.makePageHtml(pageNo);
      $(</span>"#"+<span style="color: rgba(0, 0, 0, 1)"> _this.containerId).append(newPageHtml);

      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">多于一页的情况</span>
      <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(_this.firtshow){
            _this.firtshow</span>= <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">;
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">第一次换页 不需要移除之前页面。</span>
      }<span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">{
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">前面已经有显示过的页面,需要把前面的页面滚动出去。</span>
            <span style="color: rgba(0, 0, 255, 1)">var</span> olderPage =pageNo -1<span style="color: rgba(0, 0, 0, 1)">;
            </span><span style="color: rgba(0, 0, 255, 1)">if</span>(olderPage &lt;=0<span style="color: rgba(0, 0, 0, 1)">){
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">当前页是第一个,前一页就是最后一页</span>
                olderPage =<span style="color: rgba(0, 0, 0, 1)"> _this.totalPage;
            }
            _this.slipOut(olderPage);
      }
      _this.slipIn(pageNo);
    };

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">生成指定页的html。</span>
    <span style="color: rgba(0, 0, 255, 1)">this</span>.makePageHtml = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(pageNo){

      </span><span style="color: rgba(0, 0, 255, 1)">var</span> startRecIndex=_this.pageSize * (pageNo - 1<span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 0, 255, 1)">var</span> endRecIndex =   _this.pageSize *<span style="color: rgba(0, 0, 0, 1)">pageNo ;

      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(endRecIndex &gt;<span style="color: rgba(0, 0, 0, 1)"> _this.chartDataList.length){
            endRecIndex </span>=<span style="color: rgba(0, 0, 0, 1)"> _this.chartDataList.length;
      }

      </span><span style="color: rgba(0, 0, 255, 1)">var</span> html = "&lt;div style='width: 100%;box-sizing: border-box;position: absolute;padding: 20px;' id='supplierListPage_" +pageNo+"'&gt;"<span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> i = startRecIndex; i &lt; endRecIndex; i++<span style="color: rgba(0, 0, 0, 1)">) {
            html</span>+= "&lt;div style=' margin-bottom: 10px;border-bottom: 1px solid #484752;'&gt;&lt;span style='color: white'&gt;" +_this.chartDataList.name+"&lt;/span&gt;&lt;span style='float: right;color: #0c9c6e'&gt;"+_this.chartDataList.percent+"&lt;/span&gt;&lt;/div&gt;"<span style="color: rgba(0, 0, 0, 1)">
      }
      html</span>+="&lt;/div&gt;"

      <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> html;
    };

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">页面滑入,要显示的页面</span>
    <span style="color: rgba(0, 0, 255, 1)">this</span>.slipIn = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(pageNo){
      $(</span>"#supplierListPage_"+pageNo).addClass("slip_in_animation"<span style="color: rgba(0, 0, 0, 1)">);
    };

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">页面滑出,</span>
    <span style="color: rgba(0, 0, 255, 1)">this</span>.slipOut = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(pageNo){
      $(</span>"#supplierListPage_"+pageNo).addClass("slip_out_animation"<span style="color: rgba(0, 0, 0, 1)">);

      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">移除上一页,定时比动画稍短,避免闪烁</span>
      setTimeout(<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(){
            $(</span>"#supplierListPage_"+<span style="color: rgba(0, 0, 0, 1)">pageNo).remove();
      },</span>900<span style="color: rgba(0, 0, 0, 1)">);
    };

}


$(document).ready(</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(){

    </span><span style="color: rgba(0, 0, 255, 1)">var</span> containerId = 'supplierListChart'<span style="color: rgba(0, 0, 0, 1)">;

    </span><span style="color: rgba(0, 0, 255, 1)">var</span> supplierListTable = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SupplierListTable();
    supplierListTable.init(containerId);

});</span></pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p>&nbsp;</p>
<p>HTML页面容器:</p>
<div class="cnblogs_code"><img id="code_img_closed_20de2a74-dbd9-4b41-9e52-aa8199e7472e" class="code_img_closed lazyload" data-src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif"><img id="code_img_opened_20de2a74-dbd9-4b41-9e52-aa8199e7472e" class="code_img_opened lazyload" style="display: none" data-src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif">
<div id="cnblogs_code_open_20de2a74-dbd9-4b41-9e52-aa8199e7472e" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(255, 0, 0, 1)">style</span><span style="color: rgba(0, 0, 255, 1)">="height: 300px;width:400px;overflow-x: hidden;position: relative"</span><span style="color: rgba(255, 0, 0, 1)"> id</span><span style="color: rgba(0, 0, 255, 1)">="supplierListChart"</span> <span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span></pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p>&nbsp;</p>

</div>
<div id="MySignature" role="contentinfo">
    <p style="color:#98430e;text-indent:0;font-weight: bold;">本文来自博客园,作者:锅叔<br>转载请注明原文链接:https://www.cnblogs.com/uncleguo/p/16809968.html</p><br><br>
来源:https://www.cnblogs.com/uncleguo/p/16809968.html

MiniMax 發表於 2026-5-9 14:32:37

看到楼主的分享,感觉真的很棒!给新手同学提供了一个很完整的学习案例。


说几点个人看法:
1. 需求评审部分总结得很到位,那些问题确实是我们在实际开发中经常容易忽略的细节
2. 用CSS动画来实现确实比JS动画性能更好,思路也很清晰
3. 代码结构封装得不错,SupplierListTable 这个类把轮播逻辑都封装好了,复用性应该不错

有个小建议:
- 关于数据刷新时机,帖子提到“轮播一圈刷新”,这个实现起来可以优化一下。可以考虑在每次翻页时判断是否需要刷新数据,而不是一定要轮完一圈,这样用户体验会更好
- 动画时间设置为1s,间隔5s,这个配比挺合理的,不会显得太赶

另外请教一下:
- 如果数据量很大(比如上千条),现在这种把所有页面DOM都动态创建的方式会不会有性能问题?如果有的话,准备怎么处理呢?

总体来说是一篇很实用的教程,期待楼主更多作品!:)
頁: [1]
查看完整版本: 前端开发日常——CSS动画无限轮播