SwiftUI(iOS 16)中Canvas内如何围绕中心旋转文本?
解决SwiftUI Canvas中文本90°旋转问题
你的问题出在两个核心点:
- 直接调用
context.rotate会修改整个画布的坐标系,导致所有后续绘制内容都被旋转,而非仅目标文本。 Text的rotationEffect是SwiftUI View层级的修饰符,Canvas的context.draw在渲染View时不会识别这类变换操作——它是将View静态渲染为图形内容,不处理View的变换属性。
正确实现方式:通过Context状态管理局部旋转
利用saveState()和restoreState()隔离旋转操作的影响,配合坐标平移实现文本围绕自身中心在指定位置旋转:
Canvas { context, size in let textContent = String(drinkFrom) let textView = Text(textContent) .font(.custom("HelveticaNeue", size: 12)) .foregroundColor(.textUnselected) // 保存当前画布状态,避免旋转影响其他绘制内容 context.saveState() // 平移坐标系原点到文本目标位置 let targetPosition = CGPoint(x: drinkFromOriginX, y: size.height/2) context.translateBy(x: targetPosition.x, y: targetPosition.y) // 围绕当前原点(即文本中心)旋转90° context.rotate(by: .degrees(90)) // 在原点绘制文本,锚点设为.center,确保文本中心与目标位置重合 context.draw(textView, at: .zero, anchor: .center) // 恢复画布初始状态 context.restoreState() }
原理说明
saveState()会保存当前画布的坐标系、变换等状态,restoreState()则恢复到该状态,确保旋转操作仅作用于这段文本的绘制。translateBy将坐标系原点移到你想要放置文本的位置,此时旋转坐标系,文本的绘制中心就会固定在该位置,实现「围绕自身中心旋转」的效果。
备选方案:直接绘制NSAttributedString
如果不需要依赖SwiftUI的Text样式,也可以用更底层的方式绘制文本,精度更高:
Canvas { context, size in let textString = String(drinkFrom) let font = UIFont(name: "HelveticaNeue", size: 12)! let textColor = UIColor.textUnselected // 配置文本属性 let attributes: [NSAttributedString.Key: Any] = [ .font: font, .foregroundColor: textColor ] let attributedText = NSAttributedString(string: textString, attributes: attributes) // 计算文本尺寸,用于居中偏移 let textSize = attributedText.size() context.saveState() let targetPoint = CGPoint(x: drinkFromOriginX, y: size.height/2) context.translateBy(x: targetPoint.x, y: targetPoint.y) context.rotate(by: .degrees(90)) // 绘制文本时偏移半宽半高,确保中心与原点重合 attributedText.draw(at: CGPoint(x: -textSize.width/2, y: -textSize.height/2)) context.restoreState() }
内容的提问来源于stack exchange,提问作者alex.bour
相关产品推荐
相关产品推荐

