Как отправить события колеса прокрутки в SwiftUI SpriteView

Я пытаюсь перенести весь свой код SpriteKit в контейнер SwiftUI SpriteView. Моя программа представляет собой смесь SwiftUI и SpriteKit на MacOS для торговли криптовалютой.

У меня проблема в том, что функция scrollWheel(with event: NSEvent) внутри моего объекта SKScene не срабатывает, когда я прокручиваю колесо мыши.

Ранее я решил эту проблему, сделав SKScene nextResponder, который отлично работал, когда я использовал Cocoa.

Ниже показано, как выглядит моя основная точка входа в SwiftUI.

@main
struct ManualTradingApp: App {

    var exchangeManger: ExchangeManager = BinanceManager()
    
    var chartScene: ChartScene {
        let scene = ChartScene(size: CGSize(width: 600, height: 600), manager: exchangeManger)
        scene.scaleMode = .resizeFill
        return scene
    }
    
    var body: some Scene {
        WindowGroup {
            ContentView(manager: exchangeManger, chartScene: chartScene)
        }
    }
}

Вот функция внутри созданного мной класса ChartScene, которая должна получать события колеса прокрутки.

override func scrollWheel(with event: NSEvent) {
        
    if chartNode.contains(event.locationInWindow) {
        chartNode.scrollWheel(with: event)
    } else if chartNode2.contains(event.locationInWindow) {
        chartNode2.scrollWheel(with: event)
    }
        
    if symbolRowContainer.contains(event.locationInWindow) {
        moveSymbolContainer(deltaY: -event.scrollingDeltaY * 10.0)
    }
}
[JS за 1 час] - 9. Асинхронный
[JS за 1 час] - 9. Асинхронный
JavaScript является однопоточным, то есть он может обрабатывать только одну задачу за раз. Для обработки длительных задач, таких как сетевые запросы,...
Топ-10 компаний-разработчиков PHP
Топ-10 компаний-разработчиков PHP
Если вы ищете надежных разработчиков PHP рядом с вами, вот список лучших компаний по разработке PHP.
Скраппинг поиска Apple App Store с помощью Python
Скраппинг поиска Apple App Store с помощью Python
📌Примечание: В этой статье я покажу вам, как скрапировать поиск Apple App Store и получить точно такой же результат, как на Apple iMac, потому что...
Редкие достижения на Github ✨
Редкие достижения на Github ✨
Редкая коллекция доступна в профиле на GitHub ✨
Подъем в javascript
Подъем в javascript
Hoisting - это поведение в JavaScript, при котором переменные и объявления функций автоматически "перемещаются" в верхнюю часть соответствующих...
Улучшение генерации файлов Angular
Улучшение генерации файлов Angular
Angular - это фреймворк. Вы можете создать практически любое приложение без использования сторонних библиотек.
1
0
57
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете захватывать события scrollWheel через NSView, а затем публиковать их в виде уведомлений, которые могут быть получены SKScene.

Сначала добавьте наблюдателя уведомлений в свой SKScene

class GameSceneScrollWheel: SKScene {
    override func didMove(to view: SKView) {
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(self.scrollWheelWithEvent(notification:)),
                                               name: Notification.Name("scrollWheelWithEvent"),
                                               object: nil)
    }
    
    //receive notification and passthrough to normal `scrollWheel` function
    @objc func scrollWheelWithEvent(notification: Notification) {
        guard let event = notification.object as? NSEvent else { return }
        self.scrollWheel(with:event)
    }
    
    override func scrollWheel(with event: NSEvent) {
        print("event.deltaY: \(event.deltaY)") //success!
    }
}

Во-вторых, перехватывать события в NSView и публиковать уведомления

struct ScrollWheelEventView : NSViewRepresentable {
    
    class ScrollWheelView : NSView {
        override var acceptsFirstResponder: Bool { true }
        override func acceptsFirstMouse(for event: NSEvent?) -> Bool { return true }
                
        override func scrollWheel(with event: NSEvent) {
            NotificationCenter.default.post(name: Notification.Name("scrollWheelWithEvent"), object: event)
        }
    }
        
    func makeNSView(context: Context) -> some NSView {
        return ScrollWheelView()
    }
    
    func updateNSView(_ nsView: NSViewType, context: Context) {}
}

И, наконец, добавьте NSViewRepresentable в SwiftUI.

struct ScrollWheel: View {
    @State private var scene = GameSceneScrollWheel()

    var body: some View {
        ZStack {
            SpriteView(scene: scene)
            ScrollWheelEventView()
        }
    }
}

Спасибо, это сработало! Мне пришлось удалить эти строки, потому что они не позволяли нажимать клавиши в SKScene override var acceptsFirstResponder: Bool { true } override func acceptsFirstMouse(for event: NSEvent?) -> Bool { return true }

BDub 20.11.2022 17:17

Другие вопросы по теме