Как увеличить / уменьшить размер шрифта с помощью Pan Gesture? - PullRequest
0 голосов
/ 19 марта 2020

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

Я пытался использовать scale для добавления и вычитания значения из размера шрифта, но я не получаю точный результат.

@objc
func handleRotateGesture(_ recognizer: UIPanGestureRecognizer) {
    let touchLocation = recognizer.location(in: self.superview)
    let center = self.center

    switch recognizer.state {
    case .began:

        self.deltaAngle = CGFloat(atan2f(Float(touchLocation.y - center.y), Float(touchLocation.x - center.x))) - CGAffineTransformGetAngle(self.transform)
        self.initialBounds = self.bounds
        self.initialDistance = CGPointGetDistance(point1: center, point2: touchLocation)

    case .changed:
        let angle = atan2f(Float(touchLocation.y - center.y), Float(touchLocation.x - center.x))
        let angleDiff = Float(self.deltaAngle) - angle
        self.transform = CGAffineTransform(rotationAngle: CGFloat(-angleDiff))
        if let label = self.contentView as? UILabel {


            var scale = CGPointGetDistance(point1: center, point2: touchLocation) / self.initialDistance
            let minimumScale = CGFloat(self.minimumSize) / min(self.initialBounds.size.width, self.initialBounds.size.height)
            scale = max(scale, minimumScale)
            let scaledBounds = CGRectScale(self.initialBounds, wScale: scale, hScale: scale)


            var pinchScale = scale
            pinchScale = round(pinchScale * 1000) / 1000.0


            var fontSize = label.font.pointSize
            if(scale > minimumScale){
                if (self.bounds.height > scaledBounds.height) {
                     //  fontSize = fontSize - pinchScale
                       label.font = UIFont(name: label.font.fontName, size: fontSize - pinchScale)
                   }
                   else{
                      // fontSize = fontSize + pinchScale
                       label.font = UIFont(name: label.font.fontName, size: fontSize + pinchScale)
                   }
            } else {
                label.font = UIFont( name: label.font.fontName, size: fontSize)
            }

             print("PinchScale -- \(pinchScale), FontSize = \(fontSize)")



            self.bounds = scaledBounds

        } else {
            var scale = CGPointGetDistance(point1: center, point2: touchLocation) / self.initialDistance
            let minimumScale = CGFloat(self.minimumSize) / min(self.initialBounds.size.width, self.initialBounds.size.height)
            scale = max(scale, minimumScale)
            let scaledBounds = CGRectScale(self.initialBounds, wScale: scale, hScale: scale)
            self.bounds = scaledBounds
        }

        self.setNeedsDisplay()
    default:
        break
    }
}

Однако мы можем добиться этого, используя UIPinchGestureRecognizer. Но как мы можем сделать тот же эффект с UIPanGestureRecognizer? Любая помощь будет оценена. Спасибо.

1 Ответ

1 голос
/ 02 апреля 2020

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

  • Определить свойство для сохранения исходного размера шрифта:

    var initialPointSize: CGFloat = 0
    
  • В .began из жест, захватить текущий размер

    initialPointSize = (contentView as? UILabel)?.font?.pointSize ?? 0
    
  • В .changed отрегулируйте размер шрифта:

    let pinchScale = (scale * 1000).rounded() / 1000
    label.font = label.font.withSize(initialPointSize * pinchScale)
    

В сторону Я не уверен, что необходимо округлить scale до трех знаков после запятой, но у вас это было в исходном фрагменте кода, поэтому я сохранил это.


Лично я бы следовал тот же паттерн basi c с transform:

  • Определите свойства для захвата начального угла и текущего вида transform:

    var initialAngle: CGFloat = 0
    var initialTransform: CGAffineTransform = .identity
    
  • В .began запишите текущий начальный угол и существующее преобразование:

    initialAngle = atan2(touchLocation.y - center.y, touchLocation.x - center.x)
    initialTransform = transform
    
  • В .changed обновите transform:

    let angle = atan2(touchLocation.y - center.y, touchLocation.x - center.x)
    transform = initialTransform.rotated(by: angle - initialAngle)
    

Это избавляет вас от обратного инжиниринга угла, связанного с текущим преобразованием с CGAffineTransformGetAngle, и вместо этого просто применяет rotated(by:) к сохраненному преобразованию.

Таким образом, это, как размер точки и границы, представляет непротиворечивый шаблон: запишите начальное значение в .began и просто примените все необходимые изменения в .changed.


Несколько несвязанных наблюдений:

  1. Все эти self. ссылки не нужны. Он просто добавляет шум, который затрудняет чтение кода.

  2. Все эти преобразования между CGFloat и Float не нужны. Если вы используете функцию atof2 вместо atof2f, все они просто работают с CGFloat без приведения. Например, вместо

    let angle = atan2f(Float(touchLocation.y - center.y), Float(touchLocation.x - center.x))
    let angleDiff = Float(self.deltaAngle) - angle
    self.transform = CGAffineTransform(rotationAngle: CGFloat(-angleDiff))
    

    Вы можете просто сделать:

    let angle = atan2(touchLocation.y - center.y, touchLocation.x - center.x)
    transform = CGAffineTransform(rotationAngle: angle - deltaAngle)
    

    На самом деле вам не нужны никакие из приведений, которые в настоящее время разбросаны по всему фрагменту кода.

  3. Все эти bounds.size.width и bounds.size.height могут быть просто bounds.width и bounds.height соответственно, снова удаляя шум из кода.

  4. Когда настраивая размер шрифта, а не:

    label.font = UIFont(name: label.font.fontName, size: fontSize)
    

    Вы должны просто использовать:

    label.font = label.font.withSize(fontSize)
    

    Таким образом, вы сохраните все основные характеристики шрифта (вес и т. д. * 1111). *.) и просто измените размер.

  5. В вашем тесте if let label = contentView as? UILabel те же пять строк кода в вашем предложении else появляются и в предложении if , Вам следует просто переместить эти общие строки перед оператором if - else, и тогда вы можете полностью потерять предложение else, упрощая ваш код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...