Рисование стрелок между изображениями macOS

Я работаю над представлением SwiftUI, которое должно отображать изображения, загруженные с диска, со стрелками между ними. Структура моего представления в основном такова:

ScrollView
- HStack
-- ForEach
--- GeometryReader
---- Image

Мой мыслительный процесс заключается в том, что я могу просто использовать GeometryReader, чтобы найти текущую позицию каждого изображения в ScrollView, а затем нарисовать линию между двумя изображениями, используя путь. Я хоть на правильном пути? Я также заметил, что использование GeometryReader сильно снижает производительность, и не думаю, что это правильный способ получить положение каждого изображения, если я просто не использую его неправильно.

Вот код, который у меня есть до сих пор:

import SwiftUI

struct ScreenshotView: View {
    let screenshots = getScreenshots()
    

    var body: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack(spacing: 0) {
                ForEach(screenshots, id: \.self) { screenshot in
                    GeometryReader { geo in
                        // have to use NSImage to load from disk
                        if let nsImage = NSImage(
                            contentsOf: screenshot.path) {
                            Button(action: {
                                print("Trying to open: ", screenshot.path)
                                NSWorkspace.shared.open(screenshot.path)
                            }) {
                                Image(nsImage: nsImage)
                                    .resizable()
                                    .frame(width: 50, height: 100)
                                    .aspectRatio(contentMode: .fit)
                                    .padding()
                                    .coordinateSpace(name: "image")
                            }
                            .buttonStyle(PlainButtonStyle())
                            .help("\(geo.frame(in: .global).midX)")
                        }
                    }
                    .frame(width: 50, height: 100)
                    .padding()
                }
            }
        }
        .padding()
    }
}

Спасибо за помощь!

не могли бы вы указать «стрелку между ними»? что за стрелки? откуда и куда должны идти стрелки? только по горизонтали или поперек обзора?

ChrisR 05.04.2022 21:34

Да, просто по горизонтали между двумя изображениями. От правой стороны левого изображения к левой стороне правого изображения. (Позже я буду использовать VStack, так что в этом случае вертикально между двумя изображениями). Это не обязательно должна быть стрелка типа --->, это может быть просто линия или что-то в этом роде. Спасибо!

user5354589 05.04.2022 21:39
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
22
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Вам не нужно GeometryReader. Просто поставьте стрелку между изображениями в HStack. Если вам не нужен интервал, отрегулируйте его в HStack, например. spacing: 0.

Shape — это отдельное представление само по себе, которому не нужны абсолютные позиционные точки, но размер которого зависит от родительского представления или, как в этом примере, в размере, заданном .frame.

struct ContentView: View {
    var body: some View {
        
        ScrollView(.horizontal, showsIndicators: false) {
            HStack {
                ForEach(0..<10) { _ in
                    Rectangle().fill(.gray)
                        .frame(width: 50, height: 50)
                    ArrowShape()
                        .stroke(lineWidth: 2)
                        .frame(width: 50, height: 20)
                }
            }
        }
        .padding()
    }
}

struct ArrowShape: Shape{
    
    func path(in rect: CGRect) -> Path {
        
        let delta = rect.height / 2  // height of arrow tip legs
        
        return Path{ path in
            path.move(to: CGPoint(x: 0, y: rect.midY))
            path.addLine(to: CGPoint(x: rect.maxX, y: rect.midY))
            
            path.move(to: CGPoint(x: rect.maxX - delta, y: rect.midY - delta))
            path.addLine(to: CGPoint(x: rect.maxX, y: rect.midY))
            path.addLine(to: CGPoint(x: rect.maxX - delta, y: rect.midY + delta))
        }
    }
}

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