Как панорамировать после того, как жест панорамирования перемещает определенные суммы

Мне нужна помощь, я сделал вид, который я разделил линиями, и когда я касаюсь его, делаю прямоугольник между линиями, как на этом изображении,

и я сделал жест панорамирования, чтобы переместить прямоугольники, которые я рисую, между линиями, это работает, но это не то, что я хочу, когда я немного двигаю пальцем, он перемещается, и в этом проблемы, даже когда я двигаюсь только y он распознает наименьшее количество x и переместить оба, мне нужно переместить мой прямоугольник после того, как панорамирование больше, чем деления, затем переместить прямоугольник, я хочу, когда я выбираю свой прямоугольник и перемещаю палец в верхний или нижний раздел, влево или вправо один из существующего, в котором я нахожусь, затем переместите. так что я придумал это, но это не работает правильно, высота разделения - noteheight, а ширина между ними - timeSlotWidtho ,

@objc func handlePanGesture(_ gestureRecognizer: UIPanGestureRecognizer) {
    
    let touchLocation = gestureRecognizer.location(in: self)
    let location = touchLocation
    let timeSlotWidtho = bounds.width / CGFloat(numT)
    let note = CGFloat(numN) - location.y / noteHeight
    let startTime = Double(Int(location.x / timeSlotWidtho))
    let duration = Double(numT) / Double(numT)
    let noteHeight = bounds.height / CGFloat(numN)  
  
     var lastPanY: CGFloat = 0
     var lastPanx: CGFloat = 0

    switch gestureRecognizer.state {
        
    case .began:
        // Check if the user has touched a note rectangle
        
        // Check if a note with the same parameters already exists
        for (index, existingNote) in notes.enumerated() {
            if existingNote.note == Int(note) && existingNote.startTime == startTime && existingNote.duration == duration {
                lastPanY = location.y
                lastPanx = location.x
                selectedNoteIndex = index
                setNeedsDisplay()
                
            }
        }
        
    case .changed:
        // Move the selected note rectangle
        let translation = gestureRecognizer.translation(in: self)
        
     
        
        // Check if a note with the same parameters already exists
        for (index, existingNote) in notes.enumerated() {
            if existingNote.note == Int(note) && existingNote.startTime == startTime && existingNote.duration == duration {
                
                let deltaY = lastPanY - translation.y
                let deltax = lastPanx - translation.x
                
                
                if abs(deltaY) > noteHeight  {
                   
                    let direction = deltaY > lastPanY ? 1 : -1
                    let newValue =  existingNote.note + direction
                    if newValue >= 0 && newValue <= numN - 1 {
                        notes[index].note = newValue
                        // do something with intValue
                        lastPanY = translation.y
                        
                     
                        
                    
                        selectedNoteIndex = index
                        setNeedsDisplay()
                       
                    }
                    
                }
                if abs(deltax) > timeSlotWidtho  {
                 
                 let directionl = deltax < lastPanx ? 1.0 : -1.0
                 let newValuel =  existingNote.startTime + directionl
                 if newValuel >= 0 && Int(newValuel) <= numT  {
                 notes[index].startTime = newValuel
                 // do something with intValue
                 lastPanx = translation.x
                 
             
                 selectedNoteIndex = index
                 setNeedsDisplay()
                 
                 }
                 }
                
                selectedNoteIndex = index
                setNeedsDisplay()
               
            }
        }
        
        
        
    case .ended:
        // the end
        setNeedsDisplay()
    default:
        print("wef")
        break
    }
}

Вообще не смотрите вдаль. Не следи за пальцем. Просто посмотрите, в каком квадрате сейчас находится палец. Если заметки нет в этом квадрате, и этот квадрат пуст, переместите его туда. В противном случае ничего не делайте.

matt 31.03.2023 19:33

Спасибо за ваш ответ, хорошая идея, я сделал что-то подобное после прочтения вашего комментария, если вы посмотрите код, я определил let note = CGFloat (numN) - location.y / noteHeight, поэтому я определил новую переменную, которая является местоположением + перевод,тогда я нахожусь после кастрюли,поэтому сделал новую заметку,вместо локации это значение,работает нормально,пока я не делаю деление намного меньше,на фото 12/16,когда делаю 127/32, такой маленький, и мой прямоугольник такой маленький, и не работает, я могу выбрать прямоугольник, но не двигается, я не знаю, может ли место касания быть таким маленьким, или я неправильно определил примечание ,,

user8058965 01.04.2023 18:50

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

user8058965 01.04.2023 18:55

Заметка должна быть представлением, и это должна быть вещь, на которой есть распознаватель жестов панорамирования. Таким образом можно перетаскивать только заметку; жест, который начинается за пределами заметки, не будет затронут. Затем, как я уже говорил, в коде, который реагирует на перетаскивание, преобразуйте систему координат, чтобы «смотреть» на всю сетку, и выяснить, в каком квадрате вы находитесь в сетке, и переместить заметку туда тогда и только тогда, когда это площадь изменилась. Это действительно очень просто, не переусердствуйте. Отбросьте весь свой код «перевода», все это не имеет значения, просто посмотрите, где на самом деле сейчас находится палец.

matt 01.04.2023 19:00

Взгляните на мое приложение Diabelli's Theme (бесплатное), то, что я делаю, на самом деле сложнее, чем вам даже нужно, но все равно посмотрите на это: вы можете перетащить квадрат из сетки на любой другой квадрат, а затем поместить его туда. Это заменяет его квадратом, который уже был там, вам не нужна эта часть. И я на самом деле разрешаю физически перетаскивать квадрат и подсвечиваю квадрат, в который вы попадете, если отпустите сейчас, вы, похоже, тоже этого не хотите. Но что вам действительно нужно, так это осознание того, на чем сейчас закончился палец, как и то, что я делаю.

matt 01.04.2023 19:05

Вы имеете в виду, что каждая заметка должна быть представлением, а не cgrect? Другое дело, как мне посмотреть на всю сетку, как узнать, где мой палец? Есть ли открытый исходный код для вашего приложения Diabelli Theme? Я хотел бы изучить ваш код.

user8058965 01.04.2023 21:03

Вид — это рисунок плюс прикосновение. Прикосновение — это именно то, что вам нужно. Вы хотите перетащить рисунок; это вид. Что касается сетки: это просто элементарная арифметика.

matt 02.04.2023 02:12

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

user8058965 02.04.2023 10:41
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
8
82
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Я почти уверен, что это то, что вы описываете:

(В конце «видео» я демонстрирую, что начало перетаскивания за пределами заметки не влияет на заметку.)

Если это то, что вам нужно, просто следуйте инструкциям, которые я уже дал вам в комментариях. Сделайте каждую заметку представлением с помощью распознавателя жестов панорамирования. В состоянии .changed целевого метода этого распознавателя просто посмотрите на местоположение первого касания в представлении сетки и вычислите верхнюю левую точку прямоугольника сетки, в котором находится это касание. Если начало заметки не находится в этой точке, сделайте это так. .

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

@objc func dragged(_ g: UIPanGestureRecognizer) {
    guard let note = g.view else { return }
    if g.state == .changed {
        let pt = g.location(ofTouch: 0, in: grid)
        let targetOrigin = grid.divisionOriginFor(point: pt)
        let currentOrigin = note.frame.origin
        if currentOrigin != targetOrigin {
            var newframe = note.frame
            newframe.origin = targetOrigin
            if grid.bounds.intersection(newframe) == newframe {
                note.frame = newframe
            }
        }
    }
}

В этом коде мы предполагаем, что divisionOriginFor(point:) представления сетки — это метод, который смотрит, где находится point, и решает, в каком прямоугольнике сетки («делении») он находится, и сообщает верхний левый угол этого прямоугольника. Это может выглядеть так (я предполагаю, что xct и yct — это свойства, определяющие количество линий/делений для сетки):

func divisionOriginFor(point pt: CGPoint) -> CGPoint {
    let qx = Int(pt.x) / Int(bounds.width / CGFloat(xct))
    let qy = Int(pt.y) / Int(bounds.height / CGFloat(yct))
    return CGPoint(
        x: bounds.width / CGFloat(xct) * CGFloat(qx),
        y: bounds.height / CGFloat(yct) * CGFloat(qy)
    )
}

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

user8058965 06.04.2023 20:15

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