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

Posted

技术标签:

【中文标题】如何使用 Pan Gesture 增加/减少字体大小?【英文标题】:How to Increase/Decrease font size with Pan Gesture? 【发布时间】:2020-03-19 03:47:11 【问题描述】:

我正在对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】:

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

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

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 舍入到小数点后三位,但您的原始代码 sn-p 中包含了这一点,所以我保留了它。


就个人而言,我会遵循与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 中应用您需要的任何更改。


一些不相关的观察:

    不需要所有self. 引用。它只是增加了噪音,使代码更难阅读。

    不需要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)
    

    您实际上不需要任何当前散布在整个代码 sn-p 中的强制转换。

    所有bounds.size.widthbounds.size.height 可以分别是bounds.widthbounds.height,再次从代码中消除噪音。

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

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

    你应该只使用:

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

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

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

【讨论】:

以上是关于如何使用 Pan Gesture 增加/减少字体大小?的主要内容,如果未能解决你的问题,请参考以下文章

Spritekit中的Pan Gesture Recognizer移动对象

绑定键以增加/减少emacs中的字体大小

如何在 iOS Swift4 中滚动时增加/减少 UILabel 字体大小以及宽度和高度

立即调用 Pan Gesture 完成处理程序

为所有 UIScrollView 的子类为 Pan Gesture 提供标签

页面加载后如何增加页面上的所有字体大小?