瀏覽代碼

Allow customizing the crosshair in `ui.interactive_image` (#3848)

These new props enable or disable drawing the corresponding line when
cross is enabled.

The motivation in my case was the need to show only the vertical
crosshair line in an audio editing context (in this instance the audio
is represented as an interactive_image element of a spectrogram).

Simple demo of the functionality:

```py
from nicegui import ui

image = ui.interactive_image(source='https://picsum.photos/id/29/640/360', cross=True)

def toggle_prop(prop: str) -> None:
    image._props[prop] = not image._props[prop]
    image.update()

ui.button("toggle vertical", on_click=lambda: toggle_prop("cross_vertical"))
ui.button("toggle horizontal", on_click=lambda: toggle_prop("cross_horizontal"))

ui.run()
```

---------

Co-authored-by: Falko Schindler <falko@zauberzeug.com>
Christopher Friesen 7 月之前
父節點
當前提交
89292c7f95

+ 5 - 4
nicegui/elements/interactive_image.js

@@ -11,9 +11,10 @@ export default {
         draggable="false"
       />
       <svg ref="svg" style="position:absolute;top:0;left:0;pointer-events:none" :viewBox="viewBox">
-        <g v-if="cross" :style="{ display: showCross ? 'block' : 'none' }">
-          <line :x1="x" y1="0" :x2="x" y2="100%" :stroke="cross === true ? 'black' : cross" />
-          <line x1="0" :y1="y" x2="100%" :y2="y" :stroke="cross === true ? 'black' : cross" />
+        <g :style="{ display: showCross ? 'block' : 'none' }">
+          <line v-if="cross" :x1="x" y1="0" :x2="x" y2="100%" :stroke="cross === true ? 'black' : cross" />
+          <line v-if="cross" x1="0" :y1="y" x2="100%" :y2="y" :stroke="cross === true ? 'black' : cross" />
+          <slot name="cross" :x="x" :y="y"></slot>
         </g>
         <g v-html="content"></g>
       </svg>
@@ -118,7 +119,7 @@ export default {
   },
   computed: {
     onCrossEvents() {
-      if (!this.cross) return {};
+      if (!this.cross && !this.$slots.cross) return {};
       return {
         mouseenter: () => (this.showCross = true),
         mouseleave: () => (this.showCross = false),

+ 9 - 0
website/documentation/content/interactive_image_documentation.py

@@ -65,10 +65,19 @@ def loaded_event():
 @doc.demo('Crosshairs', '''
     You can show crosshairs by passing `cross=True`.
     You can also change the color of the crosshairs by passing a color string.
+
+    Alternatively, you can use the `add_slot` method to add a custom "cross" slot with your own SVG template.
+    The `props.x` and `props.y` variables will be available in the template, representing the crosshair position.
 ''')
 def crosshairs():
     ui.interactive_image('https://picsum.photos/id/565/640/360', cross='red')
 
+    ui.interactive_image('https://picsum.photos/id/565/640/360').add_slot('cross', '''
+        <circle :cx="props.x" :cy="props.y" r="30" stroke="red" fill="none" />
+        <line :x1="props.x - 30" :y1="props.y" :x2="props.x + 30" :y2="props.y" stroke="red" />
+        <line :x1="props.x" :y1="props.y - 30" :x2="props.x" :y2="props.y + 30" stroke="red" />
+    ''')
+
 
 @doc.demo('SVG events', '''
     You can subscribe to events of the SVG elements by using the `on` method with an "svg:" prefix.