Как я могу определить область, в которой я перемещаю палец с помощью SwiftUI?

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

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

Вот что я попробовал.

struct Circular: View {
    @State private var erasedPoints: [CGPoint] = []
    
    var body: some View {
        ZStack {
            Image("img4")
                .resizable()
                .scaledToFit()
                .overlay(
                    Color.red
                        .mask(eraserShape())
                        .blendMode(.colorDodge)
                )
                .gesture(
                    DragGesture(minimumDistance: 0)
                        .onChanged { value in
                            erasedPoints.append(value.location)
                        }
                )
        }
    }
    
    func eraserShape() -> Path {
        var path = Path()
        for point in erasedPoints {
            let rect = CGRect(x: point.x - 15, y: point.y - 15, width: 30, height: 30)
            path.addEllipse(in: rect)
        }
        return path
    }
}

Мой результат.

чего я хочу достичь

Мы не сможем помочь вам устранить неполадки, если вы не поделитесь тем, что у вас есть, и не расскажете нам, что не работает.

lorem ipsum 13.08.2024 23:36

обновлено, в основном то, что я сделал.

dshn 13.08.2024 23:50
Стоит ли изучать 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
53
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Вместо добавления эллипсов к пути вам следует нарисовать линию, соединяющую erasedPoints.

Затем создайте форму, которая будет сформирована, если эту линию нужно обвести, используя ширину линии 30 пунктов, используя strodPath .

Поглаживание этой формы дает желаемый результат. Но перед этим вам также следует нормализовать(eoFill: false), потому что, видимо, путь, созданный strokedPath, немного беспорядочный.

func eraserShape() -> Path {
    var path = Path()
    path.addLines(erasedPoints)
    return path
        .strokedPath(.init(lineWidth: 30, lineCap: .round, lineJoin: .round))
        .normalized(eoFill: false)
}

и измените наложение изображения на:

.overlay {
    eraserShape().stroke(.blue, lineWidth: 3)
}

В iOS 16 вместо этого вы можете работать напрямую с CGPath:

func eraserShape() -> Path {
    var path = Path()
    path.addLines(erasedPoints)
    return Path(
        path.cgPath
            .copy(strokingWithWidth: 30, lineCap: .round, lineJoin: .round, miterLimit: 10)
            .normalized(using: .winding)
    )
}

Спасибо! он работает, но нужно небольшое обновление. func EraserShape() -> Path { var path = Path() path.addLines(erasedPoints) путь возврата .strokedPath(.init(lineWidth: 30, lineCap: .round, lineJoin: .round)) .normalized(eoFill: false) } он также рисовал случайные прямые линии, если мы сделаем параметр lineJoin равным .round, мы решим и эту проблему. еще раз спасибо.

dshn 14.08.2024 13:01

@dshn Правда? Я знаю, что он рисует случайные прямые линии без normalized, но в ходе моего тестирования этого не произошло. В любом случае я обновил ответ.

Sweeper 14.08.2024 13:04

сделанный! Итак, у меня есть еще один вопрос. Как я могу использовать эту нарисованную область как форму клипа? Я хочу вырезать любой вид с помощью clipShape, как я нарисовал.

dshn 14.08.2024 13:35

@dshn Просто передайте eraserShape() прямо на clipShape, без поглаживания.

Sweeper 14.08.2024 13:37

мне очень жаль, но мне это нужно в iOS 15, .нормализовано в iOS 17...

dshn 14.08.2024 15:56

@dshn К сожалению, CGPath.normalized доступен начиная с iOS 16. Я не знаю, как это сделать на iOS 15, извините.

Sweeper 14.08.2024 16:04

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