Swift Media Player
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

169 lines
8.0 KiB

//
// Created by Marco Schmickler on 22.06.22.
// Copyright (c) 2022 Marco Schmickler. All rights reserved.
//
import Foundation
import SwiftUI
struct KAnimate: ViewModifier {
var dragOffset: CGSize
var spring: Bool
var off: Bool
init(dragOffset: CGSize, spring: Bool, off: Bool = false) {
self.dragOffset = dragOffset
self.spring = spring
self.off = off
}
func body(content: Content) -> some View {
if (off) {
content
} else if (spring) {
content.animation(.spring(response: 10, dampingFraction: 0.05), value: dragOffset)
} else {
content.animation(.easeOut(duration: 3), value: dragOffset)
}
}
}
struct SPhotoView: View {
@ObservedObject
var model: SPhotoModel
@State var lastScale: CGFloat = 2
@State var lastScaleValue: CGFloat = 1.0
@State var lastDragOffset: CGSize = CGSize.zero
@State var lastDrag: CGSize = CGSize.zero
@State var skip = false
@State var zooming = false
@State var startindex = -1
@State var animateX = 0
@State var dampen = 0.05
@State var jump = LocalManager.sharedInstance.settings.jump
init(model: SPhotoModel) {
self.model = model
}
var body: some View {
GeometryReader { geo in
// AsyncImage(item: model.selectedItem, thumb: false, placeholder: { Text("Loading ...") }, image: { Image(uiImage: $0).resizable() })
ZStack {
Image(uiImage: model.image)
.resizable().scaledToFit()
// SwiftUI.AsyncImage(url: URL(string: model.allItems[model.index].imageUrlAbsolute)) { image in
// image.resizable().scaledToFit()
// }
// placeholder: {
// if let i = model.selectedItem.thumbImage {
// Image(uiImage: i).resizable().scaledToFit()
// } else {
// Text("...")
// }
// }
.frame(height: geo.size.height).frame(width: geo.size.width, alignment: .leading)
.scaleEffect(model.scale).offset(model.dragOffset).modifier(KAnimate(dragOffset: model.dragOffset, spring: model.spring, off: zooming))
}
.onTapGesture(count: 2) {
let h1 = geo.size.height
let h2 = model.image.size.height
model.maxScale = h2 / h1
print("3 tapped!")
if model.scale == 1 {
model.scale = lastScale
} else {
lastScale = model.scale
model.scale = 1
model.dragOffset = CGSize.zero
}
}
.gesture(
DragGesture()
.onChanged { gesture in
let dragged = gesture.translation
let multi = (model.spring) ? 2.0 : 3.0
if startindex < 0 {
startindex = model.index
}
// print("\(startindex) \(dragged.width)")
if model.scale == 1 { //&& gesture.startLocation.x < 400 {
if (jump && dragged.height > 120) {
print("next")
model.next()
return
}
if (jump && dragged.height < -120) {
print("back")
model.back()
return
}
var i = startindex + Int(dragged.width / 15.0)
if i >= model.allItems.count {
i = model.allItems.count - 1
}
if i < 0 {
i = 0
}
if (i != model.index) {
ImageLoader.shared.backgroundQueue.cancelAllOperations()
model.index = i
model.selectedItem = model.allItems[model.index]
model.loadImage()
}
} else {
if (dragged.height * multi) + lastDragOffset.height > -500 * model.scale {
model.dragOffset = CGSize(width: (dragged.width * multi) + lastDragOffset.width, height: (dragged.height * multi) + lastDragOffset.height)
}
}
dampen = 0.05
lastDrag = dragged
print("scale \(model.scale) h \(model.dragOffset.height) w \(model.dragOffset.width)")
}
.onEnded { gesture in
startindex = -1
lastDragOffset = model.dragOffset
dampen = 0.05
skip = false
}
)
.gesture(MagnificationGesture()
.onChanged { val in
if !zooming {
zooming = true
lastDragOffset = model.dragOffset
}
let delta = val / self.lastScaleValue
self.lastScaleValue = val
model.scale = model.scale * delta
let h1 = geo.size.height
let h2 = model.image.size.height
model.maxScale = h2 / h1
let width = geo.size.width / 2;
model.dragOffset.width = lastDragOffset.width + (width - (width / model.scale))
let height = geo.size.height / 2;
model.dragOffset.height = lastDragOffset.height + (height - (height / model.scale))
print("scale \(model.scale) h \(model.dragOffset.height) w \(model.dragOffset.width) lh \(lastDragOffset.height) lw \(lastDragOffset.width)")
// print("scale \(model.scale) frame \(h1) image \(h2) \(h2/h1)")
}
.onEnded { val in
zooming = false
// without this the next gesture will be broken
self.lastScaleValue = 1.0
})
}
.contentShape(Rectangle()).clipped();
}
}