I am at the moment attempting out a small notice app. I wish to add a sticky notice to the drawing pad. I would like to have the ability to transfer and resize the sticky notice.
Transferring already works, however altering the scale doesn’t work in a managed manner. Are you able to assist me with this? Both it would not work in any respect to alter the scale, or it adjustments fully uncontrolled. Right here is the code
import SwiftUI
import PencilKit
struct NotesView: View {
@State non-public var canvasView = PKCanvasView()
@State non-public var toolPicker = PKToolPicker()
@State non-public var isToolPickerVisible = false
@State non-public var stickyNotes: [StickyNoteView] = [] // Array für die Sticky Notes
@State non-public var selectedColor: Coloration = .yellow // Standardfarbe für Sticky Notes
var physique: some View {
VStack {
// Werkzeugleiste mit zusätzlichen Optionen
HStack {
Button(motion: toggleToolPicker) {
Picture(systemName: isToolPickerVisible ? "pencil.circle.fill" : "pencil.circle")
}
Button(motion: createStickyNote) {
Picture(systemName: "notice.textual content")
}
Button(motion: addShape) {
Picture(systemName: "sq..on.circle")
}
Button(motion: addTextField) {
Picture(systemName: "textformat")
}
Button(motion: addPhoto) {
Picture(systemName: "picture")
}
Button(motion: undoLastAction) {
Picture(systemName: "arrow.uturn.backward")
}
Menu {
// Farbauswahl für Sticky Notes
Button(motion: { selectedColor = .yellow }) {
Textual content("Gelb")
Picture(systemName: "circle.fill").foregroundColor(.yellow)
}
Button(motion: { selectedColor = .inexperienced }) {
Textual content("Grün")
Picture(systemName: "circle.fill").foregroundColor(.inexperienced)
}
Button(motion: { selectedColor = .blue }) {
Textual content("Blau")
Picture(systemName: "circle.fill").foregroundColor(.blue)
}
Button(motion: { selectedColor = .pink }) {
Textual content("Pink")
Picture(systemName: "circle.fill").foregroundColor(.pink)
}
} label: {
Label("Farbe", systemImage: "paintpalette")
}
}
// Zeichenfläche (Canvas) für das Zeichnen
ZStack {
PKCanvasRepresentable(canvasView: $canvasView)
.onAppear {
toolPicker.setVisible(isToolPickerVisible, forFirstResponder: canvasView)
toolPicker.addObserver(canvasView)
canvasView.becomeFirstResponder() // Setze die Canvas als First Responder
}
.onChange(of: isToolPickerVisible) { newValue in
toolPicker.setVisible(newValue, forFirstResponder: canvasView)
if newValue {
canvasView.becomeFirstResponder()
}
}
.gesture(DragGesture(minimumDistance: 0).onChanged { _ in
// Werkzeugleiste aktivieren, wenn der Apple Pencil benutzt wird
if !isToolPickerVisible {
isToolPickerVisible = true
toolPicker.setVisible(true, forFirstResponder: canvasView)
}
})
// Sticky Observe-Ansicht auf der Zeichenfläche hinzufügen
ForEach(stickyNotes) { stickyNote in
stickyNote
}
}
}
}
// Sichtbarkeit des Werkzeugpickers umschalten und das Image ändern
func toggleToolPicker() {
isToolPickerVisible.toggle()
toolPicker.setVisible(isToolPickerVisible, forFirstResponder: canvasView)
}
// Sticky Observe erstellen und zur Liste hinzufügen
func createStickyNote() {
let newStickyNote = StickyNoteView(shade: selectedColor) // Verwende die ausgewählte Farbe
stickyNotes.append(newStickyNote)
}
func addShape() {
// Funktion, um eine Type hinzuzufügen
}
func addTextField() {
// Funktion, um ein Textfeld hinzuzufügen
}
func addPhoto() {
// Funktion, um ein Foto hinzuzufügen
}
func undoLastAction() {
canvasView.undoManager?.undo()
}
}
// Canvas-Representable zum Verbinden von UIKit's PKCanvasView mit SwiftUI
struct PKCanvasRepresentable: UIViewRepresentable {
@Binding var canvasView: PKCanvasView
func makeUIView(context: Context) -> PKCanvasView {
return canvasView
}
func updateUIView(_ uiView: PKCanvasView, context: Context) {
// Aktualisiere die Canvas-Ansicht falls nötig
}
}
struct StickyNoteView: View, Identifiable {
let id = UUID()
@State non-public var place: CGSize = .zero // Place der Sticky Observe
@State non-public var lastPosition: CGSize = .zero // Letzte bekannte Place
@State non-public var textual content: String = "" // Inhalt der Sticky Observe
@State non-public var dimension: CGSize = CGSize(width: 200, top: 200) // Größe der Sticky Observe
@State non-public var isSelected: Bool = false // Ob die Sticky Observe ausgewählt ist
@State non-public var isResizing: Bool = false // Ob gerade eine Größenänderung durchgeführt wird
@State non-public var lastSize: CGSize = CGSize(width: 200, top: 200) // Letzte Größe
let shade: Coloration
var physique: some View {
ZStack(alignment: .topLeading) {
// Sticky Observe Hintergrund
shade
.body(width: dimension.width, top: dimension.top)
.cornerRadius(10)
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(isSelected ? Coloration.blue : Coloration.clear, lineWidth: 3) // Markierungsrahmen, wenn ausgewählt
)
.overlay(
// Resize-Griffe nur anzeigen, wenn die Sticky Observe ausgewählt ist
isSelected ? resizeHandles : nil, alignment: .bottomTrailing
)
// Textfeld innerhalb der Sticky Observe
TextField("Notiz", textual content: $textual content)
.padding()
.background(Coloration.clear)
.body(width: dimension.width - 20, top: dimension.top - 20)
.multilineTextAlignment(.main)
.disabled(!isSelected) // Nur bei Auswahl kann geschrieben werden
}
.offset(x: place.width, y: place.top) // Place der Sticky Observe
.gesture(
DragGesture()
.onChanged { worth in
// Sticky Observe verschieben, wenn nicht resized wird
if !isResizing {
self.place = CGSize(width: lastPosition.width + worth.translation.width,
top: lastPosition.top + worth.translation.top)
}
}
.onEnded { _ in
self.lastPosition = self.place
}
)
.onTapGesture {
// Sticky Observe auswählen oder abwählen
isSelected.toggle()
}
}
// Resize-Griffe an allen Ecken und Seiten
var resizeHandles: some View {
Group {
resizeHandle(place: .bottomRight)
resizeHandle(place: .bottomLeft)
resizeHandle(place: .topRight)
resizeHandle(place: .topLeft)
resizeHandle(place: .left)
resizeHandle(place: .proper)
resizeHandle(place: .high)
resizeHandle(place: .backside)
}
}
// Einzelne Resize-Griffe basierend auf der Place
func resizeHandle(place: ResizePosition) -> some View {
ZStack {
Circle()
.fill(Coloration.blue) // Blau gefüllte Resize-Griffe
.body(width: 10, top: 10) // Kleinere Griffe
.gesture(
DragGesture()
.onChanged { worth in
change place {
case .bottomRight:
self.dimension.width = max(100, lastSize.width + worth.translation.width)
self.dimension.top = max(100, lastSize.top + worth.translation.top)
case .bottomLeft:
self.dimension.width = max(100, lastSize.width - worth.translation.width)
self.dimension.top = max(100, lastSize.top + worth.translation.top)
self.place.width = lastPosition.width + worth.translation.width
case .topRight:
self.dimension.width = max(100, lastSize.width + worth.translation.width)
self.dimension.top = max(100, lastSize.top - worth.translation.top)
self.place.top = lastPosition.top + worth.translation.top
case .topLeft:
self.dimension.width = max(100, lastSize.width - worth.translation.width)
self.dimension.top = max(100, lastSize.top - worth.translation.top)
self.place = CGSize(width: lastPosition.width + worth.translation.width, top: lastPosition.top + worth.translation.top)
case .left:
self.dimension.width = max(100, lastSize.width - worth.translation.width)
self.place.width = lastPosition.width + worth.translation.width
case .proper:
self.dimension.width = max(100, lastSize.width + worth.translation.width)
case .high:
self.dimension.top = max(100, lastSize.top - worth.translation.top)
self.place.top = lastPosition.top + worth.translation.top
case .backside:
self.dimension.top = max(100, lastSize.top + worth.translation.top)
}
self.isResizing = true
}
.onEnded { _ in
self.lastSize = self.dimension
self.lastPosition = self.place
self.isResizing = false
}
)
}
.place(x: place == .left || place == .topLeft || place == .bottomLeft ? 0 : dimension.width,
y: place == .high || place == .topLeft || place == .topRight ? 0 : dimension.top)
}
}
// Positionen für die Resize-Griffe
enum ResizePosition {
case topLeft, topRight, bottomLeft, bottomRight, left, proper, high, backside
}