Selaa lähdekoodia

Merge pull request #616 from dclause/rewrite_interactive_image

Rewrite InteractiveImage component in a more vue-style way.
Falko Schindler 2 vuotta sitten
vanhempi
säilyke
9e51d1e60e
2 muutettua tiedostoa jossa 45 lisäystä ja 68 poistoa
  1. 45 64
      nicegui/elements/interactive_image.js
  2. 0 4
      nicegui/elements/interactive_image.py

+ 45 - 64
nicegui/elements/interactive_image.js

@@ -1,78 +1,59 @@
 export default {
   template: `
     <div style="position:relative">
-      <img style="width:100%; height:100%" />
-      <svg style="position:absolute;top:0;left:0;pointer-events:none">
-        <g style="display:none">
-          <line x1="100" y1="0" x2="100" y2="100%" stroke="black" />
-          <line x1="0" y1="100" x2="100%" y2="100" stroke="black" />
+      <img :src="src" style="width:100%; height:100%;" v-on="onEvents" draggable="false" />
+      <svg v-if="cross" style="position:absolute;top:0;left:0;pointer-events:none" :viewBox="viewBox">
+        <g :style="{ display: cssDisplay }">
+          <line :x1="x" y1="0" :x2="x" y2="100%" stroke="black" />
+          <line x1="0" :y1="y" x2="100%" :y2="y" stroke="black" />
         </g>
-        <g v-html="content" style="display:none"></g>
+        <g v-html="content"></g>
       </svg>
     </div>
   `,
-  mounted() {
-    this.image = this.$el.firstChild;
-    const handle_completion = () => {
-      if (this.waiting_source) {
-        this.image.src = this.waiting_source;
-        this.waiting_source = undefined;
-      } else {
-        this.loading = false;
-      }
-    };
-    this.image.addEventListener("load", handle_completion);
-    this.image.addEventListener("error", handle_completion);
-    this.svg = this.$el.lastChild;
-    const cross = this.svg.firstChild;
-    this.image.ondragstart = () => false;
-    if (this.cross) {
-      this.image.style.cursor = "none";
-      this.image.addEventListener("mouseenter", (e) => {
-        cross.style.display = "block";
-      });
-      this.image.addEventListener("mouseleave", (e) => {
-        cross.style.display = "none";
-      });
-      this.image.addEventListener("mousemove", (e) => {
-        const x = (e.offsetX * e.target.naturalWidth) / e.target.clientWidth;
-        const y = (e.offsetY * e.target.naturalHeight) / e.target.clientHeight;
-        cross.firstChild.setAttribute("x1", x);
-        cross.firstChild.setAttribute("x2", x);
-        cross.lastChild.setAttribute("y1", y);
-        cross.lastChild.setAttribute("y2", y);
-      });
-    }
-    this.image.onload = (e) => {
-      const viewBox = `0 0 ${this.image.naturalWidth} ${this.image.naturalHeight}`;
-      this.svg.setAttribute("viewBox", viewBox);
-      this.svg.lastChild.setAttribute("style", "");
+  data() {
+    return {
+      viewBox: "0 0 0 0",
+      x: 100,
+      y: 100,
+      cssDisplay: "none",
     };
-    this.image.src = this.src;
-    for (const type of this.events) {
-      this.image.addEventListener(type, (e) => {
-        this.$emit("mouse", {
-          mouse_event_type: type,
-          image_x: (e.offsetX * e.target.naturalWidth) / e.target.clientWidth,
-          image_y: (e.offsetY * e.target.naturalHeight) / e.target.clientHeight,
-          button: e.button,
-          buttons: e.buttons,
-          altKey: e.altKey,
-          ctrlKey: e.ctrlKey,
-          metaKey: e.metaKey,
-          shiftKey: e.shiftKey,
-        });
-      });
-    }
   },
   methods: {
-    set_source(source) {
-      if (this.loading) {
-        this.waiting_source = source;
-        return;
+    updateCrossHair(e) {
+      this.x = (e.offsetX * e.target.naturalWidth) / e.target.clientWidth;
+      this.y = (e.offsetY * e.target.naturalHeight) / e.target.clientHeight;
+    },
+    onImageLoaded(e) {
+      this.viewBox = `0 0 ${e.target.naturalWidth} ${e.target.naturalHeight}`;
+    },
+    onMouseEvent(type, e) {
+      this.$emit("mouse", {
+        mouse_event_type: type,
+        image_x: (e.offsetX * e.target.naturalWidth) / e.target.clientWidth,
+        image_y: (e.offsetY * e.target.naturalHeight) / e.target.clientHeight,
+        button: e.button,
+        buttons: e.buttons,
+        altKey: e.altKey,
+        ctrlKey: e.ctrlKey,
+        metaKey: e.metaKey,
+        shiftKey: e.shiftKey,
+      });
+    },
+  },
+  computed: {
+    onEvents() {
+      const allEvents = {};
+      for (const type of this.events) {
+        allEvents[type] = (event) => this.onMouseEvent(type, event);
+      }
+      if (this.cross) {
+        allEvents["mouseenter"] = () => (this.cssDisplay = "block");
+        allEvents["mouseleave"] = () => (this.cssDisplay = "none");
+        allEvents["mousemove"] = (event) => this.updateCrossHair(event);
+        allEvents["load"] = (event) => this.onImageLoaded(event);
       }
-      this.loading = true;
-      this.image.src = source;
+      return allEvents;
     },
   },
   props: {

+ 0 - 4
nicegui/elements/interactive_image.py

@@ -52,7 +52,3 @@ class InteractiveImage(SourceElement, ContentElement):
             )
             return handle_event(on_mouse, arguments)
         self.on('mouse', handle_mouse)
-
-    def on_source_change(self, source: str) -> None:
-        super().on_source_change(source)
-        self.run_method('set_source', source)