@dage/krpano
将常用的标签使用 React
进行了组件化封装(MVVM 真香),并在实例上补充了 vtourskin
的功能,支持类型推断,基本满足开发需求。
krpano 1.19-pr13
import React, { useState, useMemo } from "react";
import {
Autorotate,
Krpano,
Scene,
View,
HotSpot,
Events,
SceneProps,
ROTATE_DIRECTION,
ZOOM_ACTION,
} from "@dage/krpano";
import { MouseHoldView } from "./components";
import "./index.less";
interface ISceneProps extends Partial<SceneProps> {
thumbUrl?: string;
}
const URL = "https://houseoss.4dkankan.com/project/leifeng-transfer";
const Demo = () => {
const [currentMenu, setCurrentMenu] = useState(0);
const [currentScene, setCurrentScene] = useState("center1");
const [autorotateEnable, setAutorotateEnable] = useState(false);
const CENTER_SCENE_LIST = useMemo<ISceneProps[]>(
() => [
{
name: "center1",
thumbUrl: URL + "/panos/center1.tiles/thumb.jpg",
previewUrl: URL + "/panos/center1.tiles/preview.jpg",
imageTagAttributes: {
type: "cube",
tileSize: 512,
multires: true,
},
images: [
{
tiledImageWidth: 2624,
tiledImageHeight: 2624,
url: URL + "/panos/center1.tiles/%s/l3/%v/l3_%s_%v_%h.jpg",
},
{
tiledImageWidth: 1280,
tiledImageHeight: 1280,
url: URL + "/panos/center1.tiles/%s/l2/%v/l2_%s_%v_%h.jpg",
},
{
tiledImageWidth: 640,
tiledImageHeight: 640,
url: URL + "/panos/center1.tiles/%s/l1/%v/l1_%s_%v_%h.jpg",
},
],
children: (
<>
<View
hlookat={0}
vlookat={0}
fovType="MFOV"
fov={120}
maxPixelZoom={2}
fovMin={70}
fovMax={140}
limitView="auto"
/>
<HotSpot
name="hotspot1"
url="/krpano/images/guide.png"
atv={5}
scale={0.5}
edge="top"
distorted={true}
onClick={() => setCurrentScene("center2")}
/>
</>
),
},
{
name: "center2",
thumbUrl: URL + "/panos/center2.tiles/thumb.jpg",
previewUrl: URL + "/panos/center2.tiles/preview.jpg",
imageTagAttributes: {
type: "cube",
tileSize: 512,
multires: true,
},
images: [
{
tiledImageWidth: 2624,
tiledImageHeight: 2624,
url: URL + "/panos/center2.tiles/%s/l3/%v/l3_%s_%v_%h.jpg",
},
{
tiledImageWidth: 1280,
tiledImageHeight: 1280,
url: URL + "/panos/center2.tiles/%s/l2/%v/l2_%s_%v_%h.jpg",
},
{
tiledImageWidth: 640,
tiledImageHeight: 640,
url: URL + "/panos/center2.tiles/%s/l1/%v/l1_%s_%v_%h.jpg",
},
],
children: (
<View
hlookat={0}
vlookat={0}
fovType="MFOV"
fov={120}
maxPixelZoom={2}
fovMin={70}
fovMax={140}
limitView="auto"
/>
),
},
],
[]
);
// 支持从 xml 中获取场景
const PARTY_SCENE_LIST = useMemo<ISceneProps[]>(
() => [
{
name: "scene_party",
thumbUrl: URL + "/panos/party.tiles/thumb.jpg",
},
],
[]
);
const MENUS = [
{
title: "长沙国防教育馆",
scenes: CENTER_SCENE_LIST,
},
{
title: "游客服务中心",
scenes: PARTY_SCENE_LIST,
},
];
const handleSceneClick = (name: string) => {
setCurrentScene(name);
};
const handleMenuClick = (idx: number) => {
setCurrentMenu(idx);
};
const handleView = (direction: ROTATE_DIRECTION) => {
window.ReactKrpanoActionProxy?.rotateView(direction);
};
const handleZoom = (action: ZOOM_ACTION) => {
window.ReactKrpanoActionProxy?.zoomView(action);
};
const handleAutoRotateOneRound = () => {
const count = window.ReactKrpanoActionProxy?.get("scene").count;
const curIndex = window.ReactKrpanoActionProxy?.get(
"scene[get(xml.scene)].index"
);
const nextScene = window.ReactKrpanoActionProxy?.get("scene").getItem(
curIndex + 1 >= count ? 0 : curIndex + 1
);
setCurrentScene(nextScene.name);
};
return (
<div className="demo">
<Krpano
className="krpano"
xml="./party.xml"
webvrUrl="./krpano/1.21/plugins/webvr.xml"
currentScene={currentScene}
littlePlanetIntro={true}
passQueryParameters={true}
>
<Autorotate enabled={autorotateEnable} />
<Events onAutoRotateOneRound={handleAutoRotateOneRound} />
{[...CENTER_SCENE_LIST, ...PARTY_SCENE_LIST].map(
(sc) => sc.imageTagAttributes && <Scene key={sc.name} {...sc} />
)}
</Krpano>
<div className="scene-panel">
<div className="scene-panel__menu">
{MENUS.map((sc, idx) => (
<div
key={sc.title}
className={`scene-panel__menu__item ${
idx === currentMenu && "active"
}`}
onClick={handleMenuClick.bind(undefined, idx)}
>
{sc.title}
</div>
))}
</div>
<div className="scene-panel__list">
{MENUS[currentMenu].scenes.map((sc) => (
<div
key={sc.name}
className={`scene-panel__list__item ${
sc.name === currentScene ? "active" : ""
}`}
onClick={handleSceneClick.bind(undefined, sc.name)}
>
<img
src={sc.thumbUrl || sc.images![0].url.replace("%s", "f")}
alt={sc.name}
/>
</div>
))}
</div>
</div>
<div className="toolbar">
<MouseHoldView
onHold={handleView.bind(undefined, ROTATE_DIRECTION.LEFT)}
>
<button>←</button>
</MouseHoldView>
<MouseHoldView
onHold={handleView.bind(undefined, ROTATE_DIRECTION.RIGHT)}
>
<button>→</button>
</MouseHoldView>
<MouseHoldView onHold={handleView.bind(undefined, ROTATE_DIRECTION.UP)}>
<button>↑</button>
</MouseHoldView>
<MouseHoldView
onHold={handleView.bind(undefined, ROTATE_DIRECTION.DOWN)}
>
<button>↓</button>
</MouseHoldView>
<MouseHoldView onHold={handleZoom.bind(undefined, ZOOM_ACTION.IN)}>
<button>+</button>
</MouseHoldView>
<MouseHoldView onHold={handleZoom.bind(undefined, ZOOM_ACTION.OUT)}>
<button>-</button>
</MouseHoldView>
<button
className={`${autorotateEnable && "active-btn"}`}
onClick={() => setAutorotateEnable(!autorotateEnable)}
>
360°
</button>
<button
onClick={() => {
window.ReactKrpanoActionProxy?.call("webvr.enterVR();");
}}
>
vr
</button>
</div>
</div>
);
};
export default Demo;
执行 Javascript 函数
Name | Description | Type | Default |
---|---|---|---|
action | 动作 | string |
(required) |
nexttick | 是否在下一个渲染帧后执行 | boolean |
false |
动态添加标签
Name | Description | Type | Default |
---|---|---|---|
tag | 标签 | string |
(required) |
name | 名称 | string |
(required) |
attrs | 属性 | Record<string, any> |
(required) |
删除场景
Name | Description | Type | Default |
---|---|---|---|
name | 场景名称 | string |
(required) |
加载场景
Name | Description | Type | Default |
---|---|---|---|
name | 场景名称 | string |
(required) |
旋转视图
Name | Description | Type | Default |
---|---|---|---|
direction | 方位 | ROTATE_DIRECTION |
(required) |
degrees | 旋转度数 | number |
10 |
缩放视图
Name | Description | Type | Default |
---|---|---|---|
action | 动作 | ZOOM_ACTION |
(required) |
num | 缩放大小 | number |
10 |