Масштабирование текста в наложении без размытия

#swiftui

#свифтуи

Вопрос:

У меня есть пятерка Text() в ан overlay() . После применения .scaleEffect() текст становится размытым/сглаженным:

введите описание изображения здесь

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

(Это упрощенная версия сложного элемента пользовательского интерфейса с вложенными накладками. Перемещение наложения ниже эффекта масштаба не является опцией.)

 import SwiftUI  struct ZoomFontView: View {  var body: some View {  Rectangle()  .frame(maxWidth: 100, maxHeight: 100)  .foregroundColor(Color.yellow)  .overlay(sub_view)  .scaleEffect(6) // Placeholder for MagnificationGesture  }    var sub_view: some View {  ZStack {  Rectangle()  .frame(maxWidth: 70, maxHeight: 70)  .foregroundColor(Color.mint)  .overlay(Text("Hello"))  }  } }  struct ZoomFontView_Previews: PreviewProvider {  static var previews: some View {  ZoomFontView()  } }  

Ответ №1:

scaleEffect Масштабирование похоже на изображение, вместо этого вам нужно масштабировать фон и текст отдельно, масштабируя шрифт Text , чтобы он отображался правильно.

Вот демонстрация возможного подхода. Протестировано с Xcode 13.1 / iOS 15.1

демонстрация1демо2

слева: масштаб = 1 справа: масштаб = 8

 struct ZoomFontView: View {   let scale: CGFloat = 8  var body: some View {  ZStack {  Rectangle()  .frame(maxWidth: 100, maxHeight: 100)  .foregroundColor(Color.mint)  .scaleEffect(1 * scale) // Placeholder for MagnificationGesture  Text("Hello").font(.system(size: 18 * scale))  .fixedSize()  }  } }  

Комментарии:

1. Спасибо, и да, конечно, это возможно. Но у меня сложный пользовательский интерфейс с вложенными накладками, поэтому я не могу использовать ZStacks вместо этого. Есть ли другой обходной путь?

2. Я обновил вопрос, чтобы отразить ограничения

Ответ №2:

Как текст, так и изображения отображаются в низкоуровневом слое CoreAnimation, который использует графический процессор (он же Металл) для отображения в виде растровой графики. Поэтому, если вы масштабируете слой, на котором отображается текст, он будет иметь тот же эффект масштабирования изображения, другими словами, он увеличит масштаб пикселей и заставит его попытаться «сгладить псевдоним» текста, чтобы сделать края более гладкими.

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

 Text("Hello")  // scale is the scale factor you're applying to the layer.  .font(.system(size: 16 * scale))