ios - 仅拖动和缩放“选定”视图
问题描述
完成斯坦福 cs193p 课程 (iOS SwiftUI) 的一项任务,并且难以将拖动和缩放手势应用于仅选定的视图 (emojis)。选定的表情符号存储在 selectedEmojis 集中。当前设置如下:在我们拥有的 struct EmojiArtDocumentView 中(我只留下了相关代码):
import SwiftUI
struct EmojiArtDocumentView: View {
@ObservedObject var document: EmojiArtDocument
@State var selectedEmojis: Set<EmojiArtModel.Emoji> = []
var body: some View {
VStack(spacing: 0) {
documentBody
palette
}
}
var documentBody: some View {
GeometryReader { geometry in
ZStack {
Color.white.overlay(
OptionalImage(uiImage: document.backgroundImage)
.scaleEffect(zoomScale)
.position(convertFromEmojiCoordinates((0,0), in: geometry))
)
.gesture(doubleTapToZoom(in: geometry.size))
ForEach(document.emojis) { emoji in
Text(emoji.text)
.font(.system(size: fontSize(for: emoji)))
.scaleEffect(zoomScale)
.position(position(for: emoji, in: geometry))
.saturation(selectedEmojis.contains(emoji) ? 0 : 1)
.onTapGesture {
select(emoji)
}
.gesture(selectedEmojis.contains(emoji) ? panGesture().simultaneously(with: zoomGesture()) : nil)
}
}
}
}
// 下面我们实现了缩放和平移(拖动):
@State private var steadyStateZoomScale: CGFloat = 1 //document's zoom scale when not zooming with pinch
@GestureState private var gestureZoomScale: CGFloat = 1
private var zoomScale: CGFloat {
steadyStateZoomScale * gestureZoomScale
}
private func zoomGesture() -> some Gesture {
MagnificationGesture()
.updating($gestureZoomScale) { latestGestureScale, gestureZoomScale, _ in
gestureZoomScale = latestGestureScale
}
.onEnded { gestureScaleAtEnd in
//at the end sets the new value to steadyStateZoomScale
steadyStateZoomScale *= gestureScaleAtEnd
}
}
private func doubleTapToZoom(in size: CGSize) -> some Gesture {
TapGesture(count: 2)
.onEnded {
withAnimation {
zoomToFit(document.backgroundImage, in: size)
}
}
}
private func zoomToFit(_ image: UIImage?, in size: CGSize) {
if let image = image, image.size.width > 0, image.size.height > 0, size.width > 0, size.height > 0 {
let hZoom = size.width / image.size.width
let vZoom = size.height / image.size.height
steadyStatePanOffset = .zero
steadyStateZoomScale = min(hZoom, vZoom)
}
}
// MARK: - Panning
@State private var steadyStatePanOffset: CGSize = CGSize.zero
@GestureState private var gesturePanOffset: CGSize = CGSize.zero
private var panOffset: CGSize {
// + made via extension CGSize
(steadyStatePanOffset + gesturePanOffset) * zoomScale
}
private func panGesture() -> some Gesture {
DragGesture()
.updating($gesturePanOffset) { latestDragGestureValue, gesturePanOffset, _ in
gesturePanOffset = latestDragGestureValue.translation / zoomScale
}
.onEnded { finalDragGestureValue in
steadyStatePanOffset = steadyStatePanOffset + (finalDragGestureValue.translation / zoomScale)
}
}
如您所见,我尝试将条件设置为视图修饰符: .gesture(selectedEmojis.contains(emoji) ? panGesture().simultaneously(with: zoomGesture()) : nil) 但结果是我可以移动整个如果我触摸“已选择”,则选择,如果我触摸“未选择”,则不会移动。不知道如何仅使“选定”的表情符号移动。如果有人分享如何实现它的想法,将不胜感激。似乎不需要使@GestureState private vargesturePanOffset var 成为每个表情符号视图一个 vars 的数组...
解决方案
推荐阅读
- python - 如何使用 python-docx 更改所有 .docx 文档的字体大小
- c++ - 无法在顶点着色器中设置输入位置
- c# - 从返回的模型中显示网格中的数据
- java - 其他应用程序的 Android Broadcastreceiver 安装/删除不起作用
- ios - Ionic iOS 构建在 iPhone 上工作,但在 iPad 上不工作
- elasticsearch - 如何避免在弹性搜索中重复无痛脚本
- typescript - 在 Angular html 表单中,当在 Angular 组件中调用 Typescript 文件时,小写的 id 或名称变为大写(例如 make as Make)。这是为什么?
- mysql - 连接同一个表中的两个外键引用同一个主键
- python-3.x - 以下代码在输入后没有执行(打印推文)是否有原因?
- android - 如何修复订阅可观察对象以在 rxjava 中获取数据