vue上通过krpano.js实现360全景图 - 中文呀
source link: https://www.cnblogs.com/ChineseLiao/p/17746727.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
vue上通过krpano.js实现360全景图
首先贴出一些XML对应的函数,文件内容都有注释说明,
前端代码读取xml文件代码
View Code
<krpano>
<!-- 这个文件主要写了一些自定义函数,可以在页面通过js来调用 --> <!-- 热点增加动画 --> <action name="hotspot_do_animation" scope="local"> calc(local.xframes, (caller.imagewidth /128) BOR 0); calc(local.frames, xframes * ((caller.imageheight / 128) BOR 0)); def(local.frame, integer, 0); calc(caller.crop, '0|0|' + 128 + '|' + 128); setinterval(calc('crop_anim_' + caller.name), 0.03, if(caller.loaded, inc(frame); if(frame GE frames, if(caller.onlastframe !== null, callwith(caller, onlastframe() ) ); set(frame,0); ); mod(xpos, frame, xframes); div(ypos, frame, xframes); Math.floor(ypos); mul(xpos, 128); mul(ypos, 128); calc(caller.crop, xpos + '|' + ypos + '|' + 128 + '|' + 128); , clearinterval(calc('crop_anim_' + caller.name)); ); ,10); </action> <!-- 热点显示标题,hotspot_title 字段 --> <action name="hotspot_show_title"> txtadd(tooltipname, 'tooltip_', get(name)); addplugin(get(tooltipname)); txtadd(plugin[get(tooltipname)].parent, 'hotspot[',get(name),']'); set(plugin[get(tooltipname)].url,'%SWFPATH%/plugins/textfield.swf'); set(plugin[get(tooltipname)].align,top); set(plugin[get(tooltipname)].edge,bottom); set(plugin[get(tooltipname)].x,0); set(plugin[get(tooltipname)].y,0); set(plugin[get(tooltipname)].autowidth,true); set(plugin[get(tooltipname)].autoheight,true); set(plugin[get(tooltipname)].background,false); set(plugin[get(tooltipname)].border,false); set(plugin[get(tooltipname)].css,'text-align:center; color:#FFFFFF; font-family: PingFangSC-Medium,PingFang SC; font-weight:bold; font-size:16px;'); set(plugin[get(tooltipname)].textshadow,1); set(plugin[get(tooltipname)].textshadowrange,6.0); set(plugin[get(tooltipname)].textshadowangle,90); copy(plugin[get(tooltipname)].html,hotspot[get(name)].hotspot_title); set(plugin[get(tooltipname)].enabled,false); </action> <!-- 热点拖动 --> <action name="hotspot_drag"> spheretoscreen(ath, atv, hotspotcenterx, hotspotcentery, calc(mouse.stagex LT stagewidth/2 ? 'l' : 'r')); sub(drag_adjustx, mouse.stagex, hotspotcenterx); sub(drag_adjusty, mouse.stagey, hotspotcentery); asyncloop(pressed, sub(dx, mouse.stagex, drag_adjustx); sub(dy, mouse.stagey, drag_adjusty); screentosphere(dx, dy, ath, atv); copy(print_ath, ath); copy(print_atv, atv); roundval(print_ath, 3); roundval(print_atv, 3); ); </action> <!-- 热点点击弹出编辑框 --> <action name="hotspot_click_edit"> js(handleClickHotSpotsEdit(get(hotspot_title),get(hotspot_type),get(print_ath),get(print_atv),get(url))); </action> <!-- 获取热点坐标 --> <action name="hotspot_get_ath_atv"> js(handleClickHotSpotsGetAthAtv(get(print_ath),get(print_atv))); </action> <!-- 热点点击切换场景 --> <action name="hotspot_click_scene" scope="local" args="scene_id, hotspot_code"> js(handleClickHotSpotsScene(get(scene_id),get(hotspot_code))); hotspot_get_ath_atv(); </action> <!-- 热点点击设备列表 --> <action name="hotspot_click_device" scope="local" args="collector_id, host_id, obj_type, hotspot_title, hotspot_code"> js(handleClickHotSpotsDevice(get(collector_id),get(host_id),get(obj_type),get(hotspot_title),get(hotspot_code))); hotspot_get_ath_atv(); </action> <!-- 获取当前视角的值 --> <action name="view_get_toh_tov"> copy(print_hlookat, view.hlookat); copy(print_vlookat, view.vlookat); roundval(print_hlookat, 3); roundval(print_vlookat, 3); js(handleGetViewTohTov(get(print_hlookat),get(print_vlookat))) </action> </krpano>
下面这个文件是krpano.js默认配置项的文件,简单做了一些调整以及增加了一部分注释
<krpano> <skin_settings maps="false" maps_type="google" maps_bing_api_key="" maps_google_api_key="" maps_zoombuttons="false" gyro="true" webvr="true" webvr_gyro_keeplookingdirection="false" webvr_prev_next_hotspots="true" littleplanetintro="false" title="true" thumbs="true" thumbs_width="120" thumbs_height="80" thumbs_padding="10" thumbs_crop="0|40|240|160" thumbs_opened="true" thumbs_text="true" thumbs_dragging="true" thumbs_onhoverscrolling="false" thumbs_scrollbuttons="false" thumbs_scrollindicator="false" thumbs_loop="true" tooltips_buttons="false" tooltips_thumbs="false" tooltips_hotspots="false" tooltips_mapspots="false" deeplinking="false" loadscene_flags="MERGE" loadscene_blend="OPENBLEND(0.5, 0.0, 0.75, 0.05, linear)" loadscene_blend_prev="SLIDEBLEND(0.5, 180, 0.75, linear)" loadscene_blend_next="SLIDEBLEND(0.5, 0, 0.75, linear)" loadingtext="" layout_width="100%" layout_maxwidth="814" controlbar_width="-24" controlbar_height="40" controlbar_offset="20" controlbar_offset_closed="-40" controlbar_overlap.no-fractionalscaling="10" controlbar_overlap.fractionalscaling="0" design_skin_images="%$KRPANOPATH%images/vtourskin.png" design_bgcolor="0x2D3E50" design_bgalpha="0.8" design_bgborder="0" design_bgroundedge="1" design_bgshadow="0 4 10 0x000000 0.3" design_thumbborder_bgborder="3 0xFFFFFF 1.0" design_thumbborder_padding="0" design_thumbborder_bgroundedge="0" design_thumb_css="transform:translateZ(1e+12px) translate(0,0) translate(-60px, -40px) rotate(0deg) translate(60px, 40px)" design_text_css="color:#FFFFFF; font-family:Arial;" design_text_shadow="0" /> <!-- mouse / touch / keyboard(button) control settings - http://krpano.com/docu/xml/#control --> <!-- 鼠标触屏键盘控制的设定 --> <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" /> <!-- mouse cursors - http://krpano.com/docu/xml/#cursors --> <!-- 鼠标光标设定可自定义光标的样式 --> <cursors standard="default" dragging="move" moving="move" /> <!-- ensure stagescale 2x for mobile devices (regardless if mobilescale is 0.5 or 1.0) --> <krpano stagescale="calc:stagescale * 2" if="stagescale LT 1.0" devices="mobile" /> <!-- skin styles --> <!-- skin_base - the base skin image --> <style name="skin_base" url="calc:skin_settings.design_skin_images" /> <!-- skin_glow - button glowing (if additional ondown,onup,onout,over events are needed, this style provides ondown2,onup2,onover2,onout2 events) --> <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); ); );" /> <!-- skin_thumbtext_style - style/textfield for the (optional, skin_settings.thumbs_text) thumbnails texts --> <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" /> <!-- skin_hotspotstyle - style for the hotspots --> <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); );" /> <action name="skin_hotspotstyle_click" scope="local"> if(caller.linkedscene, copy(hs_linkedscene, caller.linkedscene); if(caller.linkedscene_lookat, txtsplit(caller.linkedscene_lookat, ',', hs_lookat_h, hs_lookat_v, hs_lookat_fov); ); set(caller.enabled, false); skin_hidetooltips(); tween(caller.depth|caller.alpha|caller.oy|caller.rx, 4000|0.0|-50|-60, 0.5, default, skin_loadscene(get(hs_linkedscene), get(skin_settings.loadscene_blend)); if(hs_lookat_h !== null, skin_lookat(get(hs_lookat_h), get(hs_lookat_v), get(hs_lookat_fov)); ); skin_updatescroll(); ); ); </action> <!-- skin_tooltip - style for the thumb, hotspot and mapspot tooltips --> <style name="skin_tooltips" onover.mouse="copy(layer[skin_tooltip].html, tooltip); set(layer[skin_tooltip].visible, true); tween(layer[skin_tooltip].alpha, 1.0, 0.1); 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); );" /> <!-- the tooltip textfield --> <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="" /> <!-- skin layout --> <!-- 下方控制条 --> <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"> <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"> <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"> <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();" /> <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"> <layer name="skin_thumbs_container" type="container" align="lefttop" width="100%" height="100%" visible="false"> <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" /> <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" /> <layer name="skin_thumbs_scrollindicator" type="container" bgcolor="0xFFFFFF" bgalpha="0.25" align="lefttop" width="0" y="100" height="2" visible="false" enabled="false" /> <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();" /> </layer> </layer> </layer> </layer> <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"> <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" /> </layer> <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"> <layer name="skin_control_bar_buttons" type="container" align="leftbottom" width="100%" height="get:skin_settings.controlbar_height"> <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) );" /> <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();" /> <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" /> <layer name="skin_btn_navi" type="container" align="center" x="0" width="240" height="32"> <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);" /> <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);" /> <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);" /> <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);" /> <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);" /> <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);" /> </layer> <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" /> <!-- 全屏,暂时关闭,客户端需打开 --> <!-- <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" /> --> <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()" /> <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"> <layer name="skin_btn_show_icon" style="skin_base" crop="64|448|64|64" scale="0.5" align="bottom" y="2" enabled="false" /> </layer> <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) );" /> </layer> </layer> <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" /> <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" /> <!-- 缩略图选择边框效果 --> <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" /> </layer> <!-- previous/next scene buttons for the hidden skin mode --> <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();"> <layer name="skin_btn_prev_fs_icon" style="skin_base" crop="0|64|64|64" align="center" scale="0.5" enabled="false" /> </layer> <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();"> <layer name="skin_btn_next_fs_icon" style="skin_base" crop="64|64|64|64" align="center" scale="0.5" enabled="false" /> </layer> <!-- skin events --> <!-- 皮肤的事件 onxmlcomplete XML加载完成后清除当前事件,调用第一个函数skin_startup onnewpano 加载新场景时skin_showloading显示加载中文字 skin_update_scene_infos 根据URL重新设定初始位置等信息 onloadcomplete 加载完成后隐藏加载中文字 onidle 空闲时执行URL的信息更新 onresize 屏幕尺寸变化时执行一次skin_onresize,当每次加载新的pano时onresize也会被触发一次 onenterfullscreen onexitfullscreen 进入退出全屏时更新全屏按钮的图标 onkeydown 监听键盘事件--> <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();" /> <!-- skin actions --> <!-- 当前皮肤的启动函数 --> <action name="skin_startup"> <!-- apply skin settings on startup --> <!-- 根据设置确定缩略图是否在打开时就显示,并且设定是否可拖拽,鼠标的情况下设置为滚动 --> if(skin_settings.thumbs, if(skin_settings.thumbs_opened, set(layer[skin_thumbs].state,'opened'); set(layer[skin_thumbs_container].visible,true); ); copy(layer[skin_thumbs].draggable, skin_settings.thumbs_dragging); if(skin_settings.thumbs_onhoverscrolling AND device.mouse, set(layer[skin_thumbs].draggable, false); set(layer[skin_thumbs].onhover_autoscrolling, true); ); ); if(skin_settings.littleplanetintro AND (device.webgl OR device.flash), skin_setup_littleplanetintro(); ); <!-- 增加缩略图 --> skin_addthumbs(); <!-- 调用onresize --> skin_onresize(); skin_updatescroll(); <!-- 显示下方控制条 --> set(layer[skin_layer].visible, true); </action> <!-- 增加缩略图 --> <action name="skin_addthumbs"> if(skin_settings.thumbs == false, set(layer[skin_btn_thumbs].visible,false); , copy(thumbwidth, skin_settings.thumbs_width); copy(thumbheight, skin_settings.thumbs_height); copy(thumbpadding, skin_settings.thumbs_padding); copy(thumbcrop, skin_settings.thumbs_crop); add(thumbxoffset, thumbwidth, thumbpadding); mul(thumbxcenter, thumbxoffset, 0.5); mul(thumbbarwidth, thumbxoffset, scene.count); add(thumbbarwidth, thumbpadding); add(thumbbarheight, thumbpadding, thumbheight); add(thumbbarheight, thumbpadding); if(skin_settings.thumbs_scrollindicator, copy(layer[skin_thumbs_scrollindicator].y, thumbbarheight); add(thumbbarheight, layer[skin_thumbs_scrollindicator].height); ); copy(layer[skin_thumbs].height, thumbbarheight); copy(layer[skin_thumbs].width, thumbbarwidth); mul(halfheight, thumbbarheight, 0.5); copy(layer[skin_thumbs_scrollleft].y, halfheight); copy(layer[skin_thumbs_scrollright].y, halfheight); <!-- 遍历所有scene并且根据序号设置缩略图名称,并且根据设置添加缩略图文字 --> set(thumb_cnt,0); for(set(i,0), i LT scene.count, inc(i), inc(thumb_cnt); txtadd(thumbname,'skin_thumb_',get(i)); addlayer(get(thumbname)); copy(layer[get(thumbname)].url, scene[get(i)].thumburl); set(layer[get(thumbname)].keep, true); set(layer[get(thumbname)].parent, 'skin_thumbs'); set(layer[get(thumbname)].align, lefttop); copy(layer[get(thumbname)].crop, thumbcrop); copy(layer[get(thumbname)].width, thumbwidth); copy(layer[get(thumbname)].height, thumbheight); mul(thumbx, i, thumbxoffset); add(thumbx, thumbpadding); copy(layer[get(thumbname)].x, thumbx); copy(layer[get(thumbname)].y, thumbpadding); add(scene[get(i)].thumbx, thumbx, thumbxcenter); copy(scene[get(i)].thumby, thumbpadding); set(layer[get(thumbname)].linkedscene, get(scene[get(i)].name) ); set(layer[get(thumbname)].onclick, copy(layer[skin_thumbborder].parent, name); skin_loadscene(get(linkedscene),get(skin_settings.loadscene_blend)); ); if(skin_settings.tooltips_thumbs, set(layer[get(thumbname)].tooltip, get(scene[get(i)].title) ); layer[get(thumbname)].loadstyle(skin_tooltips); ); if(skin_settings.thumbs_text, txtadd(thumbtext, 'skin_thumbtext_', get(i)); addlayer(get(thumbtext)); layer[get(thumbtext)].loadstyle(skin_thumbtext_style); set(layer[get(thumbtext)].keep, true); set(layer[get(thumbtext)].parent, get(thumbname)); set(layer[get(thumbtext)].html, get(scene[get(i)].title)); ); ); if(thumb_cnt == 1, set(layer[skin_thumbs].align, 'lefttop'); ); ); </action> <action name="skin_addmapspots"> for(set(i,0), i LT scene.count, inc(i), if(scene[get(i)].lat, txtadd(spotname, 'spot', get(i)); 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));'); copy(scene[get(i)].mapspotname, spotname); addspot(get(spotname), get(scene[get(i)].lat), get(scene[get(i)].lng), get(scene[get(i)].heading), false, get(spotclickevent), null); if(skin_settings.tooltips_mapspots, set(layer[skin_map].spot[get(spotname)].tooltip, get(scene[get(i)].title) ); txtadd(layer[skin_map].spot[get(spotname)].onover, 'set(hovering,true);', get(style[skin_tooltips].onover) ); txtadd(layer[skin_map].spot[get(spotname)].onout, 'set(hovering,false);', get(style[skin_tooltips].onout) ); ); ); ); if(xml.scene != null, activatespot( get(scene[get(xml.scene)].mapspotname) ); , activatespot(spot0); ); <!-- zoom and pan the map to see all spots at the same time --> zoomToSpotsExtent(); </action> <action name="skin_setup_littleplanetintro"> copy(lp_scene, xml.scene); copy(lp_hlookat, view.hlookat); copy(lp_vlookat, view.vlookat); copy(lp_fov, view.fov); copy(lp_fovmax, view.fovmax); copy(lp_limitview, view.limitview); set(view.fovmax, 170); set(view.limitview, lookto); set(view.vlookatmin, 90); set(view.vlookatmax, 90); lookat(calc(lp_hlookat - 180), 90, 150, 1, 0, 0); set(events[lp_events].onloadcomplete, delayedcall(0.5, if(lp_scene === xml.scene, set(control.usercontrol, off); copy(view.limitview, lp_limitview); set(view.vlookatmin, null); set(view.vlookatmax, null); tween(view.hlookat|view.vlookat|view.fov|view.distortion, calc('' + lp_hlookat + '|' + lp_vlookat + '|' + lp_fov + '|' + 0.0), 3.0, easeOutQuad, set(control.usercontrol, all); tween(view.fovmax, get(lp_fovmax)); ); ); ); ); </action> <action name="skin_lookat"> if(webvr.isenabled, <!-- adjust the VR prev/next hotspots for the view change --> calc(hlookat_offset, %1 - view.hlookat); add(hotspot[webvr_prev_scene].ath, hlookat_offset); add(hotspot[webvr_next_scene].ath, hlookat_offset); ); <!-- change the view --> lookat(%1, %2, %3); </action> <!-- 皮肤重置位置 --> <action name="skin_onresize"> mul(mh, area.pixelheight, -1); if(layer[skin_thumbs].state == 'opened', add(mh,layer[skin_thumbs].height); ); 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); ); add(mh, layer[skin_scroll_layer].y_offset); set(layer[skin_scroll_layer].y, get(mh)); skin_video_updateseekbarwidth(); skin_arrange_buttons(); </action> <!-- determine the visibility of the buttons and calculate their positions --> <action name="skin_arrange_buttons"> calc(show_selbuttons, scene.count GT 1); calc(show_thumbutton, skin_settings.thumbs == true); calc(show_mapbutton, skin_settings.maps == true); calc(show_vrbutton, webvr.isavailable == true); calc(show_fsbutton, device.fullscreensupport == true); set(lpos,6); set(cpos,0); if(show_gyrobutton, dec(cpos,20)); if(show_vrbutton, dec(cpos,24)); set(rpos,6); calc(show_dirbuttons, !device.mobile AND ((area.pixelwidth + 2*cpos) GT 520)); copy(layer[skin_btn_navi].visible, show_dirbuttons); copy(layer[skin_btn_prev].visible, show_selbuttons); copy(layer[skin_btn_next].visible, show_selbuttons); if(show_selbuttons, inc(lpos,44); inc(rpos,44); ); copy(layer[skin_btn_thumbs].visible, show_thumbutton); copy(layer[skin_btn_thumbs].x, lpos); if(show_thumbutton, inc(lpos,40)); copy(layer[skin_btn_map].visible, show_mapbutton); copy(layer[skin_btn_map].x, lpos); if(show_mapbutton, inc(lpos,40)); if(show_dirbuttons, copy(layer[skin_btn_navi].x, cpos); inc(cpos,140); set(layer[skin_btn_gyro].align, center); copy(layer[skin_btn_gyro].visible, show_gyrobutton); copy(layer[skin_btn_gyro].x, cpos); if(show_gyrobutton, inc(cpos,48)); set(layer[skin_btn_vr].align, center); copy(layer[skin_btn_vr].visible, show_vrbutton); copy(layer[skin_btn_vr].x, cpos); if(show_vrbutton, inc(cpos,80)); , set(layer[skin_btn_gyro].align, left); copy(layer[skin_btn_gyro].visible, show_gyrobutton); copy(layer[skin_btn_gyro].x, lpos); if(show_gyrobutton, inc(lpos,40)); set(layer[skin_btn_vr].align, left); copy(layer[skin_btn_vr].visible, show_vrbutton); copy(layer[skin_btn_vr].x, lpos); if(show_vrbutton, inc(lpos,80)); ); copy(layer[skin_btn_hide].x, rpos); inc(rpos,40); copy(layer[skin_btn_fs].visible, show_fsbutton); copy(layer[skin_btn_fs].x, rpos); if(show_fsbutton, inc(rpos,40)); </action> <!-- 将当前的scene缩略图设置到正中央 --> <action name="skin_updatescroll"> if(layer[skin_thumbs].loaded, set(cursceneindex, 0); if(xml.scene, copy(cursceneindex, scene[get(xml.scene)].index)); layer[skin_thumbs].setcenter(get(scene[get(cursceneindex)].thumbx), get(scene[get(cursceneindex)].thumby)); ); <!-- 设置当前场景的缩略图为选中式样 --> txtadd(parentname, 'skin_thumb_', get(scene[get(xml.scene)].index)); if(layer[get(parentname)], set(layer[skin_thumbborder].parent, get(parentname)); set(layer[skin_thumbborder].visible, true); , set(layer[skin_thumbborder].visible, false); ); </action> <action name="skin_updatethumbscroll"> copy(padding,skin_settings.thumbs_padding); if(skin_settings.thumbs_scrollbuttons, if(loverflow GT 0, set(layer[skin_thumbs_scrollleft].visible,true), set(layer[skin_thumbs_scrollleft].visible,false) ); if(roverflow GT 0, set(layer[skin_thumbs_scrollright].visible,true), set(layer[skin_thumbs_scrollright].visible,false) ); ); if(skin_settings.thumbs_scrollindicator, if(woverflow GT 0, set(layer[skin_thumbs_scrollindicator].visible,true); sub(iw,pixelwidth,woverflow); div(pw,iw,pixelwidth); div(px,loverflow,woverflow); mul(pw,iw); copy(layer[skin_thumbs_scrollindicator].width,pw); sub(iw,pw); sub(iw,padding); sub(iw,padding); mul(px,iw); add(px,padding); copy(layer[skin_thumbs_scrollindicator].x,px); , set(layer[skin_thumbs_scrollindicator].visible,false); ); ); </action> <!-- 更新场景信息 --> <action name="skin_update_scene_infos"> if(xml.scene !== null AND scene[get(xml.scene)].index GE 0, <!-- 设置场景名称 --> if(skin_settings.title, 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 ); ); delayedcall(0.1, set(layer[skin_title].visible,true) ); ); <!-- 如果不循环根据当前场景的序号设置切换按钮显示 --> if(skin_settings.thumbs_loop == false, if(scene[get(xml.scene)].index GT 0, set(layer[skin_btn_prev].enabled, true); set(layer[skin_btn_prev].alpha, 1.0); , set(layer[skin_btn_prev].enabled, false); set(layer[skin_btn_prev].alpha, 0.3); ); sub(lastsceneindex, scene.count, 1); if(scene[get(xml.scene)].index LT lastsceneindex, set(layer[skin_btn_next].enabled, true); set(layer[skin_btn_next].alpha, 1.0); , set(layer[skin_btn_next].enabled, false); set(layer[skin_btn_next].alpha, 0.3); ); , if(scene.count GT 1, set(layer[skin_btn_prev].enabled, true); set(layer[skin_btn_prev].alpha, 1.0); set(layer[skin_btn_next].enabled, true); set(layer[skin_btn_next].alpha, 1.0); , set(layer[skin_btn_prev].enabled, false); set(layer[skin_btn_prev].alpha, 0.3); set(layer[skin_btn_next].enabled, false); set(layer[skin_btn_next].alpha, 0.3); ); ); if(scene.count GT 1, set(layer[skin_btn_prev_fs].visible, true); set(layer[skin_btn_next_fs].visible, true); , set(layer[skin_btn_prev_fs].visible, false); set(layer[skin_btn_next_fs].visible, false); ); <!-- 设置当前场景的缩略图为选中式样 --> txtadd(parentname, 'skin_thumb_', get(scene[get(xml.scene)].index)); if(layer[get(parentname)], set(layer[skin_thumbborder].parent, get(parentname)); set(layer[skin_thumbborder].visible, true); , set(layer[skin_thumbborder].visible, false); ); ); </action> <action name="skin_gotoscene"> if(scene[%1], copy(cursceneindex, scene[get(xml.scene)].index); copy(newsceneindex, scene[%1].index); 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)) ); ); </action> <action name="skin_nextscene"> add(newsceneindex, scene[get(xml.scene)].index, %1); if(newsceneindex GE 0 AND newsceneindex LT scene.count, skin_loadscene(get(newsceneindex), calc(%1 LT 0 ? skin_settings.loadscene_blend_prev : skin_settings.loadscene_blend_next)); ); </action> <action name="skin_nextscene_loop"> add(newsceneindex, scene[get(xml.scene)].index, %1); sub(lastsceneindex, scene.count, 1); if(newsceneindex LT 0, copy(newsceneindex,lastsceneindex)); if(newsceneindex GT lastsceneindex, set(newsceneindex,0)); skin_loadscene(get(newsceneindex), calc(%1 LT 0 ? skin_settings.loadscene_blend_prev : skin_settings.loadscene_blend_next)); </action> <!-- skin_loadscene(scenenameorindex, blendmode) --> <action name="skin_loadscene"> if(webvr.isenabled AND scene.count GT 1, set(hotspot[webvr_prev_scene].visible, false); set(hotspot[webvr_next_scene].visible, false); ); txtadd(layer[skin_thumbborder].parent, 'skin_thumb_', get(scene[%1].index)); layer[skin_thumbs].scrolltocenter(get(scene[%1].thumbx), get(scene[%1].thumby)); loadscene(get(scene[%1].name), null, get(skin_settings.loadscene_flags), %2); </action> <action name="skin_showloading"> if(display.stereo == true, set(layer[skin_loadingtext].visible, false); , set(layer[skin_loadingtext].visible, %1); ); </action> <action name="skin_hidetooltips"> set(layer[skin_tooltip].alpha,0.0); set(layer[skin_tooltip].visible,false); </action> <action name="skin_buttonglow"> if('%1' !== 'null', set(strength,0.7); if(%2 != null, set(strength,%2)); set(layer[skin_buttonglow].parent, %1); set(layer[skin_buttonglow].visible, true); tween(layer[skin_buttonglow].alpha, get(strength), 0.07); , tween(layer[skin_buttonglow].alpha, 0.0, 0.1, default, set(layer[skin_buttonglow].parent, null); set(layer[skin_buttonglow].visible, false); ); ); </action> <action name="skin_calc_opened_closed"> if(layer[get(name)].y_closed === null, set(layer[get(name)].y_opened, get(layer[get(name)].y)); set(layer[get(name)].y_closed, calc(layer[get(name)].y - skin_settings.controlbar_offset - skin_settings.controlbar_height + skin_settings.controlbar_offset_closed)); ); </action> <action name="skin_hideskin"> callwith(layer[skin_scroll_window], skin_calc_opened_closed() ); callwith(layer[skin_splitter_bottom], skin_calc_opened_closed() ); callwith(layer[skin_control_bar], skin_calc_opened_closed() ); if(layer[skin_map].state != 'closed', skin_showmap(false); wait(0.40); ); if(layer[skin_thumbs].state != 'closed', skin_showthumbs(false); wait(0.25); ); set(hidetime, calc('%1' == 'instant' ? 0.0 : 0.5)); tween(layer[skin_scroll_window].y, get(layer[skin_scroll_window ].y_closed), get(hidetime)); tween(layer[skin_splitter_bottom].y, get(layer[skin_splitter_bottom].y_closed), get(hidetime)); tween(layer[skin_control_bar].y, get(layer[skin_control_bar ].y_closed), get(hidetime)); tween(layer[skin_btn_prev_fs].x, 0, get(hidetime)); tween(layer[skin_btn_next_fs].x, 0, get(hidetime)); if(layer[skin_logo], tween(layer[skin_logo].alpha, 0.0, 0.5, default, set(layer[skin_logo].visible,false)); ); stopdelayedcall(skin_btn_show_alpha); set(layer[skin_btn_show].visible, true); delayedcall(skin_btn_show_alpha, get(hidetime), tween(layer[skin_btn_show].alpha, 0.25, 0.25); ); </action> <action name="skin_showskin"> tween(layer[skin_scroll_window ].y, get(layer[skin_scroll_window ].y_opened)); tween(layer[skin_splitter_bottom].y, get(layer[skin_splitter_bottom].y_opened)); tween(layer[skin_control_bar ].y, get(layer[skin_control_bar ].y_opened)); tween(layer[skin_btn_prev_fs].x, -50); tween(layer[skin_btn_next_fs].x, -50); if(layer[skin_logo], set(layer[skin_logo].visible,true); tween(layer[skin_logo].alpha, 1.0); ); stopdelayedcall(skin_btn_show_alpha); set(layer[skin_btn_show].visible, false); delayedcall(skin_btn_show_alpha, 0.25, tween(layer[skin_btn_show].alpha, 0.0, 0.0); ); </action> <action name="skin_showthumbs"> if(%1 == null, if(layer[skin_thumbs].state == 'closed', set(show,true), set(show,false)); , set(show,%1); ); mul(mh, layer[skin_scroll_layer].pixelheight, -1); if(show, set(layer[skin_thumbs].state, 'opened'); tween(layer[skin_thumbs].alpha, 1.0, 0.25); add(mh, layer[skin_thumbs].height); add(mh, layer[skin_scroll_layer].y_offset); tween(layer[skin_scroll_layer].y, get(mh), 0.5, easeOutQuint); set(layer[skin_thumbs_container].visible, true); tween(layer[skin_thumbs_container].alpha, 1.0, 0.25); tween(layer[skin_map].alpha, 0.0, 0.25, default, set(layer[skin_map].visible,false)); , set(layer[skin_thumbs].state, 'closed'); tween(layer[skin_thumbs].alpha, 0.0, 0.25, easeOutQuint); add(mh, layer[skin_scroll_layer].y_offset); tween(layer[skin_scroll_layer].y, get(mh), 0.5, easeOutQuint, set(layer[skin_thumbs_container].visible, false);); ); </action> <action name="skin_showmap"> if(%1 == null, if(layer[skin_map].state == 'closed', set(show,true), set(show,false)); , set(show,%1); ); mul(mh, layer[skin_scroll_layer].pixelheight, -1); if(show, tween(layer[skin_thumbs_container].alpha, 0.0, 0.25, default, set(layer[skin_thumbs_container].visible,false)); set(layer[skin_map].visible, true); tween(layer[skin_map].alpha, 1.0, 0.25); set(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); sub(hh,skin_settings.controlbar_overlap); copy(layer[skin_map].height, hh); tween(layer[skin_scroll_layer].y, get(mh), 0.5, easeOutQuint); , if(layer[skin_map].state != 'closed', set(layer[skin_map].state, 'closed'); add(mh, layer[skin_scroll_layer].y_offset); tween(layer[skin_map].alpha, 0.0, 0.5, easeOutQuint); tween(layer[skin_scroll_layer].y, get(mh), 0.5, easeOutQuint, set(layer[skin_map].visible,false) ); ); ); </action> <action name="skin_keydown_event"> if(keycode == 33, skin_nextscene_loop(-1) ); <!-- Page Up - previous scene --> if(keycode == 34, skin_nextscene_loop(+1) ); <!-- Page Dowm - next scene --> if(keycode == 35, skin_gotoscene(calc(scene.count-1)) ); <!-- End - last scene --> if(keycode == 36, skin_gotoscene(0) ); <!-- Home/Pos1 - first scene --> </action> <action name="skin_deeplinking_update_url"> if(skin_settings.deeplinking AND (!webvr OR webvr.isenabled === false), delayedcall(skin_deeplinking_update, calc(%1 == null ? 0.1 : %1), skin_deeplinking_update_url_process() ); ); </action> <action name="skin_deeplinking_update_url_process"> copy(adr, browser.location); indexoftxt(qi, get(adr), '?'); if(qi GT 0, subtxt(adr, adr, 0, get(qi))); copy(si, scene[get(xml.scene)].index); copy(h, view.hlookat); copy(v, view.vlookat); copy(f, view.fov); copy(d, view.distortion); copy(a, view.architectural); clamp(d, 0.0, 1.0); clamp(a, 0.0, 1.0); set(pp, calc(f LT 10 ? 6 : 2)); roundval(h, get(pp)); roundval(v, get(pp)); roundval(f, get(pp)); roundval(d, 2); roundval(a, 1); set(adr, calc(adr + '?startscene=' + si + '&startactions=lookat('+h+','+v+','+f+','+d+','+a+');')); js( history.replaceState(null, document.title, get(adr)); ); </action> <!-- reload the scene when there is a special image for VR --> <action name="skin_reloadscene_webvr"> delayedcall(0.1, if(scene[get(xml.scene)].havevrimage, copy(keeplookingdirection_backup, skin_settings.webvr_gyro_keeplookingdirection); set(skin_settings.webvr_gyro_keeplookingdirection, true); loadscene(get(xml.scene), null, MERGE|KEEPVIEW|KEEPMOVING|KEEPPLUGINS|KEEPHOTSPOTS|NOPREVIEW, BLEND(0.5)); copy(skin_settings.webvr_gyro_keeplookingdirection, keeplookingdirection_backup); delete(keeplookingdirection_backup); ); ); </action> <action name="skin_video_removecontrols"> stopdelayedcall(skin_video_delayedvisible); set(events[skin_events].onclick, null); set(layer[skin_video_playpause].alpha, 0.0); set(layer[skin_video_controls].visible, false); clearinterval(skin_video_seek_updates); </action> <action name="skin_video_updateseekbarwidth"> if(skin_settings.title, calc(layer[skin_video_seekbar_container].width, 0 - (32 + layer[skin_title].pixelwidth + layer[skin_video_time].pixelwidth)); calc(layer[skin_video_seekbar_container].x, layer[skin_title].pixelwidth + 16); , calc(layer[skin_video_seekbar_container].width, 0 - (24 + layer[skin_video_time].pixelwidth)); set(layer[skin_video_seekbar_container].x, 8); ); </action> <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();" /> <!-- context menu - http://krpano.com/docu/xml/#contextmenu --> <contextmenu> <item name="kr" caption="KRPANO" /> <item name="fs" caption="FULLSCREEN" /> <item name="cc" caption="Change Controlmode" onclick="skin_changecontrolmode();" separator="true" /> <item name="nv" caption="Normal View" onclick="skin_view_normal();" showif="view.vlookatrange == 180" separator="true" /> <item name="fv" caption="Fisheye View" onclick="skin_view_fisheye();" showif="view.vlookatrange == 180" devices="flash|webgl" /> <item name="sv" caption="Stereographic View" onclick="skin_view_stereographic();" showif="view.vlookatrange == 180" devices="flash|webgl" /> <item name="av" caption="Architectural View" onclick="skin_view_architectural();" showif="view.vlookatrange == 180" /> <item name="pv" caption="Pannini View" onclick="skin_view_pannini();" showif="view.vlookatrange == 180" devices="flash|webgl" /> <item name="lp" caption="Little Planet View" onclick="skin_view_littleplanet();" showif="view.vlookatrange == 180" devices="flash|webgl" /> </contextmenu> <action name="skin_changecontrolmode"> switch(control.mouse, moveto, drag); switch(control.touch, moveto, drag); </action> <action name="skin_view_look_straight"> if(view.vlookat LT -80 OR view.vlookat GT +80, tween(view.vlookat, 0.0, 1.0, easeInOutSine); tween(view.fov, 100, distance(150,0.8)); ); skin_deeplinking_update_url(1.0); </action> <action name="skin_view_normal"> skin_view_look_straight(); tween(view.architectural, 0.0, distance(1.0,0.5)); tween(view.pannini, 0.0, distance(1.0,0.5)); tween(view.distortion, 0.0, distance(1.0,0.5)); </action> <action name="skin_view_fisheye"> skin_view_look_straight(); tween(view.architectural, 0.0, distance(1.0,0.5)); tween(view.pannini, 0.0, distance(1.0,0.5)); tween(view.distortion, 0.35, distance(1.0,0.5)); </action> <action name="skin_view_architectural"> skin_view_look_straight(); tween(view.architectural, 1.0, distance(1.0,0.5)); tween(view.pannini, 0.0, distance(1.0,0.5)); tween(view.distortion, 0.0, distance(1.0,0.5)); </action> <action name="skin_view_stereographic"> skin_view_look_straight(); tween(view.architectural, 0.0, distance(1.0,0.5)); tween(view.pannini, 0.0, distance(1.0,0.5)); tween(view.distortion, 1.0, distance(1.0,0.8)); </action> <action name="skin_view_pannini"> skin_view_look_straight(); tween(view.architectural, 0.0, distance(1.0,0.5)); tween(view.pannini, 1.0, distance(1.0,0.8)); if(view.distortion LT 0.1, tween(view.distortion, 1.0, distance(1.0,0.8)); ); </action> <action name="skin_view_littleplanet"> tween(view.architectural, 0.0, distance(1.0,0.5)); tween(view.pannini, 0.0, distance(1.0,0.5)); tween(view.distortion, 1.0, distance(1.0,0.8)); tween(view.fov, 150, distance(150,0.8)); tween(view.vlookat, 90, distance(100,0.8)); add(new_hlookat, view.hlookat, 123.0); tween(view.hlookat, get(new_hlookat), distance(100,0.8)); skin_deeplinking_update_url(1.0); </action> </krpano>
这一段代码是主要写怎么生成对应的xml文件,也就是新增和编辑功能,以及一下全景图视角和缩放比例的设置
<template> <AModal class="div-scene-edit" :title="info.title" :footer="null" :visible="info.visible" @cancel="handleCancelVisible" width="40%" > <a-form-model ref="refFormScene" :model="formData" :label-col="labelCol" :wrapper-col="wrapperCol"> <a-form-model-item label="场景名称" prop="sceneName" :rules="[{ required: true, validator: validateName, trigger: 'change' }]" > <a-input v-model="formData.sceneName" placeholder="全景图场景名称,中英文、数字,不要使用特殊字符" /> </a-form-model-item> <a-form-model-item label="场景序号" prop="orderSeq" :rules="[{ required: true }]"> <a-input v-model="formData.orderSeq" placeholder="请输入当前场景序号" /> </a-form-model-item> <a-form-model-item label="全景图上传" extra="球形全景图:上传方便,长宽比=2:1" :rules="[{ required: true }]"> <template> <a-upload :file-list="fileData.fileList" listType="picture-card" :action="fileData.uploadImg" :headers="fileData.headers" :transformFile="handleTransformFile" @preview="handlePreviewImg" @change="handleChangeImg" > <div v-if="fileData.fileList.length === 0"> <a-icon type="plus" /> <div class="ant-upload-text">点击上传</div> </div> </a-upload> <a v-if="formData.sceneType == 'SPHERE'" href="javascript:;" @click="handleCutImg">切图</a> </template> <a-modal :visible="fileData.visible" :footer="null" @cancel="handleCancelPreviewImg"> <img alt="example" style="width: 100%" :src="fileData.thumbUrl" /> </a-modal> </a-form-model-item> <a-form-model-item label="初始视角(水平)" name="hlookat" :rules="[{ required: true }]"> <a-input v-model:value="formData.hlookat" placeholder="水平方向视角" @focus="handleFocusAthAtv" /> </a-form-model-item> <a-form-model-item label="初始视角(垂直)" name="vlookat" :rules="[{ required: true }]"> <a-input v-model:value="formData.vlookat" placeholder="垂直方向视角" @focus="handleFocusAthAtv" /> </a-form-model-item> <a-form-model-item label="初始缩放视角FOV" name="fov" :rules="[{ required: true }]"> <a-input v-model:value="formData.fov" placeholder="初始缩放视角FOV,默认值:120" @focus="handleFocusAthAtv" /> </a-form-model-item> <a-form-model-item label="缩放最小FOV" name="fovmin" :rules="[{ required: true }]"> <a-input v-model:value="formData.fovmin" placeholder="缩放最小FOV(场景拉近),必须小于初始FOV" /> </a-form-model-item> <a-form-model-item label="缩放最大FOV" name="fovmax" :rules="[{ required: true }]"> <a-input v-model:value="formData.fovmax" placeholder="缩放最大FOV(场景拉远),必须大于初始FOV" /> </a-form-model-item> <a-form-model-item class="div-scene-edit-foot"> <AButton class="create-ant-btn" @click.prevent="handleCancel" :loading="isLoading">取消</AButton> <AButton type="primary" @click.prevent="handleSave" :loading="isLoading">保存</AButton> </a-form-model-item> </a-form-model> <AModal v-if="lookatInfo.visible" title="选取初始视角,请拖动至弹框中心" :footer="null" :visible="lookatInfo.visible" @cancel="handleCancelXMLVisible" width="80%" > <div id="pano" :style="{ width: `80vd`, height: `65vh` }"></div> <img class="btn-content-img" @click.prevent="handleSaveXMLLookat" src="~@/assets/introimage.png" /> </AModal> </AModal> </template> <script> import { getACCESS_TOKEN } from '@/utils/util' import { postAction, putAction, uploadAction } from '@/api/manage' import KrpanoToolJS from '@krpano/js-tools' export default { name: 'SceneEdit', props: { info: { type: Object, default: () => ({ title: '场景新建', visible: false, }), }, }, data() { return { labelCol: { span: 6 }, wrapperCol: { span: 14 }, // 表单数据 formData: {}, fileData: { fileList: [], uploadImg: `${process.env.VUE_APP_API_BASE_URL}/pano/panoScene/uploadPanoImage/${this.info.monitorPointId}`, headers: { 'X-Access-Token': getACCESS_TOKEN() }, thumbUrl: '', visible: false, }, url: { list: '/bimModelUpdateRecord/bimModelUpdateRecord/bimList', }, disableMixinCreated: true, isHotspot: false, sceneList: [], sceneName: '', lookatInfo: { visible: false, }, isLoading: false, } }, created() { this.formData = { ...this.info } if (this.formData.sceneId) { this.fileData.fileList = [ { uid: '-1', name: 'image.png', status: 'done', url: this.info.sceneUrl, }, ] } window['handleGetViewTohTov'] = this.handleGetViewTohTov }, methods: { // 场景名称正则 validateName(rule, value, callback) { if (value === '') { callback(new Error('请输入场景名称')) } else if (!/^[a-zA-Z0-9\u4e00-\u9fa5]+$/.test(value)) { callback(new Error('请输入中英文及数字')) } else { this.$refs.refFormScene.validateField('sceneName') callback() } }, // 关闭弹框 handleCancelVisible() { this.$emit('cancelVisible') }, // 上传前先处理一下,调用切片方法 handleTransformFile(file) { return new Promise((resolve) => { const krpanoTool = new KrpanoToolJS() krpanoTool .checkFile(file) .then(() => { krpanoTool.makeCube(file).then((result) => { resolve(result.content) }) }) .catch(() => { this.$message.error('图片需要小于20000*10000,建议图片大小不超过25MB') }) }) }, // 上传完成后,图片信息改变 handleChangeImg({ fileList }) { this.fileData.fileList = [] fileList.forEach((item) => { if (item.response) { if (item.response.result) { this.formData.previewUrl = item.response.result.previewImageUrl this.formData.sceneUrl = item.response.result.thumbImageUrl this.formData.cubeUrl = item.response.result.panoWildcardUrl // 缩略图使用切片后的 item.url = item.response.result.thumbImageUrl } } this.fileData.fileList.push(item) }) }, // 浏览大图 handlePreviewImg(file) { this.fileData.thumbUrl = file.url || file.thumbUrl this.fileData.visible = true }, // 关闭浏览大图 handleCancelPreviewImg() { this.fileData.visible = false }, handleCancel() { this.formData.previewUrl = '' this.formData.sceneUrl = '' this.$emit('cancelVisible') }, // 场景创建或编辑 handleSave() { this.$refs.refFormScene.validate((valid) => { if (!this.formData.previewUrl) { this.$message.warning('全景图不能为空') return } if (valid) { if (this.formData.sceneId) { putAction('/pano/panoScene/edit', { sceneId: this.formData.sceneId, previewUrl: this.formData.previewUrl, sceneUrl: this.formData.sceneUrl, cubeUrl: this.formData.cubeUrl, hotspotCount: 0, camroll: 1, fov: this.formData.fov, fovmin: this.formData.fovmin, fovmax: this.formData.fovmax, monitorPointId: this.formData.monitorPointId, sceneName: this.formData.sceneName, orderSeq: this.formData.orderSeq, hlookat: this.formData.hlookat, hlookatmin: -180, hlookatmax: 180, vlookat: this.formData.vlookat, vlookatmin: -90, vlookatmax: 90, fovtype: 'MFOV', sceneType: 'CUBE', }) .then((res) => { if (res.success) { this.$message.success(res.message) } else { this.$message.warning(res.message) } }) .finally(() => { this.$emit('cancelVisible', true) }) } else { postAction('/pano/panoScene/add', { sceneCode: `scene${this.formData.orderSeq}`, previewUrl: this.formData.previewUrl, sceneUrl: this.formData.sceneUrl, cubeUrl: this.formData.cubeUrl, hotspotCount: 0, camroll: 1, fov: this.formData.fov, fovmin: this.formData.fovmin, fovmax: this.formData.fovmax, monitorPointId: this.formData.monitorPointId, sceneName: this.formData.sceneName, orderSeq: this.formData.orderSeq, hlookat: this.formData.hlookat, hlookatmin: -180, hlookatmax: 180, vlookat: this.formData.vlookat, vlookatmin: -90, vlookatmax: 90, fovtype: 'MFOV', sceneType: 'CUBE', }) .then((res) => { if (res.success) { this.$message.success(res.message) } else { this.$message.warning(res.message) } }) .finally(() => { this.$emit('cancelVisible', true) }) } } }) }, // 获取初始化视角值 handleFocusAthAtv() { const { previewUrl, sceneUrl, hlookat, vlookat, fov, fovmin, fovmax, cubeUrl } = this.formData if (!previewUrl) { this.$message.warning('全景图不能为空') return } this.lookatInfo.visible = true this.$nextTick(() => { window.embedpano({ xml: 0, target: 'pano', html5: 'only', mobilescale: 1.0, passQueryParameters: 'startscene,startlookat', initvars: { KRPANOPATH: process.env.NODE_ENV === 'development' ? '/' : '', }, }) var krpano = document.getElementById('krpanoSWFObject') var tempXml = `<krpano version="1.20.7" onstart="loadscene(scene1);"> <include url="template_action.xml" /> <scene name="scene1" thumburl="${sceneUrl}" title="场景1"> <view hlookat="${hlookat}" vlookat="${vlookat}" fovmin="${fovmin}" fovmax="${fovmax}" fov="${fov}" hlookatmin="-180" hlookatmax="180" vlookatmin="-90" vlookatmax="90" fovtype="MFOV" /> <preview url="${previewUrl}"/> <image> <cube url="${cubeUrl}" /> </image> </scene> </krpano>` // 如果是开发环境 if (process.env.NODE_ENV === 'development') { window._CONFIG.krpanoPath = '/' } tempXml = tempXml.replaceAll( `url="template_action.xml"`, `url="${window._CONFIG.krpanoPath}template_action.xml"` ) tempXml = tempXml.replaceAll(`url="vtourskin.xml"`, `url="${window._CONFIG.krpanoPath}vtourskin.xml"`) tempXml = tempXml.replaceAll(`url="images/`, `url="${window._CONFIG.krpanoPath}images/`) krpano.call(`loadxml(${tempXml})`) }) }, // 关闭xml handleCancelXMLVisible() { this.lookatInfo.visible = false window.removepano('pano') }, // 保存当前xml值 handleSaveXMLLookat() { var krpano = document.getElementById('krpanoSWFObject') krpano.call(`view_get_toh_tov()`) this.lookatInfo.visible = false window.removepano('pano') }, // 获取当前视角的值 handleGetViewTohTov(hlookat, vlookat, fov) { this.formData.hlookat = hlookat this.formData.vlookat = vlookat this.formData.fov = fov }, // 切图 handleCutImg() { this.isLoading = true this.getImageFileFromUrl(this.info.previewUrl, '图片.png', function (file) { const krpanoTool = new KrpanoToolJS() krpanoTool .checkFile(file) .then(() => { krpanoTool.makeCube(file).then((result) => { const fileData = new FormData() fileData.append('file', result.content) uploadAction(`/pano/panoScene/uploadPanoImage/${this.info.monitorPointId}`, fileData) .then((response) => { this.formData.previewUrl = response.result.previewImageUrl this.formData.sceneUrl = response.result.thumbImageUrl this.formData.cubeUrl = response.result.panoWildcardUrl }) .finally(() => { this.isLoading = false }) }) }) .catch(() => { this.$message.error('图片需要小于20000*10000,建议图片大小不超过25MB') }) }) }, getImageFileFromUrl(url, imageName, callback) { var blob = null var xhr = new XMLHttpRequest() xhr.open('GET', url) xhr.setRequestHeader('Accept', 'image/jpeg') xhr.responseType = 'blob' xhr.onload = () => { if (xhr.status === 200) { blob = xhr.response let imgFile = new File([blob], imageName, { type: 'image/jpeg' }) callback.call(this, imgFile) } } xhr.send() }, }, } </script> <style lang="less"> .div-scene-edit { .ant-upload-text { color: #bfbfbf; } .anticon { color: #bfbfbf; } .ant-form-extra { color: #bfbfbf; } } .div-scene-edit-foot { display: flex; justify-content: flex-end; .create-ant-btn { margin-right: 10px; } } .btn-content-img { position: absolute; left: 0; right: 0; top: 0; bottom: 0; margin: auto; cursor: pointer; } </style>
后面再贴一下vue页面对应的代码
<template> <transition name="scale" appear> <AnTaiModal v-model="visibles" @visibleMethod="handleCloseVisibleMethod" :title="panoramaTitle" :isCollapse="info.isMore" > <template slot="collapses"> <TreeTemplate ref="refTree" modules="" colorsKey="releaseWarnLevel" :listData="xmlListRst" :defaultFilter="false" placeholder="请输入隐患点名称,编号" @switchActive="handleActiveeXml" @change="searchInputChange" /> </template> <template slot="contents"> <div class="div-krpano"> <!-- 全景图 --> <div id="pano" :style="{ width: `${vw}%`, height: `${vh}%` }"></div> </div> </template> </AnTaiModal> </transition> </template> <script> import { mapState, mapMutations } from 'vuex'; import routeMixin from '@/mixins/routeMixin.js'; import TreeTemplate from '@/components/_public/treeTemplate/treeTemplate'; export default { // 全景图浏览弹框 name: 'XmlPreview', components: { TreeTemplate }, mixins: [routeMixin], props: { vw: { type: Number, default: 100 }, vh: { type: Number, default: 100 } }, computed: { ...mapState({ info: state => state.common.xmlInfo }) }, data() { return { krpano: null, visibles: true, xmlListRst: [], panoramaTitle: '', routeLeaveShow: true }; }, beforeMount() { window['handleClickHotSpotsDevice'] = this.handleClickHotSpotsDevice; window['handleClickHotSpotsScene'] = this.handleClickHotSpotsScene; }, created() { this.panoramaTitle = this.info.title; this.xmlListRst = this.info.xmlList.map(i => ({ ...i, id: i.monitorPointId, key: i.monitorPointId, title: i.monitorPointName })); }, mounted() { this.$nextTick(() => { window.embedpano({ xml: 0, target: 'pano', html5: 'only', mobilescale: 1.0, passQueryParameters: 'startscene,startlookat', initvars: { KRPANOPATH: process.env.NODE_ENV === 'development' ? '/' : '' } }); this.initKrpanoReady(this.info.panoSceneXml); }); }, methods: { ...mapMutations([ 'SET_XMLVISIBLE', 'SET_DEVICEDETAILVISIBLE', 'SET_DEVICEDETAILTITLE', 'SET_METHODROUTEBEFORE', 'SET_HOSTID', 'SET_OBJTYPE' ]), // 初始化完成,展示xml数据, initKrpanoReady(tempXml, title) { this.krpano = document.getElementById('krpanoSWFObject'); tempXml = tempXml.replaceAll(`ondown="hotspot_drag();"`, ''); // 如果是开发环境 if (process.env.NODE_ENV === 'development') { window._CONFIG.krpanoPath = '/'; } tempXml = tempXml.replaceAll( `url="template_action.xml"`, `url="${window._CONFIG.krpanoPath}template_action.xml"` );
// 这里主要解决文件路径问题 tempXml = tempXml.replaceAll(`url="vtourskin.xml"`, `url="${window._CONFIG.krpanoPath}vtourskin.xml"`); tempXml = tempXml.replaceAll(`url="images/`, `url="${window._CONFIG.krpanoPath}images/`); this.krpano.call(`loadxml(${tempXml})`); if (title) { this.panoramaTitle = `${title} - 全景图浏览`; } }, // 切换全景图 handleActiveeXml(value) { const { panoSceneXml, title } = this.info.xmlList.find(i => i.monitorPointId == value); window.removepano('pano'); // 创建一个新的 div 元素 let newDiv = document.createElement('div'); // 解决动态创建元素无样式属性继承问题 newDiv.style.width = `${this.vw}%`; newDiv.style.height = `${this.vh}%`; newDiv.id = 'pano'; let tempEvent = document.getElementsByClassName('div-krpano')[0]; tempEvent.appendChild(newDiv); this.$nextTick(() => { window.embedpano({ xml: 0, target: 'pano', html5: 'only', mobilescale: 1.0, passQueryParameters: 'startscene,startlookat', initvars: { KRPANOPATH: process.env.NODE_ENV === 'development' ? '/' : '' } }); this.initKrpanoReady(panoSceneXml, title); }); }, // 热点场景切换 handleClickHotSpotsScene(sceneId, hotspotCode) { this.krpano.call(`loadscene(${sceneId}), null, MERGE, ZOOMBLEND(2.0, 2.0, easeInOutSine))`); this.krpano.call(`skin_gotoscene(${sceneId})`); }, // 热点点击设备事件,需挂载全局 handleClickHotSpotsDevice(collectorId, hostId, objType, hotspotTitle, hotspotCode) { // 设备主机ID this.SET_HOSTID(hostId); // 传感器ID sessionStorage.setItem('collectorId', collectorId); // 隐患点对应的监测对象类型:房屋,边坡 this.SET_OBJTYPE(objType); this.SET_DEVICEDETAILTITLE(hotspotTitle); this.SET_METHODROUTEBEFORE('XmlPreview'); this.SET_DEVICEDETAILVISIBLE(true); }, // 搜索全景图 searchInputChange(value) { // 若未输入值,则展示所有数据 if (null === value || undefined === value) { this.xmlListRst = this.info.xmlList; } else { this.xmlListRst = []; // 结果列表置空 let regStr = ''; // 初始化正则表达式 for (let i = 0; i < value.length; i++) { regStr = regStr + '(' + value[i] + ')([\\s]*)'; //跨字匹配 } let reg = new RegExp(regStr); for (let i = 0; i < this.info.xmlList.length; i++) { let name = this.info.xmlList[i].monitorPointName; //按照名字匹配 let regMatch = name.match(reg); if (null !== regMatch) { // 将匹配的数据放入结果列表中 this.xmlListRst.push(this.info.xmlList[i]); } } this.$refs.refTree.setTreeList( this.xmlListRst.map(i => ({ ...i, id: i.monitorPointId, key: i.monitorPointId, title: i.monitorPointName })) ); } }, // 关闭弹框 handleCloseVisibleMethod() { this.SET_XMLVISIBLE(false); this.SET_METHODROUTEBEFORE(''); } }, destroyed() { window.removepano('pano'); } }; </script> <style lang="less" scoped> #pano { height: 100%; width: 100%; } .ant-menu-inline { overflow: auto; } .ant-layout-has-sider { height: 100%; .ant-layout-sider-dark { height: 100%; overflow: auto; } } .ant-layout-sider-trigger { left: 62px; } .ant-layout-sider-dark { border-left: 1px #001529 solid; .ant-input { font-size: 12px; background-color: #202226; border: 1px solid #001529; color: white; } .ant-input:hover { border-color: #1890ff; } .ant-input-search-icon { color: white; } } .ant-menu-item-selected { background-color: #1890ff !important; } .div-krpano { height: 85vh; } </style>
后面再贴一下实现效果图
Recommend
-
120
-
103
-
61
百度百科用200亿像素重现秦始皇兵马俑,所及之处,纤毫毕现!
-
33
Evan You 刚刚发布了最新的 Vue 3 和他在 Vue Toronto 的演讲内容: Tweet PPT Vue 3.0 将会发生什么? 更快 更小 更易维护 更易于原生 让开发者更爽 Virtual DOM 完全重写,mountin
-
7
Cointelegraph中文HUB | PolkaFantasy是如何通过GameFi构建跨链NFT市场的? - 耳朵财经 Cointelegraph中文HUB | PolkaFantasy是如何通过GameFi构建跨链NFT市场的? 耳朵财经...
-
8
vue3通过Proxy+Reflect实现响应式,vue2通过defineProperty来实现ProxyProxy是什么Proxy是ES6中增加的类,表示代理。如果我们想要监听对象的操作过程,可以先创建一个代理对象,之后所有对于对象的操...
-
1
囧克斯 这里是勾三股四的家
-
1
通过断点跟踪探索Vue响应原理 September 1, 2018 Vue
-
5
此文我首发于CSDN(所以里面的图片有它的水印) 趁着隔离梳理一下之前做的一个有用的功能:在浏览器中去切割多分辨率瓦片图 这是一个有趣的过程,跟我一起探索吧 阅读本文需具备前置知识:对krpano有所了解,如:...
-
4
【笔记】解决通过 CUPS 打印的中文乱码问题 捕捉一只爱折腾的绯鞠
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK