Krpano:打造全景漫游体验—全景开发(三)

本文介绍了如何使用krpano技术在全景预览中实现用户可自定义的初始视角、视角范围大小和限制条件,包括水平/垂直视角调整,通过HTML和XML文件操作view元素及组件设置详细步骤。
摘要由CSDN通过智能技术生成

前言

在我们生成全景预览的时候,用户观看的视角是固定的,因为在创建全景作品的时候对于视角的设置会给一个默认值,对于用户观看的方向和距离,我们想要有更多的设置,例如初始视角视角的范围大小水平/垂直的视角限制都可以自定义修改,这篇文章就来实现自定义每个场景的视角

code.png

效果预览

krpano自定义视角demo

1.制作定义视角框

首先制作视频中的红白色的框框,用来定义初始的视角

image.png

但是发现使用html制作的框,在框内拖动不了全景,所以得使用krpano来制作,新建一个xml文件,命名为perspective.xml,并在主xml文件里引入,设置一个layer元素命名为view_bar,宽度为屏幕的60%,高度为屏幕的70%,并且设置bgborder属性为layer元素添加白色的虚线边框

在view_bar里再添加四个layer,代表四个角,最后在添加一个命名为view_bar_btn的layer元素,固定在定义视角框的底部,作为设置初始视角的交互按钮

<krpano>
  <layer name="view_bar" type="container" keep="true" width="60%" height="70%" bgborder="2 0xffffff 1 dashed" align="top" y="10%" scalechildren="true" visible="false">
    <layer name="view_bar_tl" type="container" keep="true" width="50" height="50" bgborder="4,0,0,4 0xD6000F 1" bgroundedge="5 0 0 0" align="lefttop"></layer>
    <layer name="view_bar_tr" type="container" keep="true" width="50" height="50" bgborder="4,4,0,0 0xD6000F 1" bgroundedge="0 5 0 0" align="righttop"></layer>
    <layer name="view_bar_bl" type="container" keep="true" width="50" height="50" bgborder="0,0,4,4 0xD6000F 1" bgroundedge="0 0 0 5" align="leftbottom"></layer>
    <layer name="view_bar_br" type="container" keep="true" width="50" height="50" bgborder="0,4,4,0 0xD6000F 1" bgroundedge="0 0 5 0" align="rightbottom"></layer>
    <layer name="view_bar_btn" type="container" keep="true" width="180" height="30" bgcolor="0xD6000F" bgalpha="1.0" bgroundedge="4" align="bottom" y="40">
      <layer
        name="view_bar_text"
        type="text"
        keep="true"
        html="设置当前视角为初始视角"
        css="font-size:14px;color:#ffffff;"
        align="center"
        bgalpha="0"
      />
    </layer>
  </layer>
</krpano>

2.设置初始视角

在全景中用户的观看方向是由view元素决定的,它可用于设置启动视图设置,view元素可以说是一个全局标签,有且只能有一个,元素的更多说明可以查看文档

为了便于区分当前的视角和初始视角,在右边的操作栏里新增一个当前初始视角的场景

image.png

直接引入定义好的组件,传入当前场景的id(scene)和目标html元素id(target),以及krpano回调(onPanoReady),具体如何定义通用的Krpano组件可以参考这篇文章

import Krpano from '@/components/Krpano'

<Krpano
    scene={scene.scene_id ? scene.scene_id + '_view' : ''}
    target="krpano_view"
    onPanoReady={onPanoReady}
/>

当回调触发就可以加载当前初始场景了,直接将手动生成的案例代码复制过来

image.png

根据当前场景的参数设置对应的属性

const onPanoReady = (e: any) => {
    const content = `
      <control bouncinglimits="calc:image.cube ? true : false" />
      <view hlookat="${scene.view.hlookat}" vlookat="${scene.view.vlookat}" fovtype="MFOV" fov="${scene.view.fov}" maxpixelzoom="${scene.view.maxpixelzoom}" fovmin="${scene.view.fovmin}"
        fovmax="${scene.view.fovmax}" hlookatmin="${scene.view.hlookatmin}" hlookatmax="${scene.view.hlookatmax}" vlookatmin="${scene.view.vlookatmin}" vlookatmax="${scene.view.vlookatmax}" limitview="lookat" />
      <preview url="https://oss-krp.oss-cn-shenzhen.aliyuncs.com${scene.path}/preview.jpg" />
      <image>
        <cube url="https://oss-krp.oss-cn-shenzhen.aliyuncs.com${scene.path}/%s/l%l/%v/l%l_%s_%v_%h.jpg" multires="${scene.multires}" />
      </image>
    `
    // 设置场景title属性
    e.set(`scene[${scene.scene_id}_view].title`, scene.name)
    // 设置场景缩略图
    e.set(
      `scene[${scene.scene_id}_view].thumburl`,
      `https://oss-krp.oss-cn-shenzhen.aliyuncs.com${scene.thumbUrl}`
    )
    // 设置场景内容
    e.set(`scene[${scene.scene_id}_view].content`, content)
    // 固定视角禁止移动和缩放
    e.set('control.usercontrol', false)
    setViewKp(e)
}

然后为定义视角框里的按钮绑定点击事件,返回当前视角的垂直视角和水平视角,通过get方法可以获取到

<krpano>
  <layer name="view_bar" type="container" keep="true" width="60%" height="70%" bgborder="2 0xffffff 1 dashed" align="top" y="10%" scalechildren="true" visible="false">
    // ....
    <layer name="view_bar_btn" type="container" keep="true" width="180" height="30" bgcolor="0xD6000F" bgalpha="1.0" bgroundedge="4" align="bottom" y="40">
      <layer
        name="view_bar_text"
        type="text"
        keep="true"
        html="设置当前视角为初始视角"
        css="font-size:14px;color:#ffffff;"
        align="center"
        bgalpha="0"
        onclick.addevent="js(handleViewSetting(get(view.hlookat),get(view.vlookat)))"
      />
    </layer>
  </layer>
</krpano>

当点击按钮的时候修改当前场景的hlookat和vlookat,并且监听这两个值,发生变化重新设置垂直视角和水平视角

useEffect(() => {
    if (viewKp) {
        viewKp.set(`view.hlookat`, scene.view.hlookat)
        viewKp.set(`view.vlookat`, scene.view.vlookat)
    }
}, [scene.view.hlookat, scene.view.vlookat])

window.handleViewSetting = (hlookat: number, vlookat: number) => {
    const sceneList = [...workConfig.scene]
    const index = sceneList.findIndex((item) => item.scene_id === selectSceneId)
    sceneList[index].view.hlookat = Math.floor(hlookat)
    sceneList[index].view.vlookat = Math.floor(vlookat)
    setWorkConfig((prevConfig) => ({
      ...prevConfig,
      scene: sceneList
    }))
}

再给初始视角场景添加一个回到初始视角的功能

<Button
    className="init-perspective-button"
    type="primary"
    size="small"
    onClick={handleViewReset}
>
    回到初始视角
</Button>
kp.call(`reset_view(${view.hlookat},${view.vlookat},${view.fov})`)
const handleViewReset = () => {
    kp.call(`reset_view(${view.hlookat},${view.vlookat},${view.fov})`)
}

// xml中添加一个action
// 初始视角重置
<action name="reset_view" scope="local">
        tween(view.hlookat | view.vlookat | view.fov, %1 | %2 | %3,1.5);
</action>

在这里插入图片描述

2.设置视角的范围

场景当前观看的范围和范围的大小都是通过view元素的fov,fovmin和fovmax设置的,我们通过antd的Slider组件来绑定这三个属性

<Card bordered={false} className="pano-view-card" style={{ background: '#282828' }}>
    <div className="f14 mb15">视角 (FOV) 范围</div>
    <Slider
        min={0.1}
        max={180}
        range
        marks={{
        0.1: '最近',
        180: '最远'
        }}
        step={0.1}
        defaultValue={[scene.view.fovmin, scene.view.fov, scene.view.fovmax]}
        onChange={handleFovChange}
    />
</Card>

当Slider的值发生改变时,触发onChange事件,拿到改变后的值通过set方法修改场景当前观看的范围和范围的大小

const handleFovChange = (value: number[]) => {
    const sceneList = [...workConfig.scene]
    const index = sceneList.findIndex((item) => item.scene_id === selectSceneId)
    if(index === -1) return
    if (sceneList[index].view.fov !== value[1]) {
        kp.set(`view.fov`, value[1])
    } else if (sceneList[index].view.fovmin !== value[0]) {
        kp.set(`view.fovmin`, value[0])
        kp.set(`view.fov`, value[0])
    } else if (sceneList[index].view.fovmax !== value[2]) {
        kp.set(`view.fovmax`, value[2])
        kp.set(`view.fov`, value[2])
    }
}

在这里插入图片描述

3.设置观看范围

限制观看的垂直视角通过vlookatmax,vlookatmin这两个属性来限制,代表最小垂直观察位置和垂直水平观察位置,可设置的值为-90到90之间

水平视角则是通过hlookatmax,hlookatmin这两个属性来限制,代表最小水平观察位置和最大水平观察位置,可设置的值为-180到180之间

也是通过Slider组件来设置这些属性,和视角的范围的设置一样

<Card bordered={false} className="pano-view-card" style={{ background: '#282828' }}>
    <div className="f16 mb15">视角限制</div>
    <div className="f14 mb15">水平视角限制</div>
    <Slider
        min={-180}
        max={180}
        range
        marks={{
            '-180': '-180',
            180: '180'
        }}
        defaultValue={[scene.view.hlookatmin, scene.view.hlookatmax]}
        onChange={handleHlookChange}
    />
    <div className="f14 mb15">垂直视角限制</div>
    <Slider
        min={-90}
        max={90}
        range
        marks={{
            '-90': '-90',
            90: '90'
        }}
        defaultValue={[scene.view.vlookatmin, scene.view.vlookatmax]}
        onChange={handleVlookChange}
    />
</Card>
const handleHlookChange = (value: number[]) => {
    const sceneList = [...workConfig.scene]
    const index = sceneList.findIndex((item) => item.scene_id === selectSceneId)
    if (sceneList[index].view.hlookatmin !== value[0]) {
      kp.set(`view.hlookatmin`, value[0])
      kp.set(`view.hlookatmax`, value[1])
      kp.set(`view.hlookat`, value[0])
    } else if (sceneList[index].view.hlookatmax !== value[1]) {
      kp.set(`view.hlookatmin`, value[0])
      kp.set(`view.hlookatmax`, value[1])
      kp.set(`view.hlookat`, value[1])
    }
  }
  const handleVlookChange = (value: number[]) => {
    const sceneList = [...workConfig.scene]
    const index = sceneList.findIndex((item) => item.scene_id === selectSceneId)
    if (sceneList[index].view.vlookatmin !== value[0]) {
      kp.set(`view.vlookatmin`, value[0])
      kp.set(`view.vlookatmax`, value[1])
      kp.set(`view.vlookat`, value[0])
    } else if (sceneList[index].view.vlookatmax !== value[1]) {
      kp.set(`view.vlookatmin`, value[0])
      kp.set(`view.vlookatmax`, value[1])
      kp.set(`view.vlookat`, value[1])
    }
  }

在这里插入图片描述

结尾

以上就是我对场景视角设置的实现,如果还有更好的方式也欢迎大家一起分享交流,学习学习😊🤞💋😘

  • 35
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值