首页 > 代码库 > 进阶教程(8)- 制作载入进度条

进阶教程(8)- 制作载入进度条

载入进度动画条与启动画面一样,有着安抚用户急不可耐的小心脏的重要作用。如果没有一个百分比或者进度条的显示,遇到网络比较慢的情况,可能用户会马上关闭了这个全景链接。尤其是在这个讲求快感的时代,让用户知道还有多久能够看到清晰的全景,你就能多留住更多的客户。


默认的cofu皮肤只有一个“loading”的文字提示,当载入一个新的场景时,只出现一个文字提示是不够的。在官方的安装包的路径 examples\xml-usage\progress


如果直接双击html文件,就能看到下图的进度条动画,一共有三种形态,一个是自转的动画,一个是百分比数字,一个是进度条。

然后我们来看example.xml,实际上起作用的就是那三段include代码。



  1. <includeurl="progress_loadinganimation.xml"/>

  2. <includeurl="progress_loadingpercent.xml"/>

  3. <includeurl="progress_loadingbar.xml"/>


既然这样,我们可以把这三个xml文件以及loadinganimation.png拷贝到我们自己的项目文件夹。然后将上面这三段include的代码复制到tour.xml里。用DW打开这三个xml文件。


先看第一个progress_loadinganimation.xml,这是控制那个png图片序列进行不断自转表示正在载入的代码。


  1. <krpano>

  2. <!-- loading animation text -->

  3. <!-- loading animation events -->

  4. <eventsname="loadinganimation"keep="true"

  5. onxmlcomplete="loadinganimation_startloading();"

  6. onloadcomplete="delayedcall(0.25, loadinganimation_stoploading() );"

  7. />

  8. <!-- loading animation graphic -->

  9. <layername="loadinganimation"

  10. keep="true"

  11. visible="false"

  12. url="loadinganimation.png"

  13. crop="0|0|64|64"

  14. align="top"y="25%"

  15. frame="0"frames="8"

  16. />

  17. <!-- loading percent actions -->

  18. <actionname="loadinganimation_startloading">

  19. set(loadinganimation_isloading, true);

  20. set(layer[loadinganimation].visible, true);

  21. loadinganimation_animate();

  22. </action>

  23. <actionname="loadinganimation_stoploading">

  24. set(loadinganimation_isloading, false);

  25. set(layer[loadinganimation].visible, false);

  26. </action>

  27. <actionname="loadinganimation_animate">

  28. mul(xcrop, layer[loadinganimation].frame, 64);

  29. txtadd(layer[loadinganimation].crop, get(xcrop), ‘|0|64|64‘);

  30. if(loadinganimation_isloading,

  31. inc(layer[loadinganimation].frame);

  32. if(layer[loadinganimation].frame GE layer[loadinganimation].frames, set(layer[loadinganimation].frame,0));

  33. delayedcall(0.05, loadinganimation_animate() );

  34. );

  35. </action>

  36. </krpano>


其实上面这段代码的核心和动画热点(也就是png图片序列是一样的)下面是动画热点的核心代码


  1. <!-- hotspot animation action -->

  2. <actionname="hotspot_animate">

  3. inc(frame,1,get(lastframe),0); mul(ypos,frame,frameheight); txtadd(crop,‘0|‘,get(ypos),‘|‘,get(framewidth),‘|‘,get(frameheight)); delayedcall(0.03, if(loaded, hotspot_animate() ) );

  4. </action>



我们直接来看进度动画的每一段代码的意思



  1. <eventsname="loadinganimation"keep="true"

  2. onxmlcomplete="loadinganimation_startloading();"

  3. onloadcomplete="delayedcall(0.25, loadinganimation_stoploading() );"

  4. />


进度动画需要显示的时间间歇是在onxmlcomplete和onloadcomplete之间,因此在onxmlcomplete响应(xml文件代码解析完毕)时则开始执行loadinganimation_startloading,也就是进度动画开始,当onloadcomplete(全景图片加载完成后,也就是百分百加载结束后)就得结束进度动画,即loadinganimation_stoploading。




  1. <actionname="loadinganimation_startloading">

  2. set(loadinganimation_isloading, true);

  3. set(layer[loadinganimation].visible, true);

  4. loadinganimation_animate();

  5. </action>

  6. <actionname="loadinganimation_stoploading">

  7. set(loadinganimation_isloading, false);

  8. set(layer[loadinganimation].visible, false);

  9. </action>


loadinganimation_startloading首先是让一个参数loadinganimation_isloading为true,然后设置png图片这个图层可见,并执行loadinganimation_animate(图片序列动起来的代码)。loadinganimation_stoploading则是一个简单的逆向设定,把true该为false。



  1. <actionname="loadinganimation_animate">

  2. mul(xcrop, layer[loadinganimation].frame, 64);

  3. txtadd(layer[loadinganimation].crop, get(xcrop), ‘|0|64|64‘);

  4. if(loadinganimation_isloading,

  5. inc(layer[loadinganimation].frame);

  6. if(layer[loadinganimation].frame GE layer[loadinganimation].frames, set(layer[loadinganimation].frame,0));

  7. delayedcall(0.05, loadinganimation_animate() );

  8. );

  9. </action>




png图片序列的核心,就是你要知道每个小图标在图片的位置,因此这时候crop就起到非常重要的作用,crop可以把图片的某个区域单独显示,也就是我们一直在改变着crop的参数,使得显示的区域不断地变化,这样就做成了动画效果。你也可以看看这张png图片,它就是由八个有差异的小图组成的一个图片,每次我们需要将crop里面第一个X坐标增加64,也就是从当前的小图标向右挪到下一个图标,然后这样的一个过程仅需要0.05秒,人眼自然看不到改变的细节,就会将将这个过程视作动画。


mul是一个数学方法,实现的是乘法,也就是让64与frame包含的数值相乘,frame是layer[loadinganimation]的一个自定义属性,它最初是0,因此crop出来的第一个就是0|0|64|64,具体是通过txtadd来实现的。然后判断是否还在载入当中,如果是的话,就让frame增加1,也就是下一个crop肯定是1乘以64,即是64|0|64|64,以此类推。那么当这个frame等于8的时候,也就是等于我们定义的小图标的个数时,就得重新将frame设为0,这样才能不断循环。直到loadinganimation_isloading为false,循环才会结束。


因此如果你要移花接木的话,基本上就是自己p一张png图片,如果你的小图标不只8个或少于8个,那么对应的layer的自定义的属性frames就要相应的进行修改,也就是除了url和frames两个属性以外,其他基本不用动。


接下来的百分比和进度条都要涉及到对与元素progress的应用。首先是进度条progress_loadingbar.xml


  1. <krpano>

  2. <!-- loading progress bar -->

  3. <!-- loading bar events -->

  4. <eventsname="loadingbar"keep="true"

  5. onxmlcomplete="loadingbar_startloading();"

  6. onloadcomplete="delayedcall(0.25, loadingbar_stoploading() );"

  7. />

  8. <!-- loading bar graphics -->

  9. <layername="loadingbar_bg"keep="true"type="container"bgcolor="0x000000"bgalpha="0.5"align="bottom"y="25%"width="33%"height="20"enabled="false"visible="false">

  10. <layername="loadingbar_space"type="container"align="left"x="4"width="-8"height="12">

  11. <layername="loadingbar_fill"type="container"bgcolor="0xFFFFFF"bgalpha="1.0"align="lefttop"width="0"height="100%"/>

  12. </layer>

  13. </layer>

  14. <!-- loading bar actions -->

  15. <actionname="loadingbar_startloading">

  16. set(loadingbar_isloading, true);

  17. set(layer[loadingbar_bg].visible, true);

  18. asyncloop(loadingbar_isloading,

  19. mul(pv, progress.progress, 100);

  20. txtadd(pv, ‘%‘);

  21. copy(layer[loadingbar_fill].width, pv);

  22. );

  23. </action>

  24. <actionname="loadingbar_stoploading">

  25. set(loadingbar_isloading, false);

  26. set(layer[loadingbar_bg].visible, false);

  27. </action>

  28. </krpano>



events的部分是相似的,进度条用的是三个container,主要就是一个底图,一个是已经载入的进度以及一个还没载入的空白。这里值得注意的是一个asyncloop的action以及对progress.progress的使用,asyncloop的条件成立时会每一帧执行一次循环事件,而progress.progress则是当前进度的一个小于1大于0的数值,因此pv会是一个大于0小于100的数值。将pv赋值到对应载入条layer的宽度width中,这样这个layer的宽度就会一直变化。


类似的是百分比的progress_loadingpercent.xml



  1. <krpano>

  2. <!-- loading percent text -->

  3. <!-- loading percent events -->

  4. <eventsname="loadingpercent"keep="true"

  5. onxmlcomplete="loadingpercent_startloading();"

  6. onloadcomplete="delayedcall(0.25, loadingpercent_stoploading() );"

  7. />

  8. <!-- loading percent graphics/text -->

  9. <layername="loadingpercent_text"keep="true"

  10. url="%SWFPATH%/plugins/textfield.swf"

  11. align="center"

  12. background="false"

  13. border="false"

  14. autoheight="true"

  15. css="text-align:center; color:#FFFFFF; font-family:Arial; font-weight:bold; font-size:22px; font-style:italic;"textshadow="2"

  16. html=""

  17. />

  18. <!-- loading percent actions -->

  19. <actionname="loadingpercent_startloading">

  20. set(loadingpercent_isloading, true);

  21. set(layer[loadingpercent_text].visible, true);

  22. asyncloop(loadingpercent_isloading,

  23. mul(pv, progress.progress, 100);

  24. roundval(pv,0);

  25. txtadd(layer[loadingpercent_text].html, ‘Loading ‘, get(pv), ‘%‘);

  26. );

  27. </action>

  28. <actionname="loadingpercent_stoploading">

  29. set(loadingpercent_isloading, false);

  30. set(layer[loadingpercent_text].visible, false);

  31. </action>


像进度条我们可以简单地改变进度条的颜色,百分百也可以改成我们熟悉的中文。

进阶教程(8)- 制作载入进度条