更新于 2020.11.19 krpano 1.20.9
1.20默认皮肤自定义地图
krpano 1.20版本提供了在默认皮肤这能够添加自定义地图的方式,也即是如果你不使用在线地图,可以利用原有默认皮肤中地图按钮(地球图标),点击后会弹出在线地图,该地图可实现拖拽以及基本的位置标识。
1.20默认皮肤自定义地图使用方法
使用MAKE VTOUR droplet.bat生成默认皮肤,打开tour.xml,找到下面skin_settings代码,如果使用默认皮肤的自定义地图的话,可直接使用下面的设置,api_key不要填写。
1 2 3 4 5 6 |
<skin_settings maps="true" maps_type="" maps_bing_api_key="" maps_google_api_key="" maps_zoombuttons="false" maps_loadonfirstuse="true" |
然后在scene标签外加入下面代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<!-- add a custom map (container+scrollarea+image) --> <layer name="skin_layer"> <layer name="skin_scroll_window"> <layer name="skin_scroll_layer"> <layer name="skin_scroll_container"> <layer name="skin_map_container"> <layer name="skin_map" type="container"> <layer name="skin_map_scrollarea" url="%VIEWER%/plugins/scrollarea.js" align="center" width="100%" height="100%"> <layer name="skin_map_image" url="corfumap.jpg" align="center" onloaded="copy(layer[skin_map_scrollarea].width, width); copy(layer[skin_map_scrollarea].height, height); layer[skin_map_scrollarea].update();"> <layer name="mapspot1" style="mapspot" x="16.93%" y="14.80%" linkedscene="scene_canaldemure5" /> <layer name="mapspot2" style="mapspot" x="52.34%" y="14.50%" linkedscene="scene_kalamaki-strand" /> <layer name="mapspot3" style="mapspot" x="58.72%" y="16.40%" linkedscene="scene_kassiopi-felsen" /> <layer name="mapspot4" style="mapspot" x="48.57%" y="24.00%" linkedscene="scene_pantokrator-antenne" /> <layer name="mapspot5" style="mapspot" x="58.85%" y="47.30%" linkedscene="scene_korfu-stadt-alte-festung-ganz-oben" /> <layer name="mapspot6" style="mapspot" x="54.43%" y="58.60%" linkedscene="scene_achilleion-hof-unten" /> </layer> </layer> </layer> </layer> </layer> </layer> </layer> </layer> <style name="mapspot" style="skin_tooltips" url="skin/vtourskin_mapspot.png" align="lefttop" edge="bottom" scale="0.5" onover.addevent="tween(scale,0.55,0.2);" onout.addevent="tween(scale,0.5,0.2);" tooltip="" onloaded.addevent="copy(tooltip, scene[get(linkedscene)].title);" onclick="skin_showmap(false); skin_gotoscene(get(linkedscene));" /> |
需要修改的是上面高亮的9-15行。其中skin_map_image是自定义地图本身所用的图片,在url属性中修改为你要用的自定义地图的图片路径。
然后从mapspot1到mapspot6是对应的六个地图点,每个地图点对应各自要跳转的场景。如果你需要在地图内放入六个地图点,那么就是mapspot1到mapspot6。如果是四个地图点,就是mapspot1到mapspot4,按照你所需要的数量,对范例中的layer进行删减。
x和y是地图点对应地图本身的相对位置,这里是按照百分比,也就是如果地图宽度为1000,高度为1000,若x为16.93%,y为14.80%,则实际上x的数值为169.3,y的数值为148。
要获取这个百分比数值,可以在ps软件中打开地图图片,然后将信息窗口中的单位设置为百分比,通过鼠标移动到图上对应的位置,并查看相应的百分比值,即x和y。
每个layer的linkscene自定义属性即这个地图点被点击后要跳转到的scene的name。
如果需要修改地图点的样式,可找到url=”skin/vtourskin_mapspot.png”,也即是mapspot的style元素,修改其中的url属性。
方法1在线演示
方法1案例下载
链接:http://pan.baidu.com/s/1c0hlxao 密码:mp9j
方法1代码说明
自定义地图,非必应地图、谷歌地图或者百度地图这些我们常常使用的在线地图。自定义地图就是针对我们所拍摄场景的一张地图,例如房地产项目的户型图、酒店的平面图、景区的景区地图等等。通常也就是一张或若干张图片,一般为png带有透明通道的图片。拿本人最熟悉的房地产项目来说,拍的是一个简单的两房户型,拍了三个场景,包括客厅和两个卧室。那么我就希望在全景界面的左上角可以显示该户型的户型图,同时在我浏览场景时,户型图对应的热点有相应的变化,我不仅可以通过底部的缩略图切换不同的场景,还可以通过点击户型图上的热点来切换。这就是自定义地图的基本功能。
官方也是有一个案例的,它的位置在 examples\virtual-tours\scenes-with-imagemap-2
当我们将官方的自定义地图硬生生地搬到了自己的项目里,对于第一次看到这种情景的人,必然是满心欢喜,随着视角的变化,雷达的方向和扇形面积也随之变化,似乎真有一种“实时监控”的感觉。但没过几分钟,你就想该如何更换成自己的图片,更换成自己的地图点图标。
最快的方法,当然是针对map的url以及spot的url进行更改。而且你还可以按照我在该教程中的注释试着修改颜色、尺寸等属性,你可以将它放在画面中部,你也可以使用其他颜色做为容器背景。但如果你要面对的是上百个场景,可以想象单单是地图点的spot就有很多重复粘贴的工作。明明这里可以用一个style就可以解决的事情,我们不可能不用啊。因为官方案例几个地图点都是不同的图片,因此弃之不用也情有可原。另外spot1、spot2、spot3这些命名方式非常有规律,我们是否可以利用呢?有必要每次都要在scene的onstart里写这么多spot么?
今天我们就来对其改造吧。我们首先用自己的图片,暂时借用skin文件夹里的两个地图点图片。把图放在了左上角。你可以直接下载案例。
从演示中可以看到,激活地图点(绿色)完全替代了地图点(蓝色),相比起仅仅附加一个红点,更符合普通大众的习惯。我们来看代码。
点击代码窗口最右侧按钮,在新窗口打开后复制代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
<!-- 自定义地图开始, mapcontainer是一个半透明容器container,keep为true,确保了切换场景时地图不会被移除,mapcontainer是其它子layer的父亲,bgcolor以及bgalpha是颜色和透明度的设定,通过改动align以及xy坐标可以确定地图的位置,通过改变width和height确定该矩形的宽度和高度,--> <layer name="mapcontainer" keep="true" type="container" bgcolor="0x000000" bgalpha="0.5" align="lefttop" x="0" y="0" width="264" height="264"> <!-- map的url属性可以改成我们自己的地图文件,align一定是lefttop,这是为了确定热点位置,其坐标系以左上角为0点,也是为了方便我们通过ps等方法来获取热点的值。--> <layer name="map" url="skin/b1map.png" align="top" x="4" y="4" width="prop" height="256" handcursor="false" scalechildren="true"> <!-- 雷达遮罩部分,确保了雷达的扇形不会超出范围,这里也就是地图map的范围。注意这里也应该是对齐左上角,下面的各种layer通通都是对齐左上角,不然坐标系不统一的话,就很难确定热点的位置 --> <layer name="radarmask" type="container" align="lefttop" width="100%" height="100%" maskchildren="true"> <!-- 雷达插件 zoder=1 在开始时为隐藏,只有激活activetespot这个action时才会显示 zorder为叠放次序 数字越大越靠前 --> <layer name="radar" visible="false" url="%SWFPATH%/plugins/radar.swf" alturl="%SWFPATH%/plugins/radar.js" align="lefttop" edge="center" zorder="1" scale="0.3" fillcolor="0xFFFFFF" fillalpha="0.8" linecolor="0xFF0000" linewidth="0.5" linealpha="0.5" headingoffset="0" /> <!-- 热点 zorder=2,用style来统一处理 所有layer都载入了一个名为spot的style,注意这里spot是由0开始,而不是由1开始的,因此在一般情况下,地图点与场景一一对应,而场景的index是从0开始的,所以我们可以利用这一点提高代码的可读性--> <layer name="spot0" style="spot" x="113" y="124" /> <layer name="spot1" style="spot" x="94" y="62" /> <layer name="spot2" style="spot" x="55" y="34" /> <layer name="spot3" style="spot" x="13" y="58" /> <!-- 激活的热点 zorder=3 开始时候隐藏,在这里是一个绿色的地图点, 表示当前的场景--> <layer name="activespot" url="skin/vtourskin_mapspotactive.png" scale="0.5" oy="-17" align="lefttop" edge="center" zorder="3" visible="false"/> </layer> </layer> </layer> <!-- 地图点中相同的代码,都写在了style里面,修改的时候只需要修改style里面的代码,提高了效率。在onclick里,先是用subtxt得出spot后面的数字,也就是index,然后检查是否点击的热点就是当前场景,因为没有必要点击当前场景的热点又载入一遍,如果是点击其他的热点,则载入其他场景,载入场景的loadscene中利用了之前得到的spotid,这样就不用每次都写场景的名字了。--> <style name="spot" url="skin/vtourskin_mapspot.png" scale="0.5" oy="-17" align="lefttop" edge="center" zorder="2" onclick="subtxt(spotid,get(name),4,2);if(spotid != scene[get(xml.scene)].index, loadscene(get(scene[get(spotid)].name),null,MERGE,BLEND(1)); );" /> <!-- 激活热点 - %1 = 当前雷达的方向值heading --> <action name="activatespot"> <!-- 因此绿色地图点会在每次激活时替换蓝色普通地图点,因此每次激活之前,首先保证所有蓝色地图点是可见的,如果没有下面这个代码,则会使得上一个场景的蓝色地图点消失,这里用的是一个循环语句--> for(set(i,0),i LT scene.count,inc(i), txtadd(spotname,'spot',get(i)); set(layer[get(spotname)].visible, true); ); <!-- 将当前热点的坐标复制到雷达和激活点的坐标,直接利用当前场景的index,反过来得到layer的名字,这样就使得这个activetespot的参数只要一个就可以了--> txtadd(spotidnow,'spot',get(scene[get(xml.scene)].index)); copy(layer[radar].x, layer[get(spotidnow)].x); copy(layer[radar].y, layer[get(spotidnow)].y); copy(layer[activespot].x, layer[get(spotidnow)].x); copy(layer[activespot].y, layer[get(spotidnow)].y); <!-- 将第二个参数赋值到雷达的heading --> set(layer[radar].heading, %1); <!-- 显示雷达和绿色激活热点,以及隐藏当前场景的地图点 --> set(layer[radar].visible, true); set(layer[activespot].visible, true); set(layer[get(spotidnow)].visible, false); </action> |
另外,我们只需要在scene标签中的activetespot里写一个参数,也就是保留后面的heading值,不用再把spot1之类的name写上,毫无疑问这样提高了我们的工作效率。
点击代码窗口最右侧按钮,在新窗口打开后复制代码
1 |
<scene name="scene_2kt" title="2kt" onstart="activatespot(90);" thumburl="panos/2kt.tiles/thumb.jpg" lat="" lng="" heading=""> |
那么回头来看那几个普通的地图点,该如何确定X和Y坐标。打开PS,将map图片拖到软件里,让信息窗口打,并使得单位(点击加号)切换成像素。让鼠标放在你想要的位置上,就可以看到在信息窗口中出现XY的坐标,然后将其对应地写在xml文件。例如我们把鼠标放在图片的客厅拍摄点上,信息窗口的像素显示为X:114 Y:124,那么我们就对应地把坐标值写在代码里。
雷达heading值的获得请看关于雷达插件的介绍。
方法2官方下载包路径
你电脑的路径\krpano-1.20\viewer\examples\demotour-winecellar\ (1.20)
提示:如果不明白下载包路径是什么,请查看 循序渐进(3)- krpano下载包的使用说明
方法2在线演示
方法2代码说明
下面的代码把每个场景自身的hotspot部分去掉了,尽可能地简化了步骤。
点击代码窗口最右侧按钮,在新窗口打开后复制代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
<krpano> <!-- 加载第一个场景 --> <action name="startup" autorun="onstart"> loadscene(scene_mitte, null, MERGE); </action> <!-- 代码复制 开始位置 --> <!-- 地图部分 url对应的是地图本身的路径,按照自己的文件修改url中数值 --> <layer name="map" url="skin/inmap.png" keep="true" handcursor="false" capture="false" align="leftbottom" scale="0.25" scalechildren="true" onclick="openmap();" > <!-- 激活点图像 (覆盖在普通的地图点上) --> <layer name="activespot" url="skin/camicon_red.png" align="lefttop" edge="center" zorder="2" scale.mobile="2" /> <!-- 雷达 (也覆盖在地图点上, 但在激活点图像后面) --> <layer name="radar" url.flash="%SWFPATH%/plugins/radar.swf" url.html5="%SWFPATH%/plugins/radar.js" align="lefttop" edge="center" zorder="1" scale.mobile="1.5" fillalpha="0.5" fillcolor="0x7F5F3F" linewidth="1.0" linecolor="0xE0E0A0" linealpha="0.5" /> <!-- 地图点图像部分 url可以设置 用style来统一处理 所有layer都载入了一个名为mapspot的style,注意这里spot是由0开始,而不是由1开始的,因此在一般情况下,地图点与场景一一对应,而场景的index是从0开始的,所以我们可以利用这一点提高代码的可读性 --> <layer name="spot0" style="mapspot" x="474" y="314" zorder="1" onclick="mapspot_loadscene();" /> <layer name="spot1" style="mapspot" x="172" y="488" zorder="1" onclick="mapspot_loadscene();" /> <layer name="spot2" style="mapspot" x="732" y="315" zorder="1" onclick="mapspot_loadscene();" /> </layer> <style name="mapspot" url="skin/camicon.png" align="lefttop" edge="center" scale.mobile="2" /> <!-- 地图打开部分 - 缩放到100% (如果屏幕小的话则可能更小) --> <action name="openmap"> set(layer[map].onclick, closemap(); ); layer[map].changeorigin(center,center); set(bigscale,1); if(layer[map].imagewidth GT stagewidth, div(bigscale, stagewidth, layer[map].imagewidth); ); tween(layer[map].x, 0); tween(layer[map].y, 0); tween(layer[map].scale, get(bigscale)); </action> <!-- 地图关闭部分 - 缩放到自身尺寸的四分之一 --> <action name="closemap"> set(layer[map].onclick, openmap(); ); layer[map].changeorigin(leftbottom,leftbottom); tween(layer[map].x, 0); tween(layer[map].y, 0); tween(layer[map].scale, 0.25); </action> <!-- 当点击地图点时执行的动作 --> <action name="mapspot_loadscene"> subtxt(spotid,get(name),4,2); if(layer[map].scale GT 0.25, <!-- 当地图放大时需要执行更多特殊的动作,缩小地图等 --> set(layer[map].enabled, false); tween(layer[map].alpha, 0.0, 0.25, default, if(spotid != scene[get(xml.scene)].index, loadscene(get(scene[get(spotid)].name),null,MERGE,BLEND(1)); ); set(layer[map].onclick, openmap(); ); layer[map].changeorigin(leftbottom,leftbottom); set(layer[map].x, 0); set(layer[map].y, 0); set(layer[map].scale, 0.25); set(events[sceneload].onloadcomplete, delayedcall(1, tween(layer[map].alpha, 1.0, 0.5, default, set(layer[map].enabled, true); ); ); ); ); , <!-- 小地图时只需要载入场景 --> if(spotid != scene[get(xml.scene)].index, loadscene(get(scene[get(spotid)].name),null,MERGE,BLEND(1)); ); ); </action> <!-- 指定激活点和雷达点的父元素 设定雷达点的heading,这个在每个scene加载时都要执行一次--> <action name="updateradar"> <!-- 因此绿色地图点会在每次激活时替换蓝色普通地图点,因此每次激活之前,首先保证所有蓝色地图点是可见的,如果没有下面这个代码,则会使得上一个场景的蓝色地图点消失,这里用的是一个循环语句--> for(set(i,0),i LT scene.count,inc(i), txtadd(spotname,'spot',get(i)); set(layer[get(spotname)].visible, true); ); <!-- 将当前热点的坐标复制到雷达和激活点的坐标,直接利用当前场景的index,反过来得到layer的名字,这样就使得这个activetespot的参数只要一个就可以了--> txtadd(spotidnow,'spot',get(scene[get(xml.scene)].index)); copy(layer[radar].x, layer[get(spotidnow)].x); copy(layer[radar].y, layer[get(spotidnow)].y); copy(layer[activespot].x, layer[get(spotidnow)].x); copy(layer[activespot].y, layer[get(spotidnow)].y); <!-- 将第二个参数赋值到雷达的heading --> set(layer[radar].heading, %1); <!-- 显示雷达和绿色激活热点,以及隐藏当前场景的地图点 --> set(layer[radar].visible, true); set(layer[activespot].visible, true); set(layer[get(spotidnow)].visible, false); </action> <!-- 代码复制结束部分 --> <!-- scene的部分,注意在onstart中写updateradar(-1.92);括号的数字是heading数值 --> <scene name="scene_mitte" onstart="updateradar(-1.92);"> <view hlookat="202.65" vlookat="8.12" fov="105.5" maxpixelzoom="2.0" fovmin="60" fovmax="120" /> <preview url="panos/mitte.tiles/preview.jpg" /> <image> <cube url="panos/mitte.tiles/pano_%s.jpg" /> </image> </scene> <scene name="scene_ecke" onstart="updateradar(87.10);"> <view hlookat="-151.42" vlookat="4.18" fov="99.5" maxpixelzoom="2.0" fovmin="60" fovmax="120" /> <preview url="panos/ecke.tiles/preview.jpg" /> <image> <cube url="panos/ecke.tiles/pano_%s.jpg" /> </image> </scene> <scene name="scene_glastuer" onstart="updateradar(-91.11);"> <view hlookat="-99.5" vlookat="21.1" fov="99.5" maxpixelzoom="2.0" fovmin="60" fovmax="120" /> <preview url="panos/glastuer.tiles/preview.jpg" /> <image> <cube url="panos/glastuer.tiles/pano_%s.jpg" /> </image> </scene> </krpano> |
步骤1
确保雷达插件radar.js、radar.swf复制到plugins文件夹里,如果没有的话,则到下载包的viewer下的plugins文件夹复制。将自己的地图图片、地图点图片、激活点图片复制到skin文件夹或自己知道的路径中。
步骤2
- 把上面代码中 从代码复制部分到代码复制结束部分之间的代码全部复制到scene标签的外部。
- 找到url=”skin/inmap.png” 将url中的数值修改为地图图片的路径
- 找到url=”skin/camicon.png” 将url中的数值修改为地图点的路径
- 找到url=”skin/camicon_red.png” 将url中的数值修改为地图点的路径
- spot0、spot1、spot2……是对应的scene的index为0、1、2,按照这个原则写layer。如何确定x和y坐标。打开PS,将map图片拖到软件里,让信息窗口打,并使得单位(点击加号)切换成像素。让鼠标放在你想要的位置上,就可以看到在信息窗口中出现XY的坐标,然后将其对应地写在xml文件。例如我们把鼠标放在图片的客厅拍摄点上,信息窗口的像素显示为X:114 Y:124,那么我们就对应地把坐标值写在代码里。
步骤3
scene的部分,注意在每个scene的onstart中写updateradar(-1.92);括号的数字是heading数值。
像素比例是什么意思?
地图和图标的像素比例是多少,就是按照原始大小来的吗?
http://www.krpano360.com/subtxtdongzuowanquanjiexi/
有专门的链接,可以通过搜索 关键字找到的 请善用
Subtxt来确定index,理解不了,能解析下没