BLACK FRIDAY: Save 50% on all my Swift books and bundles! >>

Detect & use mouse wheel movement/event to call a function?

Forums > SwiftUI

Is there a way to use SwiftUI to call a function when the user scrolls the mouse wheel ( up or down ), while the mouse cursor is hovering over some lines of text?

Ultimately, I'm making a language learning app for MacOS, where the user can visually read sentences of text, then when they hover the cursor over the text - and at same time - move their mouse wheel ( up or down ), they can hear an audio file of the translation.

I'm using the condition ( cursor hover + mouse wheel event ), because I'm reserving other mouse events - or combinations of - for calling other functions ( such as showing visual transations, etc )

In CSS, I can use

<div class="smartText" onwheel="playAudioTransation()" onclick="showVisualTransation()" > How are you today? </div>

, but I haven't found the SwiftUI equivalent yet.

I was able to make a play-sound-file function work, so that part I already have.

But I can't figure out how to make some lines of text, listen for the user's cursor hover and mouse wheel movement, and then calls a function when these events happen.

Does anyone know how to do this in SwfitUI ? ( If buttons can be made to receive mouse hover + wheel events, that could work too )

Thanks,

Jay

2      

Maybe try the solution from this StackOverflow answer?

2      

I came across that StackOverflow page earlier in my Googling too, but sadly much of the solution giver's explanation and code are beyond my current understanding of SwiftUI.

I can see that on the StackOverflow page, the solution giver is creating a function called trackScrollWheel()

that runs onAppear of a view called "horizontal scroll" : .onAppear { trackScrollWheel() } and calls the function he's creating.

I'm guessing .filter { event in event?.type == .scrollWheel } specifies to only listen for scrollwheel.

Beyond that though, I'm not sure what he's doing, where this code would fit into my code of text lines ( which is just a simple vertical stack of text lines within var body: some View ), or where I would place my call for my own play-sound-file function.

I'm also not sure what he refers to by "you already have a hover/focus boolean for the view".

2      

Your code would go in place of this line:

vm?.goBackOrForwardBy(delta: Int(event?.deltaY ?? 0))

2      

Thanks, will give it a try.

2      

@Magdi  

Here is an example of handling the wheel mouse's event:

struct ZoomableCircleView: View {
    @State var circleZoom: CGFloat = 1.0
    @State var insideCircle: Bool = false
    var body: some View {
        Circle()
            .frame(width: 100 * circleZoom, height: 100 * circleZoom)
            .onHover(perform: { hovering in
                insideCircle = hovering
            })

            .onAppear(perform:{
                NSEvent.addLocalMonitorForEvents(matching: .scrollWheel) {event in

                    if insideCircle {
                        circleZoom += event.scrollingDeltaY/100
                        if circleZoom < 0.1 {circleZoom = 0.1}
                    }
                    return event
                }
            })
    }
}

In this example, when we scroll the mouse wheel, the circle's diameter increases or decreases accordingly

1      

@Magdi your ZoomableCircleView works great on my SpriteView on macOS, even when I add DragGesture and .onContinuousHover! Thank you!

   

Save 50% in my WWDC sale.

SAVE 50% All our books and bundles are half price for Black Friday, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.

Save 50% on all our books and bundles!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.