瀏覽代碼

refactor[krpano]: KrpanoActionProxy

chenlei 1 年之前
父節點
當前提交
c5f5c6e7f7

+ 1 - 1
packages/krpano/src/components/Include.tsx

@@ -14,7 +14,7 @@ export const Include: FC<IncludeProps> = ({ url }) => {
   useEffect(() => {
     if (!renderer) return;
 
-    renderer.pushSyncTag("include", { url });
+    renderer.tagAction.pushSyncTag("include", { url });
   }, [renderer]);
 
   return <></>;

+ 7 - 7
packages/krpano/src/components/Krpano.tsx

@@ -1,5 +1,5 @@
 import React, { useCallback, useEffect, useState } from "react";
-import { KrpanoActionProxy } from "../KrpanoActionProxy";
+import { KrpanoActionProxy } from "../models";
 import { useMounted, useEventCallback } from "../hooks";
 import { IKrpanoConfig, NativeKrpanoRendererObject } from "../types";
 import { CurrentSceneContext, KrpanoRendererContext } from "../contexts";
@@ -48,17 +48,17 @@ export const Krpano: React.FC<KrpanoProps> = ({
     if (!renderer) return;
 
     const reloadXML = async () => {
-      if (renderer.syncTagStack.length) {
-        // 如果有同步标签(include、plugin),则重新加载
+      if (renderer.tagAction.syncTagStack.length) {
+        // krpano 1.19 版本不支持动态插入 include,只能在文本中插入后重新加载
         const updateXmlString = new XMLSerializer().serializeToString(
-          await renderer.createSyncTags()
+          await renderer.tagAction.createSyncTags()
         );
 
         renderer.call(buildKrpanoAction("loadxml", updateXmlString));
       }
 
-      renderer.syncTagsLoaded = true;
-      renderer.dynamicTagWaitQueue.flushResolve(true);
+      renderer.tagAction.syncTagsLoaded = true;
+      renderer.tagAction.queue.flushResolve(true);
     };
 
     reloadXML();
@@ -67,7 +67,7 @@ export const Krpano: React.FC<KrpanoProps> = ({
   useEffect(() => {
     if (!renderer || !currentScene) return;
 
-    renderer.waitIncludeLoaded(true).then(() => {
+    renderer.tagAction.waitIncludeLoaded(true).then(() => {
       renderer.loadScene(currentScene);
     });
   }, [renderer, currentScene]);

+ 1 - 1
packages/krpano/src/components/Plugin.tsx

@@ -14,7 +14,7 @@ export const Plugin: FC<PluginProps> = ({ attribute }) => {
   useEffect(() => {
     if (!renderer) return;
 
-    renderer.pushSyncTag("plugin", attribute);
+    renderer.tagAction.pushSyncTag("plugin", attribute);
   }, [renderer]);
 
   return <></>;

+ 1 - 1
packages/krpano/src/contexts/KrpanoRendererContext.ts

@@ -1,5 +1,5 @@
 import React from "react";
-import { KrpanoActionProxy } from "../KrpanoActionProxy";
+import { KrpanoActionProxy } from "../models";
 
 export const KrpanoRendererContext =
   React.createContext<KrpanoActionProxy | null>(null);

+ 8 - 65
packages/krpano/src/KrpanoActionProxy.ts

@@ -1,11 +1,11 @@
-import { PromiseQueue } from "./PromiseQueue";
-import { ViewProps } from "./components";
+import { TagActionProxy } from ".";
+import { ViewProps } from "../components";
 import {
   NativeKrpanoRendererObject,
   ROTATE_DIRECTION,
   ZOOM_ACTION,
-} from "./types";
-import { buildKrpanoAction, buildKrpanoTagSetterActions } from "./utils";
+} from "../types";
+import { buildKrpanoAction, buildKrpanoTagSetterActions } from "../utils";
 
 export type HandlerFunc = (renderer: KrpanoActionProxy) => void;
 
@@ -19,7 +19,7 @@ export class KrpanoActionProxy {
   name: string;
   krpanoRenderer?: NativeKrpanoRendererObject;
   eventHandlers: EventHandler[] = [];
-  dynamicTagWaitQueue: PromiseQueue<any>;
+  tagAction: TagActionProxy;
 
   constructor(
     krpanoRenderer?: NativeKrpanoRendererObject,
@@ -27,19 +27,7 @@ export class KrpanoActionProxy {
   ) {
     this.krpanoRenderer = krpanoRenderer;
     this.name = name;
-
-    // krpano 1.19 版本不支持动态插入 include,只能在文本中插入后重新加载
-    this.dynamicTagWaitQueue = new PromiseQueue();
-  }
-
-  /**
-   * 等待 include 标签加载完成
-   */
-  waitIncludeLoaded(push?: boolean) {
-    return this.syncTagsLoaded
-      ? Promise.resolve()
-      : // 先进后出
-        this.dynamicTagWaitQueue[push ? "push" : "unshift"]();
+    this.tagAction = new TagActionProxy(krpanoRenderer);
   }
 
   /**
@@ -74,7 +62,7 @@ export class KrpanoActionProxy {
       nexttick = true;
     }
 
-    await this.waitIncludeLoaded();
+    await this.tagAction.waitIncludeLoaded();
 
     this.call(
       buildKrpanoTagSetterActions(name ? `${tag}[${name}]` : tag, attrs),
@@ -211,56 +199,11 @@ export class KrpanoActionProxy {
     name: string,
     attrs: Record<string, string | boolean | number | undefined>
   ) {
-    await this.waitIncludeLoaded();
+    await this.tagAction.waitIncludeLoaded();
     this.call(buildKrpanoAction("addhotspot", name), true);
     this.setTag("hotspot", name, attrs);
   }
   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");
-  }
 }

packages/krpano/src/PromiseQueue.ts → packages/krpano/src/models/PromiseQueue.ts


+ 75 - 0
packages/krpano/src/models/TagActionProxy.ts

@@ -0,0 +1,75 @@
+import { NativeKrpanoRendererObject } from "../types";
+import { PromiseQueue } from "./PromiseQueue";
+
+export class TagActionProxy {
+  krpanoRenderer?: NativeKrpanoRendererObject;
+
+  queue = new PromiseQueue();
+  /**
+   * 同步标签是否加载完成
+   */
+  syncTagsLoaded = false;
+  syncTagStack: {
+    tagName: string;
+    attribute: Record<string, unknown>;
+  }[] = [];
+
+  constructor(krpanoRenderer?: NativeKrpanoRendererObject) {
+    this.krpanoRenderer = krpanoRenderer;
+  }
+
+  /**
+   * 等待 include 标签加载完成
+   */
+  waitIncludeLoaded(push?: boolean) {
+    return this.syncTagsLoaded
+      ? Promise.resolve()
+      : // 先进后出
+        this.queue[push ? "push" : "unshift"]();
+  }
+
+  /**
+   * 将异步标签推入堆中
+   */
+  pushSyncTag(tagName: string, attribute: Record<string, unknown>) {
+    this.syncTagStack.unshift({
+      tagName,
+      attribute,
+    });
+  }
+
+  /**
+   * 创建一个插入同步标签后的 XMLDOM
+   */
+  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.krpanoRenderer?.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");
+  }
+}

+ 3 - 0
packages/krpano/src/models/index.ts

@@ -0,0 +1,3 @@
+export * from "./KrpanoActionProxy";
+export * from "./PromiseQueue";
+export * from "./TagActionProxy";

+ 1 - 1
packages/krpano/src/types.ts

@@ -1,4 +1,4 @@
-import { KrpanoActionProxy } from "./KrpanoActionProxy";
+import { KrpanoActionProxy } from "./models";
 
 declare global {
   interface Window {