Skip to content

Commit

Permalink
Allow customizing the crosshair in ui.interactive_image (#3848)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
parlance-zz and falkoschindler authored Oct 14, 2024
1 parent a82cdb7 commit 89292c7
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 4 deletions.
9 changes: 5 additions & 4 deletions nicegui/elements/interactive_image.js
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit 89292c7

Please sign in to comment.