|
@@ -1,3 +1,4 @@
|
|
|
+import { PromiseQueue } from "./PromiseQueue";
|
|
|
import { ViewProps } from "./components";
|
|
|
import {
|
|
|
NativeKrpanoRendererObject,
|
|
@@ -6,12 +7,6 @@ import {
|
|
|
} from "./types";
|
|
|
import { buildKrpanoAction, buildKrpanoTagSetterActions } from "./utils";
|
|
|
|
|
|
-declare global {
|
|
|
- interface Window {
|
|
|
- ReactKrpanoActionProxy?: KrpanoActionProxy;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
export type HandlerFunc = (renderer: KrpanoActionProxy) => void;
|
|
|
|
|
|
interface EventHandler {
|
|
@@ -24,6 +19,7 @@ export class KrpanoActionProxy {
|
|
|
name: string;
|
|
|
krpanoRenderer?: NativeKrpanoRendererObject;
|
|
|
eventHandlers: EventHandler[] = [];
|
|
|
+ dynamicTagWaitQueue: PromiseQueue<any>;
|
|
|
|
|
|
constructor(
|
|
|
krpanoRenderer?: NativeKrpanoRendererObject,
|
|
@@ -31,8 +27,22 @@ export class KrpanoActionProxy {
|
|
|
) {
|
|
|
this.krpanoRenderer = krpanoRenderer;
|
|
|
this.name = name;
|
|
|
+
|
|
|
+ // krpano 1.19 版本不支持动态插入 include,只能在文本中插入后重新加载
|
|
|
+ this.dynamicTagWaitQueue = new PromiseQueue();
|
|
|
}
|
|
|
|
|
|
+ waitIncludeLoad() {
|
|
|
+ return this.syncTagsLoaded
|
|
|
+ ? Promise.resolve()
|
|
|
+ : this.dynamicTagWaitQueue.push();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 执行 Javascript 函数
|
|
|
+ * @param action 动作
|
|
|
+ * @param nexttick 是否在下一个渲染帧后执行
|
|
|
+ */
|
|
|
call(action: string, nexttick = false): void {
|
|
|
const actionStr = nexttick ? `nexttick(${action})` : action;
|
|
|
|
|
@@ -43,24 +53,25 @@ export class KrpanoActionProxy {
|
|
|
this.call(buildKrpanoAction("set", name, ...params));
|
|
|
}
|
|
|
|
|
|
- setTag(
|
|
|
- tag:
|
|
|
- | "scene"
|
|
|
- | "hotspot"
|
|
|
- | "layer"
|
|
|
- | "view"
|
|
|
- | "events"
|
|
|
- | "autorotate"
|
|
|
- | "plugin",
|
|
|
+ /**
|
|
|
+ * 动态添加标签
|
|
|
+ * @param tag 标签
|
|
|
+ * @param name 名称
|
|
|
+ * @param attrs 属性
|
|
|
+ */
|
|
|
+ async setTag(
|
|
|
+ tag: "scene" | "hotspot" | "layer" | "view" | "events" | "autorotate",
|
|
|
name: string | null,
|
|
|
attrs: Record<string, any>
|
|
|
- ): void {
|
|
|
+ ) {
|
|
|
let nexttick = false;
|
|
|
|
|
|
if (tag === "hotspot" || tag === "events") {
|
|
|
nexttick = true;
|
|
|
}
|
|
|
|
|
|
+ await this.waitIncludeLoad();
|
|
|
+
|
|
|
this.call(
|
|
|
buildKrpanoTagSetterActions(name ? `${tag}[${name}]` : tag, attrs),
|
|
|
nexttick
|
|
@@ -71,6 +82,10 @@ export class KrpanoActionProxy {
|
|
|
return this.krpanoRenderer?.get(name);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 删除场景
|
|
|
+ * @param name 场景名称
|
|
|
+ */
|
|
|
removeScene(name: string): void {
|
|
|
if (
|
|
|
this.get("scene") &&
|
|
@@ -198,4 +213,49 @@ export class KrpanoActionProxy {
|
|
|
removeHotspot(name: string): void {
|
|
|
this.call(buildKrpanoAction("removehotspot", name), true);
|
|
|
}
|
|
|
+
|
|
|
+ syncTagsLoaded = false;
|
|
|
+ syncTagStack: {
|
|
|
+ tagName: string;
|
|
|
+ attribute: Record<string, unknown>;
|
|
|
+ }[] = [];
|
|
|
+
|
|
|
+ pushSyncTag(tagName: string, attribute: Record<string, unknown>) {
|
|
|
+ this.syncTagStack.unshift({
|
|
|
+ tagName,
|
|
|
+ attribute,
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ async createSyncTags() {
|
|
|
+ const xmlDoc = await this.getXMLContent();
|
|
|
+ const krpanoElement = xmlDoc.querySelector("krpano");
|
|
|
+
|
|
|
+ while (this.syncTagStack.length) {
|
|
|
+ const tag = this.syncTagStack.pop()!;
|
|
|
+ const element = xmlDoc.createElement(tag.tagName);
|
|
|
+
|
|
|
+ for (const key in tag.attribute) {
|
|
|
+ element.setAttribute(key, tag.attribute[key] as string);
|
|
|
+ }
|
|
|
+
|
|
|
+ krpanoElement?.insertBefore(element, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ return xmlDoc;
|
|
|
+ }
|
|
|
+
|
|
|
+ private async getXMLContent() {
|
|
|
+ let contentText = "";
|
|
|
+ const xml = this?.get("xml");
|
|
|
+ const parser = new DOMParser();
|
|
|
+
|
|
|
+ if (xml.content) {
|
|
|
+ contentText = xml.content;
|
|
|
+ } else if (xml.url) {
|
|
|
+ contentText = await fetch(xml.url).then((res) => res.text());
|
|
|
+ }
|
|
|
+
|
|
|
+ return parser.parseFromString(contentText, "text/xml");
|
|
|
+ }
|
|
|
}
|