如何使用Pan Gesture增大/减小字体大小?

时间:2020-03-19 03:47:11

标签: ios swift uilabel uipangesturerecognizer

我正在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 个答案:

答案 0 :(得分:1)

现在,您正在为标签的当前字体大小添加和删除点。我建议使用一种更简单的模式,使其与您在其他地方所做的工作更加一致,即仅捕获手势开始时的初始点大小,然后在用户的手指移动时将比例尺应用于保存的值。所以,我建议:

  • 定义属性以保存初始字体大小:

    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舍入到小数点后三位,但是您在原始代码段中保留了该位,所以我保留了该位。


我个人会使用与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. CGFloatFloat之间的所有这些强制类型转换都是不需要的。如果您使用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.widthbounds.size.height分别可以分别为bounds.widthbounds.height,从而再次消除了代码中的噪声。

  4. 调整字体大小时,而不是:

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

    您应该使用:

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

    这样,您可以保留字体的所有基本特征(粗细等),并只需调整大小即可。

  5. 在您的if let label = contentView as? UILabel测试中,else子句中相同的五行代码也出现在if子句中。您只需将这些常见行移到if-else语句之前,然后就可以完全丢掉else子句,从而简化代码。