دعنا SwiftUI بطاقات متحركة تدعم الإيماءات على SwiftUI :
أردت أن أضيف معاينة مفصلة ، ولكن حجم GIF ليس الأرثوذكسية. يمكن الاطلاع على معاينة كبيرة على الرابط أو في الفيديو التعليمي .
سوف تكون مطلوبة
SwiftUI الآن في مرحلة تجريبية ، ويتم تثبيته مع Xcode الجديد ، والذي هو أيضا في مرحلة تجريبية. والخبر السار هو أن Xcode الجديد يمكن وضعه بجوار القديم ولا يمكن أن تشعر بأي ألم.

يمكنك تنزيله من الرابط في قسم Applications .
ربما تكون قد شاهدت معاينات في الوقت الفعلي أثناء العمل مع SwiftUI . لتنشيطه ، وكذلك بعض قوائم السياق ، تحتاج إلى تثبيت الإصدار التجريبي من نظام macOS Catalina . لن تفعل من دون ألم. لم أراهن ، لذلك سأقوم بتشغيل المحاكاة بالطريقة القديمة.
مشروع جديد
إنشاء Single View Application مع علامة اختيار إضافية - SwiftUI :
انتقل إلى ملف ContentView.swift . وريث PreviewProvider هو المسؤول عن المعاينة. نظرًا لأننا لن نستخدمها ، فسنترك الحد الأدنى من الشفرة اللازمة:
 import SwiftUI struct ContentView: View { var body: some View { } } 
آمل أن يكون هناك بالفعل فهم مشترك حول SwiftUI ، ونحن لن نتحدث عن نقاط تافهة.
بطاقات
يتم ترتيب البطاقات واحدة تلو الأخرى ، وبالتالي سنستخدم ZStack . اسمحوا لي أن أذكرك أن هناك خيارين آخرين لتجميع العناصر: HStack - أفقيًا و VStack - عموديًا. للوضوح:

أضف البطاقة الأولى:
 struct ContentView: View { var body: some View { return ZStack { Rectangle() .fill(Color.black) .frame(height: 230) .cornerRadius(10) .padding(16) } } } 
أضفنا هنا مستطيلًا ، 230pt باللون الأسود ، مرتفعًا 230pt ، 230pt الحواف بمقدار 10pt 16pt الهوامش من جميع الجوانب على 16pt .
تتم إضافة النص الموجود في البطاقة إلى كتلة ZStack بعد المستطيل:
 Text("Main Card") .color(.white) .font(.title) .bold() 
قم بتشغيل المشروع لمعرفة النتيجة المتوسطة:
ولكن هناك ثلاثة منهم!

للراحة ، MainCard كود MainCard :
 struct MainCard: View { var title: String var body: some View { ZStack { Rectangle() .fill(Color.black) .frame(height: 230) .cornerRadius(10) .padding(16) Text(title) .color(.white) .font(.largeTitle) .bold() } } } 
سيظهر title في المُهيئ. هذا النص سيكون على البطاقة. أضف بطاقة إلى ContentView ، وفي الوقت نفسه سنرى معلمة جديدة في ContentView :
 struct ContentView: View { var body: some View { return MainCard(title: "Main Card") } } 
نحن نعرف بالفعل كيفية عمل الكود ، لذلك حدد على الفور فئة لبطاقات الخلفية:
 struct Card: View { var title: String var body: some View { ZStack { Rectangle() .fill(Color(red: 68 / 255, green: 41 / 255, blue: 182 / 255)) .frame(height: 230) .cornerRadius(10) .padding(16) Text(title) .color(.white) .font(.title) .bold() } } } 
تعيين لون مختلف ونمط للنص. بقية الكود يكرر MainCard الأسود. أضف بطاقتي خلفية إلى ContentView . يتم ترتيب البطاقات واحدة تلو الأخرى ، لذلك ZStack في ZStack . كود عرض ContentView :
 struct ContentView: View { var body: some View { return ZStack { Card(title: "Third card") Card(title: "Second Card") MainCard(title: "Main Card") } } } 
توجد بطاقات الخلفية تحت الأسود وحتى الآن غير مرئية. أضف إلى الأعلى إزاحة وحشوة من الحواف:
 Card(title: "Third card") .blendMode(.hardLight) .padding(64) .padding(.bottom, 64) Card(title: "Second Card") .blendMode(.hardLight) .padding(32) .padding(.bottom, 32) MainCard(title: "Main Card") 
الآن تشبه النتيجة الإعلان في بداية البرنامج التعليمي:
دعنا ننتقل إلى الإيماءات ، إلى جانب هذا إلى الرسوم المتحركة.
لفتات
الطريقة التي يتم بها تنفيذ الإيماءات ستجبرني على ناقص الكرمة وترك مراجعة سامة.

قبل أن ترى الكود ، يرجى ملاحظة أنه مدرج على developer.apple.com كمثال. الانطباع الأول هو خادع ، في الواقع أحببت ذلك.
قم بتعريف التعداد في ContentView :
 enum DragState { case inactive case dragging(translation: CGSize) var translation: CGSize { switch self { case .inactive: return .zero case .dragging(let translation): return translation } } var isActive: Bool { switch self { case .inactive: return false case .dragging: return true } } } 
سوف DragState جعل العمل مع لفتة أكثر راحة. إضافة dragState ContentView إلى ContentView :
 @GestureState var dragState = DragState.inactive 
سيكون هناك السحر.

أينما يتم استخدام dragState ، سيتم تطبيق القيم الجديدة تلقائيًا. أعلن لفتة:
 let dragGester = DragGesture() .updating($dragState) { (value, state, transaction) in state = .dragging(translation: value.translation) } 
أضف لفتة إلى البطاقة الرئيسية وقم بتعيين offset :
 MainCard(title: "Main Card") .offset( x: dragState.translation.width, y: dragState.translation.height ) .gesture(dragGester) 
هل تساوي الإزاحة قيمة المعلمة عند الوصول إليها؟ لا ، سيكون دائمًا متساويًا . هذا هو السحر.
سوف تتبع البطاقة بإصبع باستخدام الماوس ، ولكن بدون رسوم متحركة:
يجب أن تغير بطاقات الخلفية أيضًا موضعها ( على الأقل أردنا ذلك ). أضف رمزًا لهم مرتبطًا بحالة الإيماءة. سوف rotation3DEffect تدوير البطاقة حتى تصبح الإيماءة نشطة:
 Card(title: "Third card") .rotation3DEffect(Angle(degrees: dragState.isActive ? 0 : 60), axis: (x: 10.0, y: 10.0, z: 10.0)) .blendMode(.hardLight) .padding(dragState.isActive ? 32 : 64) .padding(.bottom, dragState.isActive ? 32 : 64) Card(title: "Second Card") .rotation3DEffect(Angle(degrees: dragState.isActive ? 0 : 30), axis: (x: 10.0, y: 10.0, z: 10.0)) .blendMode(.hardLight) .padding(dragState.isActive ? 16 : 32) .padding(.bottom, dragState.isActive ? 0 : 32) 
كيف يمكنك أيضا استخدام 3D ، يمكنك أن تبحث هنا . أضفت أيضا blendMode . تشبه الأوضاع الأدوات الموجودة في Photoshop و Sketch.
على الرغم من أن التغييرات مطبقة وليست متحركة ، فلنصلحها.
حيوية
سوف يفاجأ كم هو بسيط. فقط أضف خطًا:
 .animation(.spring()) 
إضافة لكل بطاقة. الآن سيتم تطبيق أي تغييرات بشكل متحرك ، في حالتنا ، هذه هي أحجام المسافة البادئة ودوران ثلاثي الأبعاد offset . إذا كنت بحاجة إلى رسوم متحركة ذات منحنيات ، استخدم الوضع basic .
الزينة
أضف ظل العرض الرئيسي ودورته ، مرتبطًا بالإزاحة:
 .rotationEffect(Angle(degrees: Double(dragState.translation.width / 10))) .shadow(radius: dragState.isActive ? 8 : 0) 
إذا قمت بتشغيل المشروع ، فسترى المرجع منذ بداية البرنامج التعليمي. تشغيل المعاينة غير مرئي ، واسحب البطاقة إلى الجانب لرؤية التأثير.
للباحثين
→ يمكن العثور على رمز المشروع في المستودع
يكفي نسخ الملف إلى المشروع ، ولا توجد إعدادات إضافية مطلوبة. لا تخف من أن الكود الصغير هو أحد SwiftUI .
إذا كان من المناسب لك مشاهدة الفيديو ، فقم بإلقاء نظرة على البرنامج التعليمي. بالمناسبة ، في الفيديو يمكنني استخدام معاينات الوقت الحقيقي.