Skip to content

Krpano全景图开发入门

Published: at 15:19

实现全景图的方式很多,但是目前国内最流行的成熟方案要数 Krpano。Krpano 提供了一系列工具来用于全景图的制作和播放,更重要的是 Krpano 的播放器有着灵活的编程接口,使得我们能够对全景图进行扩展和定制。

本文介绍如何基于 Krpano 进行全景图开发。

一、使用 Krpano 播放器展示一个全景图

krpano 提供的播放器有 Flash 和 HTML5 两种版本,我们主要使用 HTML5 版本。

启动播放器

使用 Krpano 展示一个全景图只需要以下材料:

播放器需要挂载到页面上的一个元素上,页面在引入 krpano.js 之后需要通过 embedpano() 方法配置播放器的挂载点和一系列参数,embedpano() 支持的所有参数可以在官方的 Embedding Parameters 部分查看。

虽然配置中唯一必须的是用于指定挂载点 id 的 target 属性,但是想要播放全景图还需要在 xml 属性中指定 Krpano XML 的路径。

<body>
  <div id="mount" style="position: absolute; width: 100%; height: 100%;"></div>
  <script src="../krpano-lib/krpano.js"></script>
  <script>
    var swfPath = '../krpano-lib/krpano.swf';
    var xmlPath = './krpano.xml';
    embedpano({
      // 引入krpano.js后获得的全局方法
      swf: swfPath, // flash模式下用到的swf文件,非必须
      xml: xmlPath, // 全景图xml路径,用于描述整个全景图
      target: 'mount', // 挂载点id,唯一必须的参数
      html5: 'prefer', // krpano支持flash和html5两种模式,此属性确定是否优先用html5,具体规则见:https://krpano.com/docu/html/#html5
      onready() {
        // 回调函数,类似的还有onerror
        console.log('load krpano success!');
      },
    });
  </script>
</body>

接下来编写我们的全景图 xml,来描述我们的全景图。常用的 krpano 元素有很多,我们先用其中最基本的几个搭建一个只有最基本的预览图的全景图。最基本的 xml 如下:

<krpano>
 <!-- 预览图,目前使用网格预览 -->
 <preview type="grid(cube,64,64,512,0xCCCCCC,0xF6F6F6,0x999999);" />

 <!-- view/fov设置 -->
 <view hlookat="0" vlookat="0" fovtype="VFOV" fov="90" fovmin="30" fovmax="150" />
</krpano>

可以看到 krpano xml 和标准的 xml 语法基本一致。此外,krpano xml 还有以下几个特点:

此时效果很简单,就是一个空旷的网格空间,可以拖动、缩放:

代码

这样的网格空间显然不是我们想要的全景图,我们还需要为其添加全景图片。全景图片有多种形式,常见的是六面图(Cube)和鱼眼图(Fisheye)。不同的图片引入的方式略有不同,接下来主要讲解六面图的使用。

首先在 xml 中添加一个 <image> 标签,作为图片显示的容器,然后根据图片类型添加子元素 <cube>,表示我们使用的是六面图。接着设置六面图的 url。url 中比较特殊的是 %s 占位符,在程序实际运行时将会被替换为 f,b,l,r,t,d 六个字符,替换后的结果分别作为前后左右上下六个方向的图片。

  <image>
    <cube url="https://qhyxpicoss.kujiale.com/r/2017/09/01/L3D221IS3QKUQUQBOGAPEK3P3XU888_7500x1250.jpg_%s" />
  </image>

这时候已经可以算是一个最基本的全景图了。

代码

坐标系和视角

可以看到,之前的全景图 xml 中还有一个 <view> 元素。这个元素描述了用户观测相关的信息(视角、fov 等),类似于相机设置。

在解释视角设置之前,先介绍下 krpano 的坐标系统。

在 krpano 全景图中,无论使用的是什么类型的图片,都会被映射到一个球面中。因此 Krpano 使用球坐标系来表示空间内的一个点。其中半径 r 是固定的,使用方位角和仰角的组合 (h, v) 来确定全景图内的一个点。六面体正前方图片 f 的中心和坐标原点重合。

我们在 <view> 元素上设置了多个属性,其中最重要的是:

下面的例子提供了视角数据的实时显示:

代码

此外,还可以通过 <view> 元素对用户的视角进行一些限制。例如 fovmin,fovmax 等属性可以用于限制用户调节 fov 的范围。

二、通过热点和事件与全景图交互

我们已经有了一个简单的全景图,但是和线上的全景图相比,还少了很多和用户交互的内容。这一节主要介绍如何为全景图添加热点和响应事件。

热点

热点是对全景图的标注,会随着全景图的旋转而运动。Krpano 中的热点有两种:

接下来以图片热点为例进行讲解,其他类型热点的使用可以参考官方文档中的对应章节。下面的图片热点的 xml 包含了热点最基本的几个参数

<hotspot
    name="image_hotspot"
    url="https://xxxx.xxx.com/hotspot/hs_001.png"
    ath="10"
    atv="10"
/>

热点之所以叫 “热点”,是因为用户可以与其交互。热点支持一系列的事件,最常用的是 onclick,一般会在点击热点时触发场景切换等行为。

<hotspot
     onover=""
     onhover=""
     onout=""
     ondown=""
     onup=""
     onclick=""
     onloaded=""
/>

和 html 元素的事件类似,在事件的回调中可以调用 krpano 脚本的方法,如调用 loadScene() 方法加载新的场景,或是使用 js() 方法来调用 JavaScript 中定义的方法。

事件

热点和其他元素支持的事件只有和其交互相关的一部分,对于 krpano 本身的事件,我们需要使用 <event> 元素来进行回调的设置。

krpano 的事件分为两大类:

无论是全局事件还是局部事件,都支持一系列不同作用的事件。可以在官方文档的 events 的介绍中找到支持的事件的列表

例如,下面这段代码定义个一个局部事件元素,使得当前的场景内每次点击鼠标都会调用 JavaScript 的 console.log () 方法。

<events
 name="localEvents"
 onmousedown="js(console.log('message from local events'));"
/>

结合事件和热点,我们可以实现在视角变化 (onviewchange) 的时候显示出当前的视角设置:

代码

三、场景

在我们之前的例子中,讲解了只包含一个场景的全景图如何定义。很多情况下,全景图是包含多个场景的,用户可以通过热点在多个场景中进行切换。在多场景的全景图中,使用 <scene> 元素来定义场景。每个场景可以具有自己独立的全景图片、热点、视角等内容。

<scene name="..." onstart="">
    <image>...</image>
   <hotspot>...</hotspot>
   <!-- other contents -->
</scene>

<scene> 中的内容在场景被加载之前不会载入,无法被访问。因此,需要调用 loadscene() 这个内置的方法来载入一个场景作为初始值。场景的切换和加载初始场景一样,都是调用 loadscene()

<krpano onstart="loadscene(scene1);">
 <scene name="scene1"></scene>
 <scene name="scene2"></scene>
  <view />
</krpano>

下面的这个例子结合了之前讲过的热点和场景加载切换,实现了一个基本的多场景全景图,使得用户能够点击热点切换场景。

<krpano onstart="loadscene(scene1);">
    <!-- grid preview pano -->
    <preview type="grid(cube,64,64,512,0xCCCCCC,0xF6F6F6,0x999999);" />
    <scene name="scene1">
        <image>
            <cube url="https://qhyxpicoss.kujiale.com/r/2017/09/01/L3D221IS3QKUQUQBOGAPEK3P3XU888_7500x1250.jpg_%s" />
        </image>
        <hotspot
            name="image_hotspot"
            type="image"
            url="https://720-cdn3.3vjia.com/Panorama/public3.2.2/hotspot/hs_001.png"
            ath="0"
            atv="0"
            onclick="loadscene(scene2);"
        />
    </scene>
    <scene name="scene2">
        <image>
            <cube url="https://qhyxpicoss.kujiale.com/r/2017/12/25/L3D221I5P2YEIUG5TL4MUG3P3XE888_7500x1250.jpg_%s" />
        </image>
        <!-- place your scene hotspots here -->
    </scene>
    <!-- view/fov settings -->
    <view hlookat="0" vlookat="0" fovtype="VFOV" fov="90" fovmin="30" fovmax="150" />
</krpano>

代码

四、与 JavaScript 交互

我们通常还需要让 krpano 和 JavaScript 代码进行交互,从而实现诸如热点开关、场景选择、点击热点打开弹窗展示详情等功能。

Krpano 调用 JavaScript

krpano 调用 JavaScript 主要使用以下几个函数:

JavaScript 操作 Krpano

想要使用 JavaScript 控制 krpano,需要得到 krpano Javascript-Interface object

这个对象可以通过两种方式得到:

这个对象对外暴露了以下几个方法:

一个基本的例子是通过 JavaScript 读取和设置 Krpano 当前的视角值

var swfPath = '../krpano-lib/krpano.swf';
var xmlPath = './krpano.xml';
var hlookat = document.querySelector('input[name="hlookat"]');
var vlookat = document.querySelector('input[name="vlookat"]');
var fov = document.querySelector('input[name="fov"]');
var buttonGet = document.querySelector('button[name="getview"]');
var buttonSet = document.querySelector('button[name="setview"]');

embedpano({
  swf: swfPath,
  xml: xmlPath,
  target: 'mount',
  html5: 'prefer',
  onready(krpano) {
    function getView() {
      hlookat.value = krpano.get('view.hlookat');
      vlookat.value = krpano.get('view.vlookat');
      fov.value = krpano.get('view.fov');
    }
    function setView() {
      krpano.set('view.hlookat', hlookat.value);
      krpano.set('view.vlookat', vlookat.value);
      krpano.set('view.fov', fov.value);
    }
    buttonGet.onclick = getView;
    buttonSet.onclick = setView;
    getView();
  },
});

更多的例子可以参考官方提供的 Demo,该 demo 展示了通过 JavaScript 操作全景图的效果。

五、更多内容

设备检测

很多时候,我们需要对不同平台或特性的设备进行差异化的配置,例如在浏览器不支持 webGL 的时候显示特定的提示元素或在 macOS 下停用自动旋转等。

krpano 内置了一定的设备检查能力,并提供了元素和属性两个层面的支持。

插件系统

krpano 支持很多官方和第三方插件,包括 WebVR、雷达图、陀螺仪、雨雪效果等。因为不同的插件使用方式不同,本文并没有对其进行讲解。

除了使用官方提供的插件以外,还可以使用 JavaScript 自行开发 krpano 插件

Actions/Scripting

krpano 支持在 XML 中使用一种简单的脚本语言来控制全景图,就好比 HTML 中使用 JavaScript,这让 Krpnao 制作的全景图有了更丰富的交互能力。类似于 HTML 中的 <script>,krpano 脚本在 XML 的 <action> 标签中定义。

需要注意的是,虽然 krpano 提供了这样的脚本语言,但是其能够实现的绝大多数功能都可以在 JavaScript 代码中通过操控 krpano 来实现,为了逻辑统一和代码的可维护性,推荐将这些逻辑写在 JavaScript 代码中。

下面的 action 示例定义了一个自动加载 startscene 指定的初始场景的脚本,其中使用了可选的 autorun 属性使得这段脚本会在应用启动时被自动触发。

<action name="startup" autorun="onstart">
 if(startscene === null OR !scene[get(startscene)], copy(startscene,scene[0].name); );
 loadscene(get(startscene), null, MERGE);
 if(startactions !== null, startactions() );
</action>

Action 的详细使用方法可以参考:https://krpano.com/docu/actions/#top

本文所有 demo 代码可在此处查看