翻譯:iOS視圖控制器編程指南(十)——自定義過渡動畫(Customizing the Transition Animations)
過渡動畫提供應用界面改變的視覺反饋。UIKit提供一組標準過渡樣式,用于present視圖控制器時使用,你可以自定義過渡補充標準過渡。
過渡動畫序列
過渡動畫互換視圖控制器的內容。有兩種類型的過渡:present和dismiss。present過渡會在應用視圖層級結構中添加一個新的視圖控制器,而dismiss過渡會從層級結構中刪除一個或多個視圖控制器。
過渡動畫的實現需要很多對象。UIKit提供所有涉及對象的默認版本,你可以自定義這些對象或僅僅繼承它們。如果你選擇正確的對象,你可以使用少量的代碼來創建動畫。如果你利用UIKit提供的現成代碼,可以很容易實現交互式動畫。
過渡委托
過渡動畫和自定義present的起點是過渡委托。過渡委托是你定義的一個對象,符合 UIViewControllerTransitioningDelegate協議。它的工作是為UIKit提供以下對象:
- 動畫對象,一個動畫對象負責創建動畫,用于顯示或隱藏視圖控制器的視圖。過渡委托可以提供獨立的動畫對象,用來present和dismiss視圖控制器。動畫對象符合 UIViewControllerAnimatedTransitioning協議。
- 交互式動畫對象。交互式動畫對象使用觸摸事件或手勢識別器,驅動自定義動畫時間。交互式動畫對象符合UIViewControllerInteractiveTransitioning協議。
創建一個交互式動畫最簡單的方法是繼承 UIPercentDrivenInteractiveTransition 類,并往子類中添加事件處理代碼。該類使用現有的動畫對象來控制創建動畫的時間。如果你創建自己的交互式動畫,你必須自己渲染動畫的每一幀。
- present控制器。present控制器管理屏幕上視圖控制器的present風格。系統提供了內置的present風格,你可以給自定義present控制器設置你自己的present風格。關于創建自定義present控制器的更多信息,參見創建自定義present(Creating Custom Presentations)。
分配過渡代理到視圖控制的 transitioningDelegate屬性,告訴UIKit你希望執行一個自定義的過渡或present。你的代理可以選擇哪個對象。如果你不提供動畫對象,UIKit使用視圖控制器的modalTransitionStyle屬性中的標準過渡動畫。
圖10-1展示了過渡代理、presented視圖控制器動畫對象之間的關系。只有當視圖控制器的 modalPresentationStyle屬性被設置為UIModalPresentationCustom,才使用present控制器。

關于如何實現過渡代理的更多信息,參見過渡代理的實現( Implementing the Transitioning Delegate)。關于過渡代理對象的方法的更多信息,參見UIViewControllerTransitioningDelegate協議引用(UIViewControllerTransitioningDelegate Protocol Reference)。
自定義動畫序列
當presented視圖控制器的 transitioningDelegate屬性包含一個有效的對象,UIKit使用你提供的自定義動畫對象present視圖控制器。當它準備present,UIKit調用過渡代理的animationControllerForPresentedController:presentingController:sourceController: 方法,檢索自定義動畫對象。如果對象可用,UIKit執行以下步驟:
- UIKit調用過渡代理的 interactionControllerForPresentation:方法,查看是否有可用的交互動畫對象。如果該方法返回nil,UIKit執行沒有交互的動畫。
- UIKit調用動畫對象的 transitionDuration: 方法來獲取動畫持續時間。
- UIKit調用適當的方法啟動動畫:對于非交互式動畫,UIKit調用動畫對象的 animateTransition:方法。對于交互式動畫,UIKit調用交互式動畫對象的 startInteractiveTransition:方法。
- UIKit等待動畫對象調用環境過渡對象的 completeTransition:方法。
在動畫完成后,自定義動畫調用該方法,一般在動畫的完成block中。調用該方法會結束過渡,讓UIKit知道可以調用完成處理器的 presentViewController:animated:completion:方法,調用動畫對象自己的animationEnded:方法。
當dismiss一個視圖控制器,UIKit調用過渡代理的 animationControllerForDismissedController:方法并執行以下步驟:
- UIKit調用過渡代理的 interactionControllerForDismissal:方法,查看是否有可用的交互式動畫對象。如果該方法返回nil,UIKit執行沒有交互的動畫。
- UIKit調用動畫對象的 transitionDuration: 方法來獲取動畫持續時間。
- UIKit調用適當的方法啟動動畫:對于非交互式動畫,UIKit調用動畫對象的 animateTransition:方法。對于交互式動畫,UIKit調用交互式動畫對象的 startInteractiveTransition:方法。
- UIKit等待動畫對象調用環境過渡對象的 completeTransition:方法。
在動畫完成后,自定義動畫調用該方法,一般在動畫的完成block中。調用該方法會結束過渡,讓UIKit知道可以調用完成處理器的 presentViewController:animated:completion:方法,調用動畫對象自己的animationEnded:方法。
重要:必須在動畫結束時調用 completeTransition: 方法。直到調用該方法,UIKit才結束過渡過程,從而返回到應用。
過渡環境對象
過渡動畫開始前,UIKit創建過渡環境對象,并添加如何執行動畫的信息。過渡環境對象是代碼中的重要部分。它實現了UIViewControllerContextTransitioning協議并存儲與過渡相關的視圖控制器和視圖的引用。它還存儲如何執行過渡的信息,包括該動畫是否為交互式。動畫對象需要這些信息來建立和執行實際動畫。
重要:當設置自定義動畫時,總是使用過渡環境對象中的對象和數據,而不是你自己管理的任何緩存信息。可以在任何條件下過渡,其中一些情況會改變動畫參數。保護過渡環境對象,這樣可以保證執行動畫的正確信息,而你的緩存信息可能是調用動畫方法時產生的過期信息。
圖10-2展示了過渡環境對象如何與其他對象交互。動畫對象接收其 animateTransition:方法的對象。你創建的動畫應該發生在提供的容器視圖中。例如,當present一個視圖控制器,將其視圖添加到容器視圖中作為子視圖。容器視圖可能是窗口或一個普通視圖,但是配置容器視圖是為了運行動畫。

關于過渡環境對象的更多信息,參見UIViewControllerContextTransitioning 協議引用(UIViewControllerContextTransitioning Protocol Reference)。
過渡協調器
內置過渡和自定義過渡,UIKit創建過渡協調器對象幫助需要執行的額外動畫。除了視圖控制器present和dismiss,當界面發生旋轉或視圖控制器的frame改變時會發生過渡。所有這些過渡代表視圖層級有變化。過渡協調器總是跟蹤這些變化同時渲染內容。訪問過渡協調器,獲取受影響的視圖控制器的 transitionCoordinator 屬性的對象。過渡協調器只存在過渡過程中。
圖10-3展示了present中視圖控制器與過渡協調器的關系。使用過渡協調器獲取過渡信息、注冊動畫block。過渡協調器對象符合 UIViewControllerTransitionCoordinatorContext協議,該對象提供時間信息、動畫當前狀態信息和過渡相關的視圖和視圖控制器。當執行動畫block,他們接收到具有相同信息的環境對象。

關于過渡協調器對象的更多信息,參見UIViewControllerTransitionCoordinator 協議引用(UIViewControllerTransitionCoordinator Protocol Reference)。環境信息可以用來配置動畫,關于環境信息,參見UIViewControllerTransitionCoordinatorContext協議引用(UIViewControllerTransitionCoordinatorContext Protocol Reference)。
使用自定義動畫present視圖控制器
使用自定義動畫present視圖控制器,在現有視圖控制器中執行以下動作方法:
- 創建想要present的視圖控制器。
- 創建自定義過渡代理對象,并將其分配給視圖控制器的 transitioningDelegate屬性。必須創建過渡代理的方法,在調用時返回自定義動畫對象。
- 調用 presentViewController:animated:completion:方法present視圖控制器。
當調用presentViewController:animated:completion:
方法,UIKit啟動present過程。在下一個run loop中啟動present,并持續到自定義動畫調用 completeTransition: 方法。交互式過渡允許你在過渡進行中處理觸摸事件,但非交互式過渡期間運行指定動畫對象。
實現過渡代理
過渡代理的目的是創建并返回自定義對象。列表10-1中展示了簡單過渡方法的實現。本例創建并返回一個自定義動畫對象,大部分實際工作由動畫對象本身處理。
列表10-1 創建動畫對象
-(id<UIViewControllerAnimatedTransitioning>)
animationControllerForPresentedController:(UIViewController *)presented
presentingController:(UIViewController *)presenting
sourceController:(UIViewController *)source {
MyAnimator* animator = [[MyAnimator alloc] init];
return animator;
}
過渡代理的其他方法和前面的方法一樣簡單。你可以基于應用的當前狀態,自定義邏輯返回不同動畫對象。關于過渡代理方法的更多信息,參見UIViewControllerTransitioningDelegate 協議引用(UIViewControllerTransitioningDelegate Protocol Reference)。
實現動畫對象
動畫對象是采用 UIViewControllerAnimatedTransitioning協議的對象。動畫對象創建動畫,該動畫在固定時間執行。動畫對象的關鍵是 animateTransition:方法,使用該方法可以創建實際動畫。動畫過程可以大致分為以下幾個部分:
- 獲取動畫參數。
- 使用核心動畫或 UIView 動畫方法創建動畫。
- 清理和完成過渡
獲取動畫參數
傳遞給方法的環境過渡對象包含執行動畫所需使用的數據。當你可以從環境過渡對象中獲取最新信息,不要使用緩存信息或者從視圖控制器獲取信息。present和dismiss視圖控制器有時涉及視圖控制器之外的對象。例如,自定義present控制器可能會添加一個背景視圖作為present的一部分。環境過渡對象考慮額外的視圖,為你提供正確的視圖用于動畫。
- 調用 viewControllerForKey:方法兩次獲取過渡中的“from”和“to”視圖控制器。永遠不要認為你知道哪些視圖控制器參與過渡。在適應新環境或者響應app請求時,UIKit可能改變視圖控制器。
- 調用 containerView方法獲取動畫的父視圖。添加所有關鍵子視圖到該視圖上。例如,在present期間,添加presented視圖控制器的視圖到該視圖上。
- 調用 viewForKey:方法獲取添加或刪除的視圖。視圖控制器的視圖可能不是唯一一個在過渡期間添加或刪除的視圖。present控制器可能添加視圖到層級結構,這些視圖也必須添加或刪除。 viewForKey:方法返回包含所有你需要添加或刪除的根視圖。
- 調用 finalFrameForViewController:方法獲取添加或刪除的視圖的最終frame。
環境過渡對象使用“from”和“to”命名法來識別視圖控制器、視圖和過渡中涉及的frame。“from”視圖控制器總是在過渡前顯示在屏幕上的視圖,“to”視圖控制器是在過渡之后顯示的視圖。如圖10-4,“from”和“to”視圖控制器在present和dismiss時交換位置。

交換值使編寫一個同時處理present和dismiss的動畫變得簡單。當你設計動畫時,你需要做的是了解該屬性是渲染present還是dismiss。兩者的唯一區別如下:
- 對于present,添加“to”視圖控制器到視圖層級結構。
- 對于dimiss,從視圖層級結構中刪除“from”視圖控制器。
創建過渡動畫
在典型的present中,屬于presented視圖控制器的視圖會被渲染。其他視圖可能作為present中的一部分,但動畫的主要目標是添加到視圖層級結構中的視圖。
當渲染主要視圖,動畫需要配置的基礎動作都是一樣的。從過渡環節對象中獲取對象和數據,使用這些信息創建實際動畫。
- present動畫使用 viewControllerForKey:和 viewForKey:方法檢索過渡中涉及的視圖控制器和視圖。設置“to”視圖的起始位置。設置其他屬性的初始值。通過過渡環境對象的 finalFrameForViewController:方法獲取“to”視圖的結束位置,添加“to”視圖作為容器視圖的子視圖。在動畫block中創建動畫,渲染“to”視圖到容器視圖。設置其他屬性為最終值。在完成block中,調用 completeTransition:方法執行其他清理。
- dismiss動畫使用 viewControllerForKey:和 viewForKey:方法檢索過渡中涉及的視圖控制器和視圖。計算“from”視圖的結束位置。該視圖屬于presented視圖控制器,現在被dismiss。添加“to”視圖到容器視圖作為其子視圖。
在present期間,當過渡完成時,屬于presenting視圖控制器的視圖被刪除。因此,在dismiss過程中,必須添加該視圖到容器視圖控制器。
- 在動畫block中創建動畫,渲染“from”視圖到容器視圖。設置其他屬性為最終值。在完成block中,調用completeTransition: 方法從視圖層級結構中刪除“from”視圖。根據需要執行其他清理。
圖10-5 展示了自定義present和dismiss過渡,以對角線的方式渲染。在present期間,presented視圖從屏幕外開始以對角線方式渲染到左邊,直到可見。在dismiss期間,視圖改變其方向,從右下角開始消失直到在屏幕外。

列表10-2 展示了如何實現過渡,如圖10-5。在檢索到動畫所需的對象后,animateTransition: 方法計算受影響的視圖的frame。在present期間,toView
變量代表presented視圖。在dismiss期間,fromView
變量代表dismiss視圖。presenting
屬性是動畫對象自定義屬性,當創建動畫時,過渡代理設置一個適當的值。
列表10-2 實現present和dismiss動畫
-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
// Get the set of relevant objects.
UIView *containerView = [transitionContext containerView];
UIViewController *fromVC = [transitionContext
viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toVC = [transitionContext
viewControllerForKey:UITransitionContextToViewControllerKey];
UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
// Set up some variables for the animation.
CGRect containerFrame = containerView.frame;
CGRect toViewStartFrame = [transitionContext initialFrameForViewController:toVC];
CGRect toViewFinalFrame = [transitionContext finalFrameForViewController:toVC];
CGRect fromViewFinalFrame = [transitionContext finalFrameForViewController:fromVC];
// Set up the animation parameters.
if (self.presenting) {
// Modify the frame of the presented view so that it starts
// offscreen at the lower-right corner of the container.
toViewStartFrame.origin.x = containerFrame.size.width;
toViewStartFrame.origin.y = containerFrame.size.height;
}
else {
// Modify the frame of the dismissed view so it ends in
// the lower-right corner of the container view.
fromViewFinalFrame = CGRectMake(containerFrame.size.width,
containerFrame.size.height,
toView.frame.size.width,
toView.frame.size.height);
}
// Always add the "to" view to the container.
// And it doesn't hurt to set its start frame.
[containerView addSubview:toView];
toView.frame = toViewStartFrame;
// Animate using the animator's own duration value.
[UIView animateWithDuration:[self transitionDuration:transitionContext]
animations:^{
if (self.presenting) {
// Move the presented view into position.
[toView setFrame:toViewFinalFrame];
}
else {
// Move the dismissed view offscreen.
[fromView setFrame:fromViewFinalFrame];
}
}
completion:^(BOOL finished){
BOOL success = ![transitionContext transitionWasCancelled];
// After a failed presentation or successful dismissal, remove the view.
if ((self.presenting && !success) || (!self.presenting && success)) {
[toView removeFromSuperview];
}
// Notify UIKit that the transition has finished
[transitionContext completeTransition:success];
}];
}
動畫后的清理
在過渡動畫結束后,關鍵要調用 completeTransition: 方法。調用該方法告訴UIKit過渡完成,用戶可能開始使用視圖控制器。調用該方法也會觸發一連串其他完成處理程序,包括 presentViewController:animated:completion:方法和動畫對象的 animationEnded:方法。最好在動畫block的完成處理程序中調用completeTransition:
方法。
因為過渡可以被取消,可以使用環境對象的transitionWasCancelled方法返回值來決定是否需要清理。當present被取消,動畫必須撤銷視圖層級結構的任何修改。一個成功的dismiss也需要類似的動作。
在過渡中添加交互
使動畫可交互的最簡單的方法是使用 UIPercentDrivenInteractiveTransition 對象。 UIPercentDrivenInteractiveTransition 對象使用現有動畫對象來控制動畫的時間。它也使用你提供的完成百分比。所有你需要做的是設置事件處理代碼,計算完成百分比和在每個事件到來時更新百分比。
你可以使用UIPercentDrivenInteractiveTransition
類或繼承該類。如果繼承,在子類中使用init方法(或startInteractiveTransition:
方法)來執行一次性事件處理代碼。之后,使用自定義事件處理代碼來計算新完成百分比并調用updateInteractiveTransition:
方法。當代碼確定過渡完成,調用 finishInteractiveTransition
方法。
列表10-3 展示了UIPercentDrivenInteractiveTransition
類的startInteractiveTransition:
方法的自定義實現。該方法設置pan手勢識別器來跟蹤觸摸事件,并設置手勢識別器到容器視圖。它也保存過渡環境的引用以備后用。
列表10-3 配置percent-driven交互式動畫
-(void)startInteractiveTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
// Always call super first.
[super startInteractiveTransition:transitionContext];
// Save the transition context for future reference.
self.contextData = transitionContext;
// Create a pan gesture recognizer to monitor events.
self.panGesture = [[UIPanGestureRecognizer alloc]
initWithTarget:self action:@selector(handleSwipeUpdate:)];
self.panGesture.maximumNumberOfTouches = 1;
// Add the gesture recognizer to the container view.
UIView* container = [transitionContext containerView];
[container addGestureRecognizer:self.panGesture];
}
手勢識別器為每個到來的新事件調用其動作方法。動作方法的視線可以使用手勢識別器的狀態信息來確定手勢是否成功,失敗或仍在進行中。在同一時間,可以使用最新觸摸事件信息來計算手勢的新百分比值。
列表10-4 展示pan手勢識別器調用的方法,如列表10-3所配置。新事件到達,該方法使用垂直距離計算完成動畫的百分比。當手勢結束時,該方法完成過渡。
列表10-4 使用事件更新動畫進程
-(void)handleSwipeUpdate:(UIGestureRecognizer *)gestureRecognizer {
UIView* container = [self.contextData containerView];
if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
// Reset the translation value at the beginning of the gesture.
[self.panGesture setTranslation:CGPointMake(0, 0) inView:container];
}
else if (gestureRecognizer.state == UIGestureRecognizerStateChanged) {
// Get the current translation value.
CGPoint translation = [self.panGesture translationInView:container];
// Compute how far the gesture has travelled vertically,
// relative to the height of the container view.
CGFloat percentage = fabs(translation.y / CGRectGetHeight(container.bounds));
// Use the translation value to update the interactive animator.
[self updateInteractiveTransition:percentage];
}
else if (gestureRecognizer.state >= UIGestureRecognizerStateEnded) {
// Finish the transition and remove the gesture recognizer.
[self finishInteractiveTransition];
[[self.contextData containerView] removeGestureRecognizer:self.panGesture];
}
}
注意:計算的值代表了完成整個動畫長度的百分比。對于交互式動畫,你可能希望在動畫中避免非線性效果如初始速度,阻尼值和非線性完成曲線。這些效果往往將事件觸摸位置與底層視圖分割開。
創建額外動畫
過渡中涉及的視圖控制器可以在present或過渡動畫上執行額外的動畫。例如,在過渡過程中,presented視圖控制器可能渲染其視圖層級結構,并添加運動效果或其他視覺反饋。任何對象都可以創建動畫,只要它能訪問presented或presenting視圖控制器的transitionCoordinator屬性。過渡協調器只存在過渡過程中。
調用過渡協調器的 animateAlongsideTransition:completion:和 animateAlongsideTransitionInView:animation:completion: 方法創建動畫。提供的block被存儲直到過渡動畫開始,此時他們和其他過渡動畫一起執行。
使用present控制器與動畫
對于自定義present,可以提供自己的present控制器給presented視圖控制器一個自定義外觀。present控制器管理任何獨立于視圖控制器和其內容的自定義chrome。例如,放置在視圖控制器視圖之后的模糊視圖由present控制器管理。事實上,它并不管理特定視圖控制器的視圖,這表明在應用中的任何視圖控制器可以使用相同的present控制器。
presented視圖控制器的過渡代理提供一個自定義present控制器。(視圖控制器的 modalTransitionStyle屬性必須為UIModalPresentationCustom。)present控制器與其他動畫對象一起運行。因為動畫對象渲染視圖控制器的視圖,present控制器渲染其他額外的視圖。在過渡結束時,present控制器可以執行視圖層級結構的任何調整。
關于如何創建自定義present控制器的信息,參見創建自定義present( Creating Custom Presentations)。
官方原文地址:
作者:栗子烤肉
鏈接:http://www.jianshu.com/p/e210bf690606
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
智能推薦
Angular練習之animations動畫二
返回目錄 回顧 文章基于angular的練手項目。文章目錄 前一篇文章《Angular練習之animations動畫》介紹了在angular中使用動畫的基本方法。 引入動畫模塊>創建動畫對象>在動畫載體上使用。我覺得其核心的內容在創建動畫對象上,今天我們就來練習創建不同的動畫對象trigger 開始練習 創建例子2 布局 ts 寫動畫效果,只定義狀態。 如下只寫兩個狀態看看效果。 添加...
QmlBook in chinese 編程之七 ---(Animations)
動畫(Animations) 動畫被用于屬性的改變。一個動畫定義了屬性值改變的曲線,將一個屬性值變化從一個值過渡到另一個值。動畫是由一連串的目標屬性活動定義的,平緩的曲線算法能夠引發一個定義時間內屬性的持續變化。所有在QtQuick中的動畫都由同一個計時器來控制,因此它們始終都保持同步,這也提高了動畫的性能和顯示效果。 &nbs...
transition屬性定義動畫
CSS3新增屬性:transition屬性,可以定義簡單動畫! 下面給大家演示一個demo,拋磚引玉。 而且不需要使用 js! CSS代碼如下 html代碼如下 效果圖如下 以上代碼知識一個簡單的小demo,希望對你們有所增益。...
瀏覽器 API 之 — Web Animations
現代的前端,在頁面上做動畫,已經是家常便飯。瀏覽器的渲染性能也越來越好,并且還逐漸提供了一系列的 Web Animations API。此 API 讓開發者可以使用 js 來創建動畫,相比之前使用 css 做動畫會方便很多,同時相比以前傳統的用 js 做的動畫會更加高效,并且相信未來此 API 的能力會越來越大。 Web Animations 可查看 w3c 的規范文檔。在 caniuse 上,可...
iOS動畫編程-View動畫[ 4 ]高級View Animations
View組合動畫 前幾節中我們已經學習了基本的View動畫,其實我們已經可以通過這些技術的組合實現非常酷炫的效果了,這節我們不會涉及新的API,一起來學習一下View動畫的組合 背景圖片的漸變效果 背景圖片的漸變效果在很多應用中都會遇到,其實利用前幾節學習到的基本View動畫就可以做到 我們現在希望在這兩個界面間進行切換 由于我們希望能夠柔和地過渡到第二個圖片,如果我們直接替換圖片的話會顯得非常突...
猜你喜歡
freemarker + ItextRender 根據模板生成PDF文件
1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...
電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!
Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...
requests實現全自動PPT模板
http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...