经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » Vue.js » 查看文章
vue上通过krpano.js实现360全景图
来源:cnblogs  作者:中文呀  时间:2023/10/9 9:22:59  对本文有异议

首先贴出一些XML对应的函数,文件内容都有注释说明,

前端代码读取xml文件代码

  1. // 初始化
  2. window.embedpano({
  3. xml: 0,
  4. target: 'pano',
  5. html5: 'only',
  6. mobilescale: 1.0,
  7. passQueryParameters: 'startscene,startlookat',
  8. initvars: {
  9. KRPANOPATH: process.env.NODE_ENV === 'development' ? '/' : '',
  10. },
  11. })
  12. // 初始化完成,展示xml数据,
  13. initKrpanoReady(tempXml, title) {
  14. this.krpano = document.getElementById('krpanoSWFObject')
  15. if (!this.info.toolkit) {
  16. tempXml = tempXml.replaceAll(`ondown="hotspot_drag();"`, '')
  17. }
  18. // 如果是开发环境
  19. if (process.env.NODE_ENV === 'development') {
  20. window._CONFIG.krpanoPath = '/'
  21. }
  22. tempXml = tempXml.replaceAll(`url="template_action.xml"`, `url="${window._CONFIG.krpanoPath}template_action.xml"`)
  23. tempXml = tempXml.replaceAll(`url="vtourskin.xml"`, `url="${window._CONFIG.krpanoPath}vtourskin.xml"`)
  24. tempXml = tempXml.replaceAll(`url="images/`, `url="${window._CONFIG.krpanoPath}images/`)
  25. this.krpano.call(`loadxml(${tempXml})`)
  26. if (title) {
  27. this.panoramaTitle = `${title} - 全景图浏览`
  28. }
  29. },
View Code

 

  1. <krpano>
    <!-- 这个文件主要写了一些自定义函数,可以在页面通过js来调用 -->
  2. <!-- 热点增加动画 -->
  3. <action name="hotspot_do_animation" scope="local">
  4. calc(local.xframes, (caller.imagewidth /128) BOR 0);
  5. calc(local.frames, xframes * ((caller.imageheight / 128) BOR 0));
  6. def(local.frame, integer, 0);
  7. calc(caller.crop, '0|0|' + 128 + '|' + 128);
  8. setinterval(calc('crop_anim_' + caller.name), 0.03,
  9. if(caller.loaded,
  10. inc(frame);
  11. if(frame GE frames, if(caller.onlastframe !== null, callwith(caller, onlastframe() ) ); set(frame,0); );
  12. mod(xpos, frame, xframes);
  13. div(ypos, frame, xframes);
  14. Math.floor(ypos);
  15. mul(xpos, 128);
  16. mul(ypos, 128);
  17. calc(caller.crop, xpos + '|' + ypos + '|' + 128 + '|' + 128);
  18. ,
  19. clearinterval(calc('crop_anim_' + caller.name));
  20. );
  21. ,10);
  22. </action>
  23. <!-- 热点显示标题,hotspot_title 字段 -->
  24. <action name="hotspot_show_title">
  25. txtadd(tooltipname, 'tooltip_', get(name));
  26. addplugin(get(tooltipname)); txtadd(plugin[get(tooltipname)].parent, 'hotspot[',get(name),']');
  27. set(plugin[get(tooltipname)].url,'%SWFPATH%/plugins/textfield.swf');
  28. set(plugin[get(tooltipname)].align,top);
  29. set(plugin[get(tooltipname)].edge,bottom);
  30. set(plugin[get(tooltipname)].x,0);
  31. set(plugin[get(tooltipname)].y,0);
  32. set(plugin[get(tooltipname)].autowidth,true);
  33. set(plugin[get(tooltipname)].autoheight,true);
  34. set(plugin[get(tooltipname)].background,false);
  35. set(plugin[get(tooltipname)].border,false);
  36. set(plugin[get(tooltipname)].css,'text-align:center; color:#FFFFFF; font-family: PingFangSC-Medium,PingFang SC; font-weight:bold; font-size:16px;');
  37. set(plugin[get(tooltipname)].textshadow,1);
  38. set(plugin[get(tooltipname)].textshadowrange,6.0);
  39. set(plugin[get(tooltipname)].textshadowangle,90);
  40. copy(plugin[get(tooltipname)].html,hotspot[get(name)].hotspot_title);
  41. set(plugin[get(tooltipname)].enabled,false);
  42. </action>
  43.  
  44. <!-- 热点拖动 -->
  45. <action name="hotspot_drag">
  46. spheretoscreen(ath, atv, hotspotcenterx, hotspotcentery, calc(mouse.stagex LT stagewidth/2 ? 'l' : 'r'));
  47. sub(drag_adjustx, mouse.stagex, hotspotcenterx);
  48. sub(drag_adjusty, mouse.stagey, hotspotcentery);
  49. asyncloop(pressed,
  50. sub(dx, mouse.stagex, drag_adjustx);
  51. sub(dy, mouse.stagey, drag_adjusty);
  52. screentosphere(dx, dy, ath, atv);
  53. copy(print_ath, ath);
  54. copy(print_atv, atv);
  55. roundval(print_ath, 3);
  56. roundval(print_atv, 3);
  57. );
  58. </action>
  59.  
  60. <!-- 热点点击弹出编辑框 -->
  61. <action name="hotspot_click_edit">
  62. js(handleClickHotSpotsEdit(get(hotspot_title),get(hotspot_type),get(print_ath),get(print_atv),get(url)));
  63. </action>
  64.  
  65. <!-- 获取热点坐标 -->
  66. <action name="hotspot_get_ath_atv">
  67. js(handleClickHotSpotsGetAthAtv(get(print_ath),get(print_atv)));
  68. </action>
  69.  
  70. <!-- 热点点击切换场景 -->
  71. <action name="hotspot_click_scene" scope="local" args="scene_id, hotspot_code">
  72. js(handleClickHotSpotsScene(get(scene_id),get(hotspot_code)));
  73. hotspot_get_ath_atv();
  74. </action>
  75.  
  76. <!-- 热点点击设备列表 -->
  77. <action name="hotspot_click_device" scope="local" args="collector_id, host_id, obj_type, hotspot_title, hotspot_code">
  78. js(handleClickHotSpotsDevice(get(collector_id),get(host_id),get(obj_type),get(hotspot_title),get(hotspot_code)));
  79. hotspot_get_ath_atv();
  80. </action>
  81.  
  82. <!-- 获取当前视角的值 -->
  83. <action name="view_get_toh_tov">
  84. copy(print_hlookat, view.hlookat);
  85. copy(print_vlookat, view.vlookat);
  86. roundval(print_hlookat, 3);
  87. roundval(print_vlookat, 3);
  88. js(handleGetViewTohTov(get(print_hlookat),get(print_vlookat)))
  89. </action>
  90. </krpano>

下面这个文件是krpano.js默认配置项的文件,简单做了一些调整以及增加了一部分注释

  1. <krpano>
  2. <skin_settings
  3. maps="false"
  4. maps_type="google"
  5. maps_bing_api_key=""
  6. maps_google_api_key=""
  7. maps_zoombuttons="false"
  8. gyro="true"
  9. webvr="true"
  10. webvr_gyro_keeplookingdirection="false"
  11. webvr_prev_next_hotspots="true"
  12. littleplanetintro="false"
  13. title="true"
  14. thumbs="true"
  15. thumbs_width="120"
  16. thumbs_height="80"
  17. thumbs_padding="10"
  18. thumbs_crop="0|40|240|160"
  19. thumbs_opened="true"
  20. thumbs_text="true"
  21. thumbs_dragging="true"
  22. thumbs_onhoverscrolling="false"
  23. thumbs_scrollbuttons="false"
  24. thumbs_scrollindicator="false"
  25. thumbs_loop="true"
  26. tooltips_buttons="false"
  27. tooltips_thumbs="false"
  28. tooltips_hotspots="false"
  29. tooltips_mapspots="false"
  30. deeplinking="false"
  31. loadscene_flags="MERGE"
  32. loadscene_blend="OPENBLEND(0.5, 0.0, 0.75, 0.05, linear)"
  33. loadscene_blend_prev="SLIDEBLEND(0.5, 180, 0.75, linear)"
  34. loadscene_blend_next="SLIDEBLEND(0.5, 0, 0.75, linear)"
  35. loadingtext=""
  36. layout_width="100%"
  37. layout_maxwidth="814"
  38. controlbar_width="-24"
  39. controlbar_height="40"
  40. controlbar_offset="20"
  41. controlbar_offset_closed="-40"
  42. controlbar_overlap.no-fractionalscaling="10"
  43. controlbar_overlap.fractionalscaling="0"
  44. design_skin_images="%$KRPANOPATH%images/vtourskin.png"
  45. design_bgcolor="0x2D3E50"
  46. design_bgalpha="0.8"
  47. design_bgborder="0"
  48. design_bgroundedge="1"
  49. design_bgshadow="0 4 10 0x000000 0.3"
  50. design_thumbborder_bgborder="3 0xFFFFFF 1.0"
  51. design_thumbborder_padding="0"
  52. design_thumbborder_bgroundedge="0"
  53. design_thumb_css="transform:translateZ(1e+12px) translate(0,0) translate(-60px, -40px) rotate(0deg) translate(60px, 40px)"
  54. design_text_css="color:#FFFFFF; font-family:Arial;"
  55. design_text_shadow="0" />
  56.  
  57. <!-- mouse / touch / keyboard(button) control settings - http://krpano.com/docu/xml/#control -->
  58. <!-- 鼠标触屏键盘控制的设定 -->
  59. <control mouse="drag" touch="drag" zoomtocursor="false" zoomoutcursor="false" draginertia="0.1" dragfriction="0.9" movetoaccelerate="1.0" movetospeed="10.0" movetofriction="0.8" keybaccelerate="0.09" keybfriction="0.94" keybfovchange="0.25" mousefovchange="1.0" fovspeed="3.0" fovfriction="0.9" bouncinglimits="true" />
  60.  
  61. <!-- mouse cursors - http://krpano.com/docu/xml/#cursors -->
  62. <!-- 鼠标光标设定可自定义光标的样式 -->
  63. <cursors standard="default" dragging="move" moving="move" />
  64.  
  65.  
  66. <!-- ensure stagescale 2x for mobile devices (regardless if mobilescale is 0.5 or 1.0) -->
  67. <krpano stagescale="calc:stagescale * 2" if="stagescale LT 1.0" devices="mobile" />
  68.  
  69.  
  70. <!-- skin styles -->
  71.  
  72. <!-- skin_base - the base skin image -->
  73. <style name="skin_base" url="calc:skin_settings.design_skin_images" />
  74.  
  75.  
  76. <!-- skin_glow - button glowing (if additional ondown,onup,onout,over events are needed, this style provides ondown2,onup2,onover2,onout2 events) -->
  77. <style name="skin_glow" ondown="copy(skin_lockglow,name); skin_buttonglow(get(name)); if(ondown2, ondown2() );" onover="if(skin_lockglow === null, copy(skin_lockglow,name); skin_buttonglow(get(name),0.3) ); if(onover2, onover2() );" onout="if(skin_lockglow === name AND !pressed, skin_buttonglow(null);delete(skin_lockglow); ); if(onout2, onout2() );" onup="if(onup2, onup2()); delayedcall(0, if(hovering AND enabled, skin_buttonglow(get(name),0.3); , skin_buttonglow(null);delete(skin_lockglow); ); );" />
  78.  
  79. <!-- skin_thumbtext_style - style/textfield for the (optional, skin_settings.thumbs_text) thumbnails texts -->
  80. <style name="skin_thumbtext_style" type="text" align="bottom" width="100%" y="5" enabled="false" background="false" border="false" css="calc:skin_settings.design_text_css + ' text-align:center; font-size:10px;'" textshadow="get:skin_settings.design_text_shadow" />
  81.  
  82. <!-- skin_hotspotstyle - style for the hotspots -->
  83. <style name="skin_hotspotstyle" url="vtourskin_hotspot.png" scale="0.5" edge="top" distorted="true" tooltip="" linkedscene="" linkedscene_lookat="" onclick="skin_hotspotstyle_click();" onover="tween(scale,0.55);" onout="tween(scale,0.5);" onloaded="if(linkedscene AND skin_settings.tooltips_hotspots, copy(tooltip,scene[get(linkedscene)].title); loadstyle(skin_tooltips); );" />
  84.  
  85. <action name="skin_hotspotstyle_click" scope="local">
  86. if(caller.linkedscene,
  87. copy(hs_linkedscene, caller.linkedscene);
  88. if(caller.linkedscene_lookat, txtsplit(caller.linkedscene_lookat, ',', hs_lookat_h, hs_lookat_v, hs_lookat_fov); );
  89. set(caller.enabled, false);
  90. skin_hidetooltips();
  91. tween(caller.depth|caller.alpha|caller.oy|caller.rx, 4000|0.0|-50|-60, 0.5, default,
  92. skin_loadscene(get(hs_linkedscene), get(skin_settings.loadscene_blend));
  93. if(hs_lookat_h !== null, skin_lookat(get(hs_lookat_h), get(hs_lookat_v), get(hs_lookat_fov)); );
  94. skin_updatescroll();
  95. );
  96. );
  97. </action>
  98.  
  99.  
  100. <!-- skin_tooltip - style for the thumb, hotspot and mapspot tooltips -->
  101. <style name="skin_tooltips" onover.mouse="copy(layer[skin_tooltip].html, tooltip);
  102. set(layer[skin_tooltip].visible, true);
  103. tween(layer[skin_tooltip].alpha, 1.0, 0.1);
  104. asyncloop(hovering, copy(layer[skin_tooltip].x,mouse.stagex); copy(layer[skin_tooltip].y,mouse.stagey); );" onout.mouse="tween(layer[skin_tooltip].alpha, 0.0, 0.1, default, set(layer[skin_tooltip].visible,false), copy(layer[skin_tooltip].x,mouse.stagex); copy(layer[skin_tooltip].y,mouse.stagey); );" />
  105.  
  106. <!-- the tooltip textfield -->
  107. <layer name="skin_tooltip" keep="true" type="text" parent="STAGE" visible="false" alpha="0" enabled="false" zorder="2" align="lefttop" edge="bottom" oy="-2" width="200" background="false" backgroundcolor="0xFFFFFF" backgroundalpha="1.0" border="false" bordercolor="0x000000" borderalpha="1.0" borderwidth="1.0" roundedge="0" shadow="0.0" shadowrange="4.0" shadowangle="45" shadowcolor="0x000000" shadowalpha="1.0" textshadow="get:skin_settings.design_text_shadow" textshadowrange="6.0" textshadowangle="90" textshadowcolor="0x000000" textshadowalpha="1.0" css="calc:skin_settings.design_text_css + ' text-align:center; font-size:16px;'" html="" />
  108.  
  109.  
  110. <!-- skin layout -->
  111. <!-- 下方控制条 -->
  112. <layer name="skin_layer" keep="true" type="container" align="top" width="get:skin_settings.layout_width" maxwidth="get:skin_settings.layout_maxwidth" height="100%" maskchildren="true" visible="false" bgcapture="false" zorder="1">
  113. <layer name="skin_scroll_window" type="container" align="bottom" width="100%" height="100%" x="0" y="calc:skin_settings.controlbar_offset + skin_settings.controlbar_height - skin_settings.controlbar_overlap" maskchildren="true" onloaded="skin_calc_opened_closed();" zorder="1">
  114. <layer name="skin_scroll_layer" type="container" align="bottom" width="get:skin_settings.controlbar_width" height="100%" x="0" y="200" y_offset="get:skin_settings.controlbar_overlap" accuracy="1" bgalpha="get:skin_settings.design_bgalpha" bgcolor="get:skin_settings.design_bgcolor" bgborder="get:skin_settings.design_bgborder" bgroundedge="get:skin_settings.design_bgroundedge" bgshadow="get:skin_settings.design_bgshadow">
  115. <layer name="skin_title" type="text" align="lefttop" edge="leftbottom" x="4" y="0" zorder="4" enabled="false" background="false" border="false" css="calc:skin_settings.design_text_css + ' text-align:left; font-style:italic; font-size:12px;'" textshadow="get:skin_settings.design_text_shadow" visible="false" onautosized="skin_video_updateseekbarwidth();" />
  116. <layer name="skin_scroll_container" type="container" align="lefttop" width="100%" height="100%" x="0" y="0" bgroundedge="get:skin_settings.design_bgroundedge" maskchildren="true">
  117. <layer name="skin_thumbs_container" type="container" align="lefttop" width="100%" height="100%" visible="false">
  118. <layer name="skin_thumbs_scrollleft" style="skin_base|skin_glow" crop="0|64|64|64" align="lefttop" edge="left" x="5" y="50" scale="0.5" zorder="2" alpha="1.0" ondown2="asyncloop(pressed, layer[skin_thumbs].scrollby(+2,0));" visible="false" />
  119. <layer name="skin_thumbs_scrollright" style="skin_base|skin_glow" crop="64|64|64|64" align="righttop" edge="right" x="5" y="50" scale="0.5" zorder="2" alpha="1.0" ondown2="asyncloop(pressed, layer[skin_thumbs].scrollby(-2,0));" visible="false" />
  120. <layer name="skin_thumbs_scrollindicator" type="container" bgcolor="0xFFFFFF" bgalpha="0.25" align="lefttop" width="0" y="100" height="2" visible="false" enabled="false" />
  121. <layer name="skin_thumbs" state="closed" url.html5="%$KRPANOPATH%js/scrollarea.js" direction="h" align="top" width="100%" height="100" zorder="1" onloaded="skin_updatescroll();" onscroll="skin_updatethumbscroll();" />
  122. </layer>
  123. </layer>
  124. </layer>
  125. </layer>
  126. <layer name="skin_splitter_bottom" type="container" align="bottom" width="100%" height="calc:skin_settings.controlbar_offset + skin_settings.controlbar_height - skin_settings.controlbar_overlap" y="0" maskchildren="true" onloaded="skin_calc_opened_closed();" zorder="2">
  127. <layer name="skin_control_bar_bg" type="container" align="bottom" width="get:skin_settings.controlbar_width" height="calc:skin_settings.controlbar_height + skin_settings.controlbar_overlap" x="0" y="get:skin_settings.controlbar_offset" bgcolor="get:skin_settings.design_bgcolor" bgalpha="get:skin_settings.design_bgalpha" bgborder="get:skin_settings.design_bgborder" bgroundedge="get:skin_settings.design_bgroundedge" bgshadow="get:skin_settings.design_bgshadow" />
  128. </layer>
  129. <layer name="skin_control_bar" type="container" align="bottom" width="get:skin_settings.controlbar_width" height="calc:skin_settings.controlbar_height" x="0" y="get:skin_settings.controlbar_offset" onloaded="skin_calc_opened_closed();" zorder="3">
  130. <layer name="skin_control_bar_buttons" type="container" align="leftbottom" width="100%" height="get:skin_settings.controlbar_height">
  131. <layer name="skin_btn_prev" style="skin_base|skin_glow" crop="0|64|64|64" align="left" x="5" y="0" scale="0.5" alpha="0.5" onclick="if(skin_settings.thumbs_loop, skin_nextscene_loop(-1), skin_nextscene(-1) );" />
  132. <layer name="skin_btn_thumbs" style="skin_base|skin_glow" crop="0|128|64|64" align="left" x="50" y="0" scale="0.5" ondown2="skin_showmap(false); skin_showthumbs();" />
  133. <layer name="skin_btn_map" style="skin_base|skin_glow" crop="64|128|64|64" align="left" x="90" y="0" scale="0.5" ondown2="skin_showthumbs(false); skin_showmap();" visible="false" />
  134. <layer name="skin_btn_navi" type="container" align="center" x="0" width="240" height="32">
  135. <layer name="skin_btn_left" style="skin_base|skin_glow" crop="0|192|64|64" align="center" x="-100" y="0" scale="0.5" ondown2="set(hlookat_moveforce,-1);" onup2="set(hlookat_moveforce,0);" />
  136. <layer name="skin_btn_right" style="skin_base|skin_glow" crop="64|192|64|64" align="center" x="-60" y="0" scale="0.5" ondown2="set(hlookat_moveforce,+1);" onup2="set(hlookat_moveforce,0);" />
  137. <layer name="skin_btn_up" style="skin_base|skin_glow" crop="0|256|64|64" align="center" x="-20" y="0" scale="0.5" ondown2="set(vlookat_moveforce,-1);" onup2="set(vlookat_moveforce,0);" />
  138. <layer name="skin_btn_down" style="skin_base|skin_glow" crop="64|256|64|64" align="center" x="+20" y="0" scale="0.5" ondown2="set(vlookat_moveforce,+1);" onup2="set(vlookat_moveforce,0);" />
  139. <layer name="skin_btn_in" style="skin_base|skin_glow" crop="0|320|64|64" align="center" x="+60" y="0" scale="0.5" ondown2="set(fov_moveforce,-1);" onup2="set(fov_moveforce,0);" />
  140. <layer name="skin_btn_out" style="skin_base|skin_glow" crop="64|320|64|64" align="center" x="+100" y="0" scale="0.5" ondown2="set(fov_moveforce,+1);" onup2="set(fov_moveforce,0);" />
  141. </layer>
  142. <layer name="skin_btn_vr" style="skin_base|skin_glow" crop="0|0|80|64" align="center" x="+146" y="0" scale="0.5" onclick="webvr.enterVR();" visible="false" />
  143. <!-- 全屏,暂时关闭,客户端需打开 -->
  144. <!-- <layer name="skin_btn_fs" style="skin_base|skin_glow" crop="0|576|64|64" align="right" x="90" y="0" scale="0.5" onclick="switch(fullscreen);" devices="fullscreensupport" /> -->
  145. <layer name="skin_btn_hide" style="skin_base|skin_glow" crop="0|448|64|64" align="right" x="50" y="0" scale="0.5" onclick="skin_hideskin()" />
  146. <layer name="skin_btn_show" type="container" bgcapture="true" align="bottom" width="100%" height="get:skin_settings.controlbar_height" y="calc:skin_settings.controlbar_height - skin_settings.controlbar_offset_closed" onclick="skin_showskin()" onhover="tween(alpha,1.0);" onout="tween(alpha,0.25);" ondown.touch="onhover();" onup.touch="onout();" visible="false" capture="false" alpha="0.0">
  147. <layer name="skin_btn_show_icon" style="skin_base" crop="64|448|64|64" scale="0.5" align="bottom" y="2" enabled="false" />
  148. </layer>
  149. <layer name="skin_btn_next" style="skin_base|skin_glow" crop="64|64|64|64" align="right" x="5" y="0" scale="0.5" alpha="0.5" onclick="if(skin_settings.thumbs_loop, skin_nextscene_loop(+1), skin_nextscene(+1) );" />
  150. </layer>
  151. </layer>
  152.  
  153. <layer name="skin_loadingtext" type="text" align="center" x="5" y="-5" html="get:skin_settings.loadingtext" visible="false" background="false" border="false" enabled="false" css="calc:skin_settings.design_text_css + ' text-align:center; font-style:italic; font-size:22px;'" textshadow="get:skin_settings.design_text_shadow" />
  154. <layer name="skin_buttonglow" style="skin_base" crop="64|384|64|64" align="center" x="0" y="1" scale="1.0" alpha="0.0" visible="false" enabled="false" />
  155. <!-- 缩略图选择边框效果 -->
  156. <layer name="skin_thumbborder" type="container" x="calc:skin_settings.design_thumbborder_padding + 3" y="calc:skin_settings.design_thumbborder_padding + 3" width="calc:skin_settings.thumbs_width - 2*skin_settings.design_thumbborder_padding" height="calc:skin_settings.thumbs_height - 2*skin_settings.design_thumbborder_padding" visible="true" enabled="false" align="lefttop" bgborder="get:skin_settings.design_thumbborder_bgborder" bgroundedge="get:skin_settings.design_thumbborder_bgroundedge" />
  157. </layer>
  158.  
  159. <!-- previous/next scene buttons for the hidden skin mode -->
  160. <layer name="skin_btn_prev_fs" keep="true" type="container" align="lefttop" x="-50" width="40" height="100%" bgcapture="true" alpha="0.25" capture="false" zorder="2" onclick="skin_nextscene_loop(-1);" onhover="tween(alpha,1.0);" onout="tween(alpha,0.25);" ondown.touch="onhover();" onup.touch="onout();">
  161. <layer name="skin_btn_prev_fs_icon" style="skin_base" crop="0|64|64|64" align="center" scale="0.5" enabled="false" />
  162. </layer>
  163. <layer name="skin_btn_next_fs" keep="true" type="container" align="righttop" x="-50" width="40" height="100%" bgcapture="true" alpha="0.25" capture="false" zorder="2" onclick="skin_nextscene_loop(+1);" onhover="tween(alpha,1.0);" onout="tween(alpha,0.25);" ondown.touch="onhover();" onup.touch="onout();">
  164. <layer name="skin_btn_next_fs_icon" style="skin_base" crop="64|64|64|64" align="center" scale="0.5" enabled="false" />
  165. </layer>
  166.  
  167. <!-- skin events -->
  168. <!-- 皮肤的事件
  169. onxmlcomplete XML加载完成后清除当前事件,调用第一个函数skin_startup
  170. onnewpano 加载新场景时skin_showloading显示加载中文字 skin_update_scene_infos 根据URL重新设定初始位置等信息
  171. onloadcomplete 加载完成后隐藏加载中文字
  172. onidle 空闲时执行URL的信息更新
  173. onresize 屏幕尺寸变化时执行一次skin_onresize,当每次加载新的pano时onresize也会被触发一次
  174. onenterfullscreen onexitfullscreen 进入退出全屏时更新全屏按钮的图标
  175. onkeydown 监听键盘事件-->
  176. <events name="skin_events" keep="true" onxmlcomplete="set(events[skin_events].onxmlcomplete,null); skin_startup();" onnewpano="skin_showloading(true); skin_update_scene_infos(); skin_deeplinking_update_url();" onremovepano="skin_showloading(true);" onloadcomplete="skin_showloading(false);" onidle="skin_deeplinking_update_url();" onresize="skin_onresize();" onenterfullscreen.fullscreensupport="set(layer[skin_btn_fs].crop, '64|576|64|64');" onexitfullscreen.fullscreensupport="set(layer[skin_btn_fs].crop, '0|576|64|64');" onkeydown="skin_keydown_event();" />
  177.  
  178. <!-- skin actions -->
  179. <!-- 当前皮肤的启动函数 -->
  180. <action name="skin_startup">
  181. <!-- apply skin settings on startup -->
  182. <!-- 根据设置确定缩略图是否在打开时就显示,并且设定是否可拖拽,鼠标的情况下设置为滚动 -->
  183. if(skin_settings.thumbs,
  184. if(skin_settings.thumbs_opened, set(layer[skin_thumbs].state,'opened'); set(layer[skin_thumbs_container].visible,true); );
  185. copy(layer[skin_thumbs].draggable, skin_settings.thumbs_dragging);
  186. if(skin_settings.thumbs_onhoverscrolling AND device.mouse,
  187. set(layer[skin_thumbs].draggable, false);
  188. set(layer[skin_thumbs].onhover_autoscrolling, true);
  189. );
  190. );
  191. if(skin_settings.littleplanetintro AND (device.webgl OR device.flash),
  192. skin_setup_littleplanetintro();
  193. );
  194. <!-- 增加缩略图 -->
  195. skin_addthumbs();
  196. <!-- 调用onresize -->
  197. skin_onresize();
  198. skin_updatescroll();
  199. <!-- 显示下方控制条 -->
  200. set(layer[skin_layer].visible, true);
  201. </action>
  202.  
  203. <!-- 增加缩略图 -->
  204. <action name="skin_addthumbs">
  205. if(skin_settings.thumbs == false,
  206. set(layer[skin_btn_thumbs].visible,false);
  207. ,
  208. copy(thumbwidth, skin_settings.thumbs_width);
  209. copy(thumbheight, skin_settings.thumbs_height);
  210. copy(thumbpadding, skin_settings.thumbs_padding);
  211. copy(thumbcrop, skin_settings.thumbs_crop);
  212. add(thumbxoffset, thumbwidth, thumbpadding);
  213. mul(thumbxcenter, thumbxoffset, 0.5);
  214. mul(thumbbarwidth, thumbxoffset, scene.count);
  215. add(thumbbarwidth, thumbpadding);
  216. add(thumbbarheight, thumbpadding, thumbheight);
  217. add(thumbbarheight, thumbpadding);
  218. if(skin_settings.thumbs_scrollindicator,
  219. copy(layer[skin_thumbs_scrollindicator].y, thumbbarheight);
  220. add(thumbbarheight, layer[skin_thumbs_scrollindicator].height);
  221. );
  222. copy(layer[skin_thumbs].height, thumbbarheight);
  223. copy(layer[skin_thumbs].width, thumbbarwidth);
  224. mul(halfheight, thumbbarheight, 0.5);
  225. copy(layer[skin_thumbs_scrollleft].y, halfheight);
  226. copy(layer[skin_thumbs_scrollright].y, halfheight);
  227. <!-- 遍历所有scene并且根据序号设置缩略图名称,并且根据设置添加缩略图文字 -->
  228. set(thumb_cnt,0);
  229. for(set(i,0), i LT scene.count, inc(i),
  230. inc(thumb_cnt);
  231. txtadd(thumbname,'skin_thumb_',get(i));
  232. addlayer(get(thumbname));
  233. copy(layer[get(thumbname)].url, scene[get(i)].thumburl);
  234. set(layer[get(thumbname)].keep, true);
  235. set(layer[get(thumbname)].parent, 'skin_thumbs');
  236. set(layer[get(thumbname)].align, lefttop);
  237. copy(layer[get(thumbname)].crop, thumbcrop);
  238. copy(layer[get(thumbname)].width, thumbwidth);
  239. copy(layer[get(thumbname)].height, thumbheight);
  240. mul(thumbx, i, thumbxoffset);
  241. add(thumbx, thumbpadding);
  242. copy(layer[get(thumbname)].x, thumbx);
  243. copy(layer[get(thumbname)].y, thumbpadding);
  244. add(scene[get(i)].thumbx, thumbx, thumbxcenter);
  245. copy(scene[get(i)].thumby, thumbpadding);
  246. set(layer[get(thumbname)].linkedscene, get(scene[get(i)].name) );
  247. set(layer[get(thumbname)].onclick, copy(layer[skin_thumbborder].parent, name); skin_loadscene(get(linkedscene),get(skin_settings.loadscene_blend)); );
  248. if(skin_settings.tooltips_thumbs,
  249. set(layer[get(thumbname)].tooltip, get(scene[get(i)].title) );
  250. layer[get(thumbname)].loadstyle(skin_tooltips);
  251. );
  252. if(skin_settings.thumbs_text,
  253. txtadd(thumbtext, 'skin_thumbtext_', get(i));
  254. addlayer(get(thumbtext));
  255. layer[get(thumbtext)].loadstyle(skin_thumbtext_style);
  256. set(layer[get(thumbtext)].keep, true);
  257. set(layer[get(thumbtext)].parent, get(thumbname));
  258. set(layer[get(thumbtext)].html, get(scene[get(i)].title));
  259. );
  260. );
  261. if(thumb_cnt == 1,
  262. set(layer[skin_thumbs].align, 'lefttop');
  263. );
  264. );
  265. </action>
  266.  
  267.  
  268. <action name="skin_addmapspots">
  269. for(set(i,0), i LT scene.count, inc(i),
  270. if(scene[get(i)].lat,
  271. txtadd(spotname, 'spot', get(i));
  272. txtadd(spotclickevent, 'skin_hidetooltips(); activatespot(',get(spotname),'); skin_loadscene(', get(scene[get(i)].name), ',get(skin_settings.loadscene_blend)); skin_updatescroll(); delayedcall(0.5,skin_showmap(false));');
  273. copy(scene[get(i)].mapspotname, spotname);
  274. addspot(get(spotname), get(scene[get(i)].lat), get(scene[get(i)].lng), get(scene[get(i)].heading), false, get(spotclickevent), null);
  275. if(skin_settings.tooltips_mapspots,
  276. set(layer[skin_map].spot[get(spotname)].tooltip, get(scene[get(i)].title) );
  277. txtadd(layer[skin_map].spot[get(spotname)].onover, 'set(hovering,true);', get(style[skin_tooltips].onover) );
  278. txtadd(layer[skin_map].spot[get(spotname)].onout, 'set(hovering,false);', get(style[skin_tooltips].onout) );
  279. );
  280. );
  281. );
  282. if(xml.scene != null,
  283. activatespot( get(scene[get(xml.scene)].mapspotname) );
  284. ,
  285. activatespot(spot0);
  286. );
  287. <!-- zoom and pan the map to see all spots at the same time -->
  288. zoomToSpotsExtent();
  289. </action>
  290.  
  291.  
  292. <action name="skin_setup_littleplanetintro">
  293. copy(lp_scene, xml.scene);
  294. copy(lp_hlookat, view.hlookat);
  295. copy(lp_vlookat, view.vlookat);
  296. copy(lp_fov, view.fov);
  297. copy(lp_fovmax, view.fovmax);
  298. copy(lp_limitview, view.limitview);
  299. set(view.fovmax, 170);
  300. set(view.limitview, lookto);
  301. set(view.vlookatmin, 90);
  302. set(view.vlookatmax, 90);
  303. lookat(calc(lp_hlookat - 180), 90, 150, 1, 0, 0);
  304. set(events[lp_events].onloadcomplete,
  305. delayedcall(0.5,
  306. if(lp_scene === xml.scene,
  307. set(control.usercontrol, off);
  308. copy(view.limitview, lp_limitview);
  309. set(view.vlookatmin, null);
  310. set(view.vlookatmax, null);
  311. tween(view.hlookat|view.vlookat|view.fov|view.distortion, calc('' + lp_hlookat + '|' + lp_vlookat + '|' + lp_fov + '|' + 0.0),
  312. 3.0, easeOutQuad,
  313. set(control.usercontrol, all);
  314. tween(view.fovmax, get(lp_fovmax));
  315. );
  316. );
  317. );
  318. );
  319. </action>
  320.  
  321.  
  322. <action name="skin_lookat">
  323. if(webvr.isenabled,
  324. <!-- adjust the VR prev/next hotspots for the view change -->
  325. calc(hlookat_offset, %1 - view.hlookat);
  326. add(hotspot[webvr_prev_scene].ath, hlookat_offset);
  327. add(hotspot[webvr_next_scene].ath, hlookat_offset);
  328. );
  329. <!-- change the view -->
  330. lookat(%1, %2, %3);
  331. </action>
  332.  
  333. <!-- 皮肤重置位置 -->
  334. <action name="skin_onresize">
  335. mul(mh, area.pixelheight, -1);
  336. if(layer[skin_thumbs].state == 'opened', add(mh,layer[skin_thumbs].height); );
  337. if(layer[skin_map].state == 'opened', sub(hh,area.pixelheight,skin_settings.controlbar_offset); sub(hh,layer[skin_control_bar].height); sub(hh,32); add(mh,hh); add(mh,skin_settings.controlbar_overlap); sub(mh, layer[skin_scroll_layer].y_offset); copy(layer[skin_map].height, hh); );
  338. add(mh, layer[skin_scroll_layer].y_offset);
  339. set(layer[skin_scroll_layer].y, get(mh));
  340. skin_video_updateseekbarwidth();
  341. skin_arrange_buttons();
  342. </action>
  343.  
  344.  
  345. <!-- determine the visibility of the buttons and calculate their positions -->
  346. <action name="skin_arrange_buttons">
  347. calc(show_selbuttons, scene.count GT 1);
  348. calc(show_thumbutton, skin_settings.thumbs == true);
  349. calc(show_mapbutton, skin_settings.maps == true);
  350. calc(show_vrbutton, webvr.isavailable == true);
  351. calc(show_fsbutton, device.fullscreensupport == true);
  352. set(lpos,6);
  353. set(cpos,0);
  354. if(show_gyrobutton, dec(cpos,20));
  355. if(show_vrbutton, dec(cpos,24));
  356. set(rpos,6);
  357. calc(show_dirbuttons, !device.mobile AND ((area.pixelwidth + 2*cpos) GT 520));
  358. copy(layer[skin_btn_navi].visible, show_dirbuttons);
  359. copy(layer[skin_btn_prev].visible, show_selbuttons);
  360. copy(layer[skin_btn_next].visible, show_selbuttons);
  361. if(show_selbuttons, inc(lpos,44); inc(rpos,44); );
  362. copy(layer[skin_btn_thumbs].visible, show_thumbutton);
  363. copy(layer[skin_btn_thumbs].x, lpos);
  364. if(show_thumbutton, inc(lpos,40));
  365. copy(layer[skin_btn_map].visible, show_mapbutton);
  366. copy(layer[skin_btn_map].x, lpos);
  367. if(show_mapbutton, inc(lpos,40));
  368. if(show_dirbuttons,
  369. copy(layer[skin_btn_navi].x, cpos);
  370. inc(cpos,140);
  371. set(layer[skin_btn_gyro].align, center);
  372. copy(layer[skin_btn_gyro].visible, show_gyrobutton);
  373. copy(layer[skin_btn_gyro].x, cpos);
  374. if(show_gyrobutton, inc(cpos,48));
  375. set(layer[skin_btn_vr].align, center);
  376. copy(layer[skin_btn_vr].visible, show_vrbutton);
  377. copy(layer[skin_btn_vr].x, cpos);
  378. if(show_vrbutton, inc(cpos,80));
  379. ,
  380. set(layer[skin_btn_gyro].align, left);
  381. copy(layer[skin_btn_gyro].visible, show_gyrobutton);
  382. copy(layer[skin_btn_gyro].x, lpos);
  383. if(show_gyrobutton, inc(lpos,40));
  384. set(layer[skin_btn_vr].align, left);
  385. copy(layer[skin_btn_vr].visible, show_vrbutton);
  386. copy(layer[skin_btn_vr].x, lpos);
  387. if(show_vrbutton, inc(lpos,80));
  388. );
  389. copy(layer[skin_btn_hide].x, rpos);
  390. inc(rpos,40);
  391. copy(layer[skin_btn_fs].visible, show_fsbutton);
  392. copy(layer[skin_btn_fs].x, rpos);
  393. if(show_fsbutton, inc(rpos,40));
  394. </action>
  395.  
  396. <!-- 将当前的scene缩略图设置到正中央 -->
  397. <action name="skin_updatescroll">
  398. if(layer[skin_thumbs].loaded,
  399. set(cursceneindex, 0);
  400. if(xml.scene, copy(cursceneindex, scene[get(xml.scene)].index));
  401. layer[skin_thumbs].setcenter(get(scene[get(cursceneindex)].thumbx), get(scene[get(cursceneindex)].thumby));
  402. );
  403. <!-- 设置当前场景的缩略图为选中式样 -->
  404. txtadd(parentname, 'skin_thumb_', get(scene[get(xml.scene)].index));
  405. if(layer[get(parentname)],
  406. set(layer[skin_thumbborder].parent, get(parentname));
  407. set(layer[skin_thumbborder].visible, true);
  408. ,
  409. set(layer[skin_thumbborder].visible, false);
  410. );
  411. </action>
  412.  
  413.  
  414. <action name="skin_updatethumbscroll">
  415. copy(padding,skin_settings.thumbs_padding);
  416. if(skin_settings.thumbs_scrollbuttons,
  417. if(loverflow GT 0, set(layer[skin_thumbs_scrollleft].visible,true), set(layer[skin_thumbs_scrollleft].visible,false) );
  418. if(roverflow GT 0, set(layer[skin_thumbs_scrollright].visible,true), set(layer[skin_thumbs_scrollright].visible,false) );
  419. );
  420. if(skin_settings.thumbs_scrollindicator,
  421. if(woverflow GT 0,
  422. set(layer[skin_thumbs_scrollindicator].visible,true);
  423. sub(iw,pixelwidth,woverflow);
  424. div(pw,iw,pixelwidth);
  425. div(px,loverflow,woverflow);
  426. mul(pw,iw);
  427. copy(layer[skin_thumbs_scrollindicator].width,pw);
  428. sub(iw,pw);
  429. sub(iw,padding);
  430. sub(iw,padding);
  431. mul(px,iw);
  432. add(px,padding);
  433. copy(layer[skin_thumbs_scrollindicator].x,px);
  434. ,
  435. set(layer[skin_thumbs_scrollindicator].visible,false);
  436. );
  437. );
  438. </action>
  439.  
  440.  
  441. <!-- 更新场景信息 -->
  442. <action name="skin_update_scene_infos">
  443. if(xml.scene !== null AND scene[get(xml.scene)].index GE 0,
  444. <!-- 设置场景名称 -->
  445. if(skin_settings.title,
  446. if(title, txtadd(layer[skin_title].html, get(title), ' - ', get(scene[get(xml.scene)].title) ); , copy(layer[skin_title].html, scene[get(xml.scene)].title ); );
  447. delayedcall(0.1, set(layer[skin_title].visible,true) );
  448. );
  449. <!-- 如果不循环根据当前场景的序号设置切换按钮显示 -->
  450. if(skin_settings.thumbs_loop == false,
  451. if(scene[get(xml.scene)].index GT 0,
  452. set(layer[skin_btn_prev].enabled, true);
  453. set(layer[skin_btn_prev].alpha, 1.0);
  454. ,
  455. set(layer[skin_btn_prev].enabled, false);
  456. set(layer[skin_btn_prev].alpha, 0.3);
  457. );
  458. sub(lastsceneindex, scene.count, 1);
  459. if(scene[get(xml.scene)].index LT lastsceneindex,
  460. set(layer[skin_btn_next].enabled, true);
  461. set(layer[skin_btn_next].alpha, 1.0);
  462. ,
  463. set(layer[skin_btn_next].enabled, false);
  464. set(layer[skin_btn_next].alpha, 0.3);
  465. );
  466. ,
  467. if(scene.count GT 1,
  468. set(layer[skin_btn_prev].enabled, true);
  469. set(layer[skin_btn_prev].alpha, 1.0);
  470. set(layer[skin_btn_next].enabled, true);
  471. set(layer[skin_btn_next].alpha, 1.0);
  472. ,
  473. set(layer[skin_btn_prev].enabled, false);
  474. set(layer[skin_btn_prev].alpha, 0.3);
  475. set(layer[skin_btn_next].enabled, false);
  476. set(layer[skin_btn_next].alpha, 0.3);
  477. );
  478. );
  479. if(scene.count GT 1,
  480. set(layer[skin_btn_prev_fs].visible, true);
  481. set(layer[skin_btn_next_fs].visible, true);
  482. ,
  483. set(layer[skin_btn_prev_fs].visible, false);
  484. set(layer[skin_btn_next_fs].visible, false);
  485. );
  486. <!-- 设置当前场景的缩略图为选中式样 -->
  487. txtadd(parentname, 'skin_thumb_', get(scene[get(xml.scene)].index));
  488. if(layer[get(parentname)],
  489. set(layer[skin_thumbborder].parent, get(parentname));
  490. set(layer[skin_thumbborder].visible, true);
  491. ,
  492. set(layer[skin_thumbborder].visible, false);
  493. );
  494. );
  495. </action>
  496.  
  497. <action name="skin_gotoscene">
  498. if(scene[%1],
  499. copy(cursceneindex, scene[get(xml.scene)].index);
  500. copy(newsceneindex, scene[%1].index);
  501. skin_loadscene(get(newsceneindex), calc(newsceneindex LT cursceneindex ? skin_settings.loadscene_blend_prev : (newsceneindex GT cursceneindex ? skin_settings.loadscene_blend_next : skin_settings.loadscene_blend)) );
  502. );
  503. </action>
  504.  
  505.  
  506. <action name="skin_nextscene">
  507. add(newsceneindex, scene[get(xml.scene)].index, %1);
  508. if(newsceneindex GE 0 AND newsceneindex LT scene.count,
  509. skin_loadscene(get(newsceneindex), calc(%1 LT 0 ? skin_settings.loadscene_blend_prev : skin_settings.loadscene_blend_next));
  510. );
  511. </action>
  512.  
  513.  
  514. <action name="skin_nextscene_loop">
  515. add(newsceneindex, scene[get(xml.scene)].index, %1);
  516. sub(lastsceneindex, scene.count, 1);
  517. if(newsceneindex LT 0, copy(newsceneindex,lastsceneindex));
  518. if(newsceneindex GT lastsceneindex, set(newsceneindex,0));
  519. skin_loadscene(get(newsceneindex), calc(%1 LT 0 ? skin_settings.loadscene_blend_prev : skin_settings.loadscene_blend_next));
  520. </action>
  521.  
  522.  
  523. <!-- skin_loadscene(scenenameorindex, blendmode) -->
  524. <action name="skin_loadscene">
  525. if(webvr.isenabled AND scene.count GT 1,
  526. set(hotspot[webvr_prev_scene].visible, false);
  527. set(hotspot[webvr_next_scene].visible, false);
  528. );
  529. txtadd(layer[skin_thumbborder].parent, 'skin_thumb_', get(scene[%1].index));
  530. layer[skin_thumbs].scrolltocenter(get(scene[%1].thumbx), get(scene[%1].thumby));
  531. loadscene(get(scene[%1].name), null, get(skin_settings.loadscene_flags), %2);
  532. </action>
  533.  
  534.  
  535. <action name="skin_showloading">
  536. if(display.stereo == true,
  537. set(layer[skin_loadingtext].visible, false);
  538. ,
  539. set(layer[skin_loadingtext].visible, %1);
  540. );
  541. </action>
  542.  
  543.  
  544. <action name="skin_hidetooltips">
  545. set(layer[skin_tooltip].alpha,0.0);
  546. set(layer[skin_tooltip].visible,false);
  547. </action>
  548.  
  549.  
  550. <action name="skin_buttonglow">
  551. if('%1' !== 'null',
  552. set(strength,0.7);
  553. if(%2 != null, set(strength,%2));
  554. set(layer[skin_buttonglow].parent, %1);
  555. set(layer[skin_buttonglow].visible, true);
  556. tween(layer[skin_buttonglow].alpha, get(strength), 0.07);
  557. ,
  558. tween(layer[skin_buttonglow].alpha, 0.0, 0.1, default,
  559. set(layer[skin_buttonglow].parent, null);
  560. set(layer[skin_buttonglow].visible, false);
  561. );
  562. );
  563. </action>
  564.  
  565.  
  566. <action name="skin_calc_opened_closed">
  567. if(layer[get(name)].y_closed === null,
  568. set(layer[get(name)].y_opened, get(layer[get(name)].y));
  569. set(layer[get(name)].y_closed, calc(layer[get(name)].y - skin_settings.controlbar_offset - skin_settings.controlbar_height + skin_settings.controlbar_offset_closed));
  570. );
  571. </action>
  572.  
  573.  
  574. <action name="skin_hideskin">
  575. callwith(layer[skin_scroll_window], skin_calc_opened_closed() );
  576. callwith(layer[skin_splitter_bottom], skin_calc_opened_closed() );
  577. callwith(layer[skin_control_bar], skin_calc_opened_closed() );
  578. if(layer[skin_map].state != 'closed', skin_showmap(false); wait(0.40); );
  579. if(layer[skin_thumbs].state != 'closed', skin_showthumbs(false); wait(0.25); );
  580. set(hidetime, calc('%1' == 'instant' ? 0.0 : 0.5));
  581. tween(layer[skin_scroll_window].y, get(layer[skin_scroll_window ].y_closed), get(hidetime));
  582. tween(layer[skin_splitter_bottom].y, get(layer[skin_splitter_bottom].y_closed), get(hidetime));
  583. tween(layer[skin_control_bar].y, get(layer[skin_control_bar ].y_closed), get(hidetime));
  584. tween(layer[skin_btn_prev_fs].x, 0, get(hidetime));
  585. tween(layer[skin_btn_next_fs].x, 0, get(hidetime));
  586. if(layer[skin_logo], tween(layer[skin_logo].alpha, 0.0, 0.5, default, set(layer[skin_logo].visible,false)); );
  587. stopdelayedcall(skin_btn_show_alpha);
  588. set(layer[skin_btn_show].visible, true);
  589. delayedcall(skin_btn_show_alpha, get(hidetime), tween(layer[skin_btn_show].alpha, 0.25, 0.25); );
  590. </action>
  591.  
  592.  
  593. <action name="skin_showskin">
  594. tween(layer[skin_scroll_window ].y, get(layer[skin_scroll_window ].y_opened));
  595. tween(layer[skin_splitter_bottom].y, get(layer[skin_splitter_bottom].y_opened));
  596. tween(layer[skin_control_bar ].y, get(layer[skin_control_bar ].y_opened));
  597. tween(layer[skin_btn_prev_fs].x, -50);
  598. tween(layer[skin_btn_next_fs].x, -50);
  599. if(layer[skin_logo], set(layer[skin_logo].visible,true); tween(layer[skin_logo].alpha, 1.0); );
  600. stopdelayedcall(skin_btn_show_alpha);
  601. set(layer[skin_btn_show].visible, false);
  602. delayedcall(skin_btn_show_alpha, 0.25, tween(layer[skin_btn_show].alpha, 0.0, 0.0); );
  603. </action>
  604.  
  605.  
  606. <action name="skin_showthumbs">
  607. if(%1 == null, if(layer[skin_thumbs].state == 'closed', set(show,true), set(show,false)); , set(show,%1); );
  608. mul(mh, layer[skin_scroll_layer].pixelheight, -1);
  609. if(show,
  610. set(layer[skin_thumbs].state, 'opened');
  611. tween(layer[skin_thumbs].alpha, 1.0, 0.25);
  612. add(mh, layer[skin_thumbs].height);
  613. add(mh, layer[skin_scroll_layer].y_offset);
  614. tween(layer[skin_scroll_layer].y, get(mh), 0.5, easeOutQuint);
  615. set(layer[skin_thumbs_container].visible, true);
  616. tween(layer[skin_thumbs_container].alpha, 1.0, 0.25);
  617. tween(layer[skin_map].alpha, 0.0, 0.25, default, set(layer[skin_map].visible,false));
  618. ,
  619. set(layer[skin_thumbs].state, 'closed');
  620. tween(layer[skin_thumbs].alpha, 0.0, 0.25, easeOutQuint);
  621. add(mh, layer[skin_scroll_layer].y_offset);
  622. tween(layer[skin_scroll_layer].y, get(mh), 0.5, easeOutQuint, set(layer[skin_thumbs_container].visible, false););
  623. );
  624. </action>
  625.  
  626.  
  627. <action name="skin_showmap">
  628. if(%1 == null, if(layer[skin_map].state == 'closed', set(show,true), set(show,false)); , set(show,%1); );
  629. mul(mh, layer[skin_scroll_layer].pixelheight, -1);
  630. if(show,
  631. tween(layer[skin_thumbs_container].alpha, 0.0, 0.25, default, set(layer[skin_thumbs_container].visible,false));
  632. set(layer[skin_map].visible, true);
  633. tween(layer[skin_map].alpha, 1.0, 0.25);
  634. set(layer[skin_map].state, 'opened');
  635. sub(hh,area.pixelheight,skin_settings.controlbar_offset);
  636. sub(hh,layer[skin_control_bar].height);
  637. sub(hh,32);
  638. add(mh,hh);
  639. sub(hh,skin_settings.controlbar_overlap);
  640. copy(layer[skin_map].height, hh);
  641. tween(layer[skin_scroll_layer].y, get(mh), 0.5, easeOutQuint);
  642. ,
  643. if(layer[skin_map].state != 'closed',
  644. set(layer[skin_map].state, 'closed');
  645. add(mh, layer[skin_scroll_layer].y_offset);
  646. tween(layer[skin_map].alpha, 0.0, 0.5, easeOutQuint);
  647. tween(layer[skin_scroll_layer].y, get(mh), 0.5, easeOutQuint, set(layer[skin_map].visible,false) );
  648. );
  649. );
  650. </action>
  651.  
  652.  
  653. <action name="skin_keydown_event">
  654. if(keycode == 33, skin_nextscene_loop(-1) );
  655. <!-- Page Up - previous scene -->
  656. if(keycode == 34, skin_nextscene_loop(+1) );
  657. <!-- Page Dowm - next scene -->
  658. if(keycode == 35, skin_gotoscene(calc(scene.count-1)) );
  659. <!-- End - last scene -->
  660. if(keycode == 36, skin_gotoscene(0) );
  661. <!-- Home/Pos1 - first scene -->
  662. </action>
  663.  
  664.  
  665. <action name="skin_deeplinking_update_url">
  666. if(skin_settings.deeplinking AND (!webvr OR webvr.isenabled === false),
  667. delayedcall(skin_deeplinking_update, calc(%1 == null ? 0.1 : %1), skin_deeplinking_update_url_process() );
  668. );
  669. </action>
  670.  
  671. <action name="skin_deeplinking_update_url_process">
  672. copy(adr, browser.location);
  673. indexoftxt(qi, get(adr), '?');
  674. if(qi GT 0, subtxt(adr, adr, 0, get(qi)));
  675. copy(si, scene[get(xml.scene)].index);
  676. copy(h, view.hlookat);
  677. copy(v, view.vlookat);
  678. copy(f, view.fov);
  679. copy(d, view.distortion);
  680. copy(a, view.architectural);
  681. clamp(d, 0.0, 1.0);
  682. clamp(a, 0.0, 1.0);
  683. set(pp, calc(f LT 10 ? 6 : 2));
  684. roundval(h, get(pp));
  685. roundval(v, get(pp));
  686. roundval(f, get(pp));
  687. roundval(d, 2);
  688. roundval(a, 1);
  689. set(adr, calc(adr + '?startscene=' + si + '&amp;startactions=lookat('+h+','+v+','+f+','+d+','+a+');'));
  690. js( history.replaceState(null, document.title, get(adr)); );
  691. </action>
  692.  
  693.  
  694. <!-- reload the scene when there is a special image for VR -->
  695. <action name="skin_reloadscene_webvr">
  696. delayedcall(0.1,
  697. if(scene[get(xml.scene)].havevrimage,
  698. copy(keeplookingdirection_backup, skin_settings.webvr_gyro_keeplookingdirection);
  699. set(skin_settings.webvr_gyro_keeplookingdirection, true);
  700. loadscene(get(xml.scene), null, MERGE|KEEPVIEW|KEEPMOVING|KEEPPLUGINS|KEEPHOTSPOTS|NOPREVIEW, BLEND(0.5));
  701. copy(skin_settings.webvr_gyro_keeplookingdirection, keeplookingdirection_backup);
  702. delete(keeplookingdirection_backup);
  703. );
  704. );
  705. </action>
  706.  
  707. <action name="skin_video_removecontrols">
  708. stopdelayedcall(skin_video_delayedvisible);
  709. set(events[skin_events].onclick, null);
  710. set(layer[skin_video_playpause].alpha, 0.0);
  711. set(layer[skin_video_controls].visible, false);
  712. clearinterval(skin_video_seek_updates);
  713. </action>
  714.  
  715. <action name="skin_video_updateseekbarwidth">
  716. if(skin_settings.title,
  717. calc(layer[skin_video_seekbar_container].width, 0 - (32 + layer[skin_title].pixelwidth + layer[skin_video_time].pixelwidth));
  718. calc(layer[skin_video_seekbar_container].x, layer[skin_title].pixelwidth + 16);
  719. ,
  720. calc(layer[skin_video_seekbar_container].width, 0 - (24 + layer[skin_video_time].pixelwidth));
  721. set(layer[skin_video_seekbar_container].x, 8);
  722. );
  723. </action>
  724.  
  725. <layer name="skin_video_playpause" keep="true" style="skin_base|skin_glow" crop="0|640|64|64" scale="0.75" align="center" alpha="0.0" autoalpha="true" state="hidden" onclick="skin_video_playpause_click();" />
  726.  
  727.  
  728. <!-- context menu - http://krpano.com/docu/xml/#contextmenu -->
  729. <contextmenu>
  730. <item name="kr" caption="KRPANO" />
  731. <item name="fs" caption="FULLSCREEN" />
  732. <item name="cc" caption="Change Controlmode" onclick="skin_changecontrolmode();" separator="true" />
  733. <item name="nv" caption="Normal View" onclick="skin_view_normal();" showif="view.vlookatrange == 180" separator="true" />
  734. <item name="fv" caption="Fisheye View" onclick="skin_view_fisheye();" showif="view.vlookatrange == 180" devices="flash|webgl" />
  735. <item name="sv" caption="Stereographic View" onclick="skin_view_stereographic();" showif="view.vlookatrange == 180" devices="flash|webgl" />
  736. <item name="av" caption="Architectural View" onclick="skin_view_architectural();" showif="view.vlookatrange == 180" />
  737. <item name="pv" caption="Pannini View" onclick="skin_view_pannini();" showif="view.vlookatrange == 180" devices="flash|webgl" />
  738. <item name="lp" caption="Little Planet View" onclick="skin_view_littleplanet();" showif="view.vlookatrange == 180" devices="flash|webgl" />
  739. </contextmenu>
  740.  
  741.  
  742. <action name="skin_changecontrolmode">
  743. switch(control.mouse, moveto, drag);
  744. switch(control.touch, moveto, drag);
  745. </action>
  746.  
  747. <action name="skin_view_look_straight">
  748. if(view.vlookat LT -80 OR view.vlookat GT +80,
  749. tween(view.vlookat, 0.0, 1.0, easeInOutSine);
  750. tween(view.fov, 100, distance(150,0.8));
  751. );
  752. skin_deeplinking_update_url(1.0);
  753. </action>
  754.  
  755. <action name="skin_view_normal">
  756. skin_view_look_straight();
  757. tween(view.architectural, 0.0, distance(1.0,0.5));
  758. tween(view.pannini, 0.0, distance(1.0,0.5));
  759. tween(view.distortion, 0.0, distance(1.0,0.5));
  760. </action>
  761.  
  762. <action name="skin_view_fisheye">
  763. skin_view_look_straight();
  764. tween(view.architectural, 0.0, distance(1.0,0.5));
  765. tween(view.pannini, 0.0, distance(1.0,0.5));
  766. tween(view.distortion, 0.35, distance(1.0,0.5));
  767. </action>
  768.  
  769. <action name="skin_view_architectural">
  770. skin_view_look_straight();
  771. tween(view.architectural, 1.0, distance(1.0,0.5));
  772. tween(view.pannini, 0.0, distance(1.0,0.5));
  773. tween(view.distortion, 0.0, distance(1.0,0.5));
  774. </action>
  775.  
  776. <action name="skin_view_stereographic">
  777. skin_view_look_straight();
  778. tween(view.architectural, 0.0, distance(1.0,0.5));
  779. tween(view.pannini, 0.0, distance(1.0,0.5));
  780. tween(view.distortion, 1.0, distance(1.0,0.8));
  781. </action>
  782.  
  783. <action name="skin_view_pannini">
  784. skin_view_look_straight();
  785. tween(view.architectural, 0.0, distance(1.0,0.5));
  786. tween(view.pannini, 1.0, distance(1.0,0.8));
  787. if(view.distortion LT 0.1,
  788. tween(view.distortion, 1.0, distance(1.0,0.8));
  789. );
  790. </action>
  791.  
  792. <action name="skin_view_littleplanet">
  793. tween(view.architectural, 0.0, distance(1.0,0.5));
  794. tween(view.pannini, 0.0, distance(1.0,0.5));
  795. tween(view.distortion, 1.0, distance(1.0,0.8));
  796. tween(view.fov, 150, distance(150,0.8));
  797. tween(view.vlookat, 90, distance(100,0.8));
  798. add(new_hlookat, view.hlookat, 123.0);
  799. tween(view.hlookat, get(new_hlookat), distance(100,0.8));
  800. skin_deeplinking_update_url(1.0);
  801. </action>
  802.  
  803. </krpano>

这一段代码是主要写怎么生成对应的xml文件,也就是新增和编辑功能,以及一下全景图视角和缩放比例的设置

  1. <template>
  2. <AModal
  3. class="div-scene-edit"
  4. :title="info.title"
  5. :footer="null"
  6. :visible="info.visible"
  7. @cancel="handleCancelVisible"
  8. width="40%"
  9. >
  10. <a-form-model ref="refFormScene" :model="formData" :label-col="labelCol" :wrapper-col="wrapperCol">
  11. <a-form-model-item
  12. label="场景名称"
  13. prop="sceneName"
  14. :rules="[{ required: true, validator: validateName, trigger: 'change' }]"
  15. >
  16. <a-input v-model="formData.sceneName" placeholder="全景图场景名称,中英文、数字,不要使用特殊字符" />
  17. </a-form-model-item>
  18. <a-form-model-item label="场景序号" prop="orderSeq" :rules="[{ required: true }]">
  19. <a-input v-model="formData.orderSeq" placeholder="请输入当前场景序号" />
  20. </a-form-model-item>
  21. <a-form-model-item label="全景图上传" extra="球形全景图:上传方便,长宽比=2:1" :rules="[{ required: true }]">
  22. <template>
  23. <a-upload
  24. :file-list="fileData.fileList"
  25. listType="picture-card"
  26. :action="fileData.uploadImg"
  27. :headers="fileData.headers"
  28. :transformFile="handleTransformFile"
  29. @preview="handlePreviewImg"
  30. @change="handleChangeImg"
  31. >
  32. <div v-if="fileData.fileList.length === 0">
  33. <a-icon type="plus" />
  34. <div class="ant-upload-text">点击上传</div>
  35. </div>
  36. </a-upload>
  37. <a v-if="formData.sceneType == 'SPHERE'" href="javascript:;" @click="handleCutImg">切图</a>
  38. </template>
  39. <a-modal :visible="fileData.visible" :footer="null" @cancel="handleCancelPreviewImg">
  40. <img alt="example" style="width: 100%" :src="fileData.thumbUrl" />
  41. </a-modal>
  42. </a-form-model-item>
  43. <a-form-model-item label="初始视角(水平)" name="hlookat" :rules="[{ required: true }]">
  44. <a-input v-model:value="formData.hlookat" placeholder="水平方向视角" @focus="handleFocusAthAtv" />
  45. </a-form-model-item>
  46. <a-form-model-item label="初始视角(垂直)" name="vlookat" :rules="[{ required: true }]">
  47. <a-input v-model:value="formData.vlookat" placeholder="垂直方向视角" @focus="handleFocusAthAtv" />
  48. </a-form-model-item>
  49. <a-form-model-item label="初始缩放视角FOV" name="fov" :rules="[{ required: true }]">
  50. <a-input v-model:value="formData.fov" placeholder="初始缩放视角FOV,默认值:120" @focus="handleFocusAthAtv" />
  51. </a-form-model-item>
  52. <a-form-model-item label="缩放最小FOV" name="fovmin" :rules="[{ required: true }]">
  53. <a-input v-model:value="formData.fovmin" placeholder="缩放最小FOV(场景拉近),必须小于初始FOV" />
  54. </a-form-model-item>
  55. <a-form-model-item label="缩放最大FOV" name="fovmax" :rules="[{ required: true }]">
  56. <a-input v-model:value="formData.fovmax" placeholder="缩放最大FOV(场景拉远),必须大于初始FOV" />
  57. </a-form-model-item>
  58. <a-form-model-item class="div-scene-edit-foot">
  59. <AButton class="create-ant-btn" @click.prevent="handleCancel" :loading="isLoading">取消</AButton>
  60. <AButton type="primary" @click.prevent="handleSave" :loading="isLoading">保存</AButton>
  61. </a-form-model-item>
  62. </a-form-model>
  63. <AModal
  64. v-if="lookatInfo.visible"
  65. title="选取初始视角,请拖动至弹框中心"
  66. :footer="null"
  67. :visible="lookatInfo.visible"
  68. @cancel="handleCancelXMLVisible"
  69. width="80%"
  70. >
  71. <div id="pano" :style="{ width: `80vd`, height: `65vh` }"></div>
  72. <img class="btn-content-img" @click.prevent="handleSaveXMLLookat" src="~@/assets/introimage.png" />
  73. </AModal>
  74. </AModal>
  75. </template>
  76.  
  77. <script>
  78. import { getACCESS_TOKEN } from '@/utils/util'
  79. import { postAction, putAction, uploadAction } from '@/api/manage'
  80. import KrpanoToolJS from '@krpano/js-tools'
  81. export default {
  82. name: 'SceneEdit',
  83. props: {
  84. info: {
  85. type: Object,
  86. default: () => ({
  87. title: '场景新建',
  88. visible: false,
  89. }),
  90. },
  91. },
  92. data() {
  93. return {
  94. labelCol: { span: 6 },
  95. wrapperCol: { span: 14 },
  96. // 表单数据
  97. formData: {},
  98. fileData: {
  99. fileList: [],
  100. uploadImg: `${process.env.VUE_APP_API_BASE_URL}/pano/panoScene/uploadPanoImage/${this.info.monitorPointId}`,
  101. headers: { 'X-Access-Token': getACCESS_TOKEN() },
  102. thumbUrl: '',
  103. visible: false,
  104. },
  105. url: {
  106. list: '/bimModelUpdateRecord/bimModelUpdateRecord/bimList',
  107. },
  108. disableMixinCreated: true,
  109. isHotspot: false,
  110. sceneList: [],
  111. sceneName: '',
  112. lookatInfo: {
  113. visible: false,
  114. },
  115. isLoading: false,
  116. }
  117. },
  118. created() {
  119. this.formData = { ...this.info }
  120. if (this.formData.sceneId) {
  121. this.fileData.fileList = [
  122. {
  123. uid: '-1',
  124. name: 'image.png',
  125. status: 'done',
  126. url: this.info.sceneUrl,
  127. },
  128. ]
  129. }
  130. window['handleGetViewTohTov'] = this.handleGetViewTohTov
  131. },
  132. methods: {
  133. // 场景名称正则
  134. validateName(rule, value, callback) {
  135. if (value === '') {
  136. callback(new Error('请输入场景名称'))
  137. } else if (!/^[a-zA-Z0-9\u4e00-\u9fa5]+$/.test(value)) {
  138. callback(new Error('请输入中英文及数字'))
  139. } else {
  140. this.$refs.refFormScene.validateField('sceneName')
  141. callback()
  142. }
  143. },
  144. // 关闭弹框
  145. handleCancelVisible() {
  146. this.$emit('cancelVisible')
  147. },
  148. // 上传前先处理一下,调用切片方法
  149. handleTransformFile(file) {
  150. return new Promise((resolve) => {
  151. const krpanoTool = new KrpanoToolJS()
  152. krpanoTool
  153. .checkFile(file)
  154. .then(() => {
  155. krpanoTool.makeCube(file).then((result) => {
  156. resolve(result.content)
  157. })
  158. })
  159. .catch(() => {
  160. this.$message.error('图片需要小于20000*10000,建议图片大小不超过25MB')
  161. })
  162. })
  163. },
  164. // 上传完成后,图片信息改变
  165. handleChangeImg({ fileList }) {
  166. this.fileData.fileList = []
  167. fileList.forEach((item) => {
  168. if (item.response) {
  169. if (item.response.result) {
  170. this.formData.previewUrl = item.response.result.previewImageUrl
  171. this.formData.sceneUrl = item.response.result.thumbImageUrl
  172. this.formData.cubeUrl = item.response.result.panoWildcardUrl
  173. // 缩略图使用切片后的
  174. item.url = item.response.result.thumbImageUrl
  175. }
  176. }
  177. this.fileData.fileList.push(item)
  178. })
  179. },
  180. // 浏览大图
  181. handlePreviewImg(file) {
  182. this.fileData.thumbUrl = file.url || file.thumbUrl
  183. this.fileData.visible = true
  184. },
  185. // 关闭浏览大图
  186. handleCancelPreviewImg() {
  187. this.fileData.visible = false
  188. },
  189. handleCancel() {
  190. this.formData.previewUrl = ''
  191. this.formData.sceneUrl = ''
  192. this.$emit('cancelVisible')
  193. },
  194. // 场景创建或编辑
  195. handleSave() {
  196. this.$refs.refFormScene.validate((valid) => {
  197. if (!this.formData.previewUrl) {
  198. this.$message.warning('全景图不能为空')
  199. return
  200. }
  201. if (valid) {
  202. if (this.formData.sceneId) {
  203. putAction('/pano/panoScene/edit', {
  204. sceneId: this.formData.sceneId,
  205. previewUrl: this.formData.previewUrl,
  206. sceneUrl: this.formData.sceneUrl,
  207. cubeUrl: this.formData.cubeUrl,
  208. hotspotCount: 0,
  209. camroll: 1,
  210. fov: this.formData.fov,
  211. fovmin: this.formData.fovmin,
  212. fovmax: this.formData.fovmax,
  213. monitorPointId: this.formData.monitorPointId,
  214. sceneName: this.formData.sceneName,
  215. orderSeq: this.formData.orderSeq,
  216. hlookat: this.formData.hlookat,
  217. hlookatmin: -180,
  218. hlookatmax: 180,
  219. vlookat: this.formData.vlookat,
  220. vlookatmin: -90,
  221. vlookatmax: 90,
  222. fovtype: 'MFOV',
  223. sceneType: 'CUBE',
  224. })
  225. .then((res) => {
  226. if (res.success) {
  227. this.$message.success(res.message)
  228. } else {
  229. this.$message.warning(res.message)
  230. }
  231. })
  232. .finally(() => {
  233. this.$emit('cancelVisible', true)
  234. })
  235. } else {
  236. postAction('/pano/panoScene/add', {
  237. sceneCode: `scene${this.formData.orderSeq}`,
  238. previewUrl: this.formData.previewUrl,
  239. sceneUrl: this.formData.sceneUrl,
  240. cubeUrl: this.formData.cubeUrl,
  241. hotspotCount: 0,
  242. camroll: 1,
  243. fov: this.formData.fov,
  244. fovmin: this.formData.fovmin,
  245. fovmax: this.formData.fovmax,
  246. monitorPointId: this.formData.monitorPointId,
  247. sceneName: this.formData.sceneName,
  248. orderSeq: this.formData.orderSeq,
  249. hlookat: this.formData.hlookat,
  250. hlookatmin: -180,
  251. hlookatmax: 180,
  252. vlookat: this.formData.vlookat,
  253. vlookatmin: -90,
  254. vlookatmax: 90,
  255. fovtype: 'MFOV',
  256. sceneType: 'CUBE',
  257. })
  258. .then((res) => {
  259. if (res.success) {
  260. this.$message.success(res.message)
  261. } else {
  262. this.$message.warning(res.message)
  263. }
  264. })
  265. .finally(() => {
  266. this.$emit('cancelVisible', true)
  267. })
  268. }
  269. }
  270. })
  271. },
  272. // 获取初始化视角值
  273. handleFocusAthAtv() {
  274. const { previewUrl, sceneUrl, hlookat, vlookat, fov, fovmin, fovmax, cubeUrl } = this.formData
  275. if (!previewUrl) {
  276. this.$message.warning('全景图不能为空')
  277. return
  278. }
  279. this.lookatInfo.visible = true
  280. this.$nextTick(() => {
  281. window.embedpano({
  282. xml: 0,
  283. target: 'pano',
  284. html5: 'only',
  285. mobilescale: 1.0,
  286. passQueryParameters: 'startscene,startlookat',
  287. initvars: {
  288. KRPANOPATH: process.env.NODE_ENV === 'development' ? '/' : '',
  289. },
  290. })
  291. var krpano = document.getElementById('krpanoSWFObject')
  292. var tempXml = `<krpano version="1.20.7" onstart="loadscene(scene1);">
  293. <include url="template_action.xml" />
  294. <scene name="scene1" thumburl="${sceneUrl}" title="场景1">
  295. <view hlookat="${hlookat}" vlookat="${vlookat}" fovmin="${fovmin}" fovmax="${fovmax}" fov="${fov}" hlookatmin="-180" hlookatmax="180" vlookatmin="-90" vlookatmax="90" fovtype="MFOV" />
  296. <preview url="${previewUrl}"/>
  297. <image>
  298. <cube url="${cubeUrl}" />
  299. </image>
  300. </scene>
  301. </krpano>`
  302. // 如果是开发环境
  303. if (process.env.NODE_ENV === 'development') {
  304. window._CONFIG.krpanoPath = '/'
  305. }
  306. tempXml = tempXml.replaceAll(
  307. `url="template_action.xml"`,
  308. `url="${window._CONFIG.krpanoPath}template_action.xml"`
  309. )
  310. tempXml = tempXml.replaceAll(`url="vtourskin.xml"`, `url="${window._CONFIG.krpanoPath}vtourskin.xml"`)
  311. tempXml = tempXml.replaceAll(`url="images/`, `url="${window._CONFIG.krpanoPath}images/`)
  312. krpano.call(`loadxml(${tempXml})`)
  313. })
  314. },
  315. // 关闭xml
  316. handleCancelXMLVisible() {
  317. this.lookatInfo.visible = false
  318. window.removepano('pano')
  319. },
  320. // 保存当前xml值
  321. handleSaveXMLLookat() {
  322. var krpano = document.getElementById('krpanoSWFObject')
  323. krpano.call(`view_get_toh_tov()`)
  324. this.lookatInfo.visible = false
  325. window.removepano('pano')
  326. },
  327. // 获取当前视角的值
  328. handleGetViewTohTov(hlookat, vlookat, fov) {
  329. this.formData.hlookat = hlookat
  330. this.formData.vlookat = vlookat
  331. this.formData.fov = fov
  332. },
  333. // 切图
  334. handleCutImg() {
  335. this.isLoading = true
  336. this.getImageFileFromUrl(this.info.previewUrl, '图片.png', function (file) {
  337. const krpanoTool = new KrpanoToolJS()
  338. krpanoTool
  339. .checkFile(file)
  340. .then(() => {
  341. krpanoTool.makeCube(file).then((result) => {
  342. const fileData = new FormData()
  343. fileData.append('file', result.content)
  344. uploadAction(`/pano/panoScene/uploadPanoImage/${this.info.monitorPointId}`, fileData)
  345. .then((response) => {
  346. this.formData.previewUrl = response.result.previewImageUrl
  347. this.formData.sceneUrl = response.result.thumbImageUrl
  348. this.formData.cubeUrl = response.result.panoWildcardUrl
  349. })
  350. .finally(() => {
  351. this.isLoading = false
  352. })
  353. })
  354. })
  355. .catch(() => {
  356. this.$message.error('图片需要小于20000*10000,建议图片大小不超过25MB')
  357. })
  358. })
  359. },
  360. getImageFileFromUrl(url, imageName, callback) {
  361. var blob = null
  362. var xhr = new XMLHttpRequest()
  363. xhr.open('GET', url)
  364. xhr.setRequestHeader('Accept', 'image/jpeg')
  365. xhr.responseType = 'blob'
  366. xhr.onload = () => {
  367. if (xhr.status === 200) {
  368. blob = xhr.response
  369. let imgFile = new File([blob], imageName, { type: 'image/jpeg' })
  370. callback.call(this, imgFile)
  371. }
  372. }
  373. xhr.send()
  374. },
  375. },
  376. }
  377. </script>
  378. <style lang="less">
  379. .div-scene-edit {
  380. .ant-upload-text {
  381. color: #bfbfbf;
  382. }
  383. .anticon {
  384. color: #bfbfbf;
  385. }
  386. .ant-form-extra {
  387. color: #bfbfbf;
  388. }
  389. }
  390. .div-scene-edit-foot {
  391. display: flex;
  392. justify-content: flex-end;
  393. .create-ant-btn {
  394. margin-right: 10px;
  395. }
  396. }
  397. .btn-content-img {
  398. position: absolute;
  399. left: 0;
  400. right: 0;
  401. top: 0;
  402. bottom: 0;
  403. margin: auto;
  404. cursor: pointer;
  405. }
  406. </style>

后面再贴一下vue页面对应的代码

  1. <template>
  2. <transition name="scale" appear>
  3. <AnTaiModal
  4. v-model="visibles"
  5. @visibleMethod="handleCloseVisibleMethod"
  6. :title="panoramaTitle"
  7. :isCollapse="info.isMore"
  8. >
  9. <template slot="collapses">
  10. <TreeTemplate
  11. ref="refTree"
  12. modules=""
  13. colorsKey="releaseWarnLevel"
  14. :listData="xmlListRst"
  15. :defaultFilter="false"
  16. placeholder="请输入隐患点名称,编号"
  17. @switchActive="handleActiveeXml"
  18. @change="searchInputChange"
  19. />
  20. </template>
  21. <template slot="contents">
  22. <div class="div-krpano">
  23. <!-- 全景图 -->
  24. <div id="pano" :style="{ width: `${vw}%`, height: `${vh}%` }"></div>
  25. </div>
  26. </template>
  27. </AnTaiModal>
  28. </transition>
  29. </template>
  30.  
  31. <script>
  32. import { mapState, mapMutations } from 'vuex';
  33. import routeMixin from '@/mixins/routeMixin.js';
  34. import TreeTemplate from '@/components/_public/treeTemplate/treeTemplate';
  35. export default {
  36. // 全景图浏览弹框
  37. name: 'XmlPreview',
  38. components: {
  39. TreeTemplate
  40. },
  41. mixins: [routeMixin],
  42. props: {
  43. vw: {
  44. type: Number,
  45. default: 100
  46. },
  47. vh: {
  48. type: Number,
  49. default: 100
  50. }
  51. },
  52. computed: {
  53. ...mapState({
  54. info: state => state.common.xmlInfo
  55. })
  56. },
  57. data() {
  58. return {
  59. krpano: null,
  60. visibles: true,
  61. xmlListRst: [],
  62. panoramaTitle: '',
  63. routeLeaveShow: true
  64. };
  65. },
  66. beforeMount() {
  67. window['handleClickHotSpotsDevice'] = this.handleClickHotSpotsDevice;
  68. window['handleClickHotSpotsScene'] = this.handleClickHotSpotsScene;
  69. },
  70. created() {
  71. this.panoramaTitle = this.info.title;
  72. this.xmlListRst = this.info.xmlList.map(i => ({
  73. ...i,
  74. id: i.monitorPointId,
  75. key: i.monitorPointId,
  76. title: i.monitorPointName
  77. }));
  78. },
  79. mounted() {
  80. this.$nextTick(() => {
  81. window.embedpano({
  82. xml: 0,
  83. target: 'pano',
  84. html5: 'only',
  85. mobilescale: 1.0,
  86. passQueryParameters: 'startscene,startlookat',
  87. initvars: {
  88. KRPANOPATH: process.env.NODE_ENV === 'development' ? '/' : ''
  89. }
  90. });
  91. this.initKrpanoReady(this.info.panoSceneXml);
  92. });
  93. },
  94. methods: {
  95. ...mapMutations([
  96. 'SET_XMLVISIBLE',
  97. 'SET_DEVICEDETAILVISIBLE',
  98. 'SET_DEVICEDETAILTITLE',
  99. 'SET_METHODROUTEBEFORE',
  100. 'SET_HOSTID',
  101. 'SET_OBJTYPE'
  102. ]),
  103. // 初始化完成,展示xml数据,
  104. initKrpanoReady(tempXml, title) {
  105. this.krpano = document.getElementById('krpanoSWFObject');
  106. tempXml = tempXml.replaceAll(`ondown="hotspot_drag();"`, '');
  107. // 如果是开发环境
  108. if (process.env.NODE_ENV === 'development') {
  109. window._CONFIG.krpanoPath = '/';
  110. }
  111. tempXml = tempXml.replaceAll(
  112. `url="template_action.xml"`,
  113. `url="${window._CONFIG.krpanoPath}template_action.xml"`
  114. );
        // 这里主要解决文件路径问题
  115. tempXml = tempXml.replaceAll(`url="vtourskin.xml"`, `url="${window._CONFIG.krpanoPath}vtourskin.xml"`);
  116. tempXml = tempXml.replaceAll(`url="images/`, `url="${window._CONFIG.krpanoPath}images/`);
  117. this.krpano.call(`loadxml(${tempXml})`);
  118. if (title) {
  119. this.panoramaTitle = `${title} - 全景图浏览`;
  120. }
  121. },
  122. // 切换全景图
  123. handleActiveeXml(value) {
  124. const { panoSceneXml, title } = this.info.xmlList.find(i => i.monitorPointId == value);
  125. window.removepano('pano');
  126. // 创建一个新的 div 元素
  127. let newDiv = document.createElement('div');
  128. // 解决动态创建元素无样式属性继承问题
  129. newDiv.style.width = `${this.vw}%`;
  130. newDiv.style.height = `${this.vh}%`;
  131. newDiv.id = 'pano';
  132. let tempEvent = document.getElementsByClassName('div-krpano')[0];
  133. tempEvent.appendChild(newDiv);
  134. this.$nextTick(() => {
  135. window.embedpano({
  136. xml: 0,
  137. target: 'pano',
  138. html5: 'only',
  139. mobilescale: 1.0,
  140. passQueryParameters: 'startscene,startlookat',
  141. initvars: {
  142. KRPANOPATH: process.env.NODE_ENV === 'development' ? '/' : ''
  143. }
  144. });
  145. this.initKrpanoReady(panoSceneXml, title);
  146. });
  147. },
  148. // 热点场景切换
  149. handleClickHotSpotsScene(sceneId, hotspotCode) {
  150. this.krpano.call(`loadscene(${sceneId}), null, MERGE, ZOOMBLEND(2.0, 2.0, easeInOutSine))`);
  151. this.krpano.call(`skin_gotoscene(${sceneId})`);
  152. },
  153. // 热点点击设备事件,需挂载全局
  154. handleClickHotSpotsDevice(collectorId, hostId, objType, hotspotTitle, hotspotCode) {
  155. // 设备主机ID
  156. this.SET_HOSTID(hostId);
  157. // 传感器ID
  158. sessionStorage.setItem('collectorId', collectorId);
  159. // 隐患点对应的监测对象类型:房屋,边坡
  160. this.SET_OBJTYPE(objType);
  161. this.SET_DEVICEDETAILTITLE(hotspotTitle);
  162. this.SET_METHODROUTEBEFORE('XmlPreview');
  163. this.SET_DEVICEDETAILVISIBLE(true);
  164. },
  165. // 搜索全景图
  166. searchInputChange(value) {
  167. // 若未输入值,则展示所有数据
  168. if (null === value || undefined === value) {
  169. this.xmlListRst = this.info.xmlList;
  170. } else {
  171. this.xmlListRst = []; // 结果列表置空
  172. let regStr = '';
  173. // 初始化正则表达式
  174. for (let i = 0; i < value.length; i++) {
  175. regStr = regStr + '(' + value[i] + ')([\\s]*)'; //跨字匹配
  176. }
  177. let reg = new RegExp(regStr);
  178. for (let i = 0; i < this.info.xmlList.length; i++) {
  179. let name = this.info.xmlList[i].monitorPointName; //按照名字匹配
  180. let regMatch = name.match(reg);
  181. if (null !== regMatch) {
  182. // 将匹配的数据放入结果列表中
  183. this.xmlListRst.push(this.info.xmlList[i]);
  184. }
  185. }
  186. this.$refs.refTree.setTreeList(
  187. this.xmlListRst.map(i => ({
  188. ...i,
  189. id: i.monitorPointId,
  190. key: i.monitorPointId,
  191. title: i.monitorPointName
  192. }))
  193. );
  194. }
  195. },
  196. // 关闭弹框
  197. handleCloseVisibleMethod() {
  198. this.SET_XMLVISIBLE(false);
  199. this.SET_METHODROUTEBEFORE('');
  200. }
  201. },
  202. destroyed() {
  203. window.removepano('pano');
  204. }
  205. };
  206. </script>
  207. <style lang="less" scoped>
  208. #pano {
  209. height: 100%;
  210. width: 100%;
  211. }
  212. .ant-menu-inline {
  213. overflow: auto;
  214. }
  215. .ant-layout-has-sider {
  216. height: 100%;
  217. .ant-layout-sider-dark {
  218. height: 100%;
  219. overflow: auto;
  220. }
  221. }
  222. .ant-layout-sider-trigger {
  223. left: 62px;
  224. }
  225. .ant-layout-sider-dark {
  226. border-left: 1px #001529 solid;
  227. .ant-input {
  228. font-size: 12px;
  229. background-color: #202226;
  230. border: 1px solid #001529;
  231. color: white;
  232. }
  233. .ant-input:hover {
  234. border-color: #1890ff;
  235. }
  236. .ant-input-search-icon {
  237. color: white;
  238. }
  239. }
  240. .ant-menu-item-selected {
  241. background-color: #1890ff !important;
  242. }
  243. .div-krpano {
  244. height: 85vh;
  245. }
  246. </style>

后面再贴一下实现效果图

 

 

 

原文链接:https://www.cnblogs.com/ChineseLiao/p/17746727.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号