TCCMapTileAnimation 0.4.18

TCCMapTileAnimation 0.4.18

测试已测试
Lang语言 Obj-CObjective C
许可证 Apache-2.0
发布最新发布2019年11月

Gary RudolphJoost KeminkRam JoshiJohn StarinMichael Byrns维护。



  • Richard Shin、Bruce Johnson 和 Matthew Sniff

TCCMapTileAnimation

一个用于从瓦片图创建动画地图覆盖层的 iOS 库。

特性

  • 使用来自本地文件系统或地图瓦片服务器的地图瓦片,在 MKMapView 上创建一个动画覆盖层,其中动画的每一帧由一组瓦片组成。
  • 允许用户播放、暂停以及在动画时间轴上跳转/快进。
  • 动画覆盖层流畅且一致。根据设备的图形性能,绘制动画帧时可能会有很少或没有瓦片或闪烁。
  • 当用户在地图上平移时,覆盖层将回退到按需检索和渲染瓦片。

TCCMapTileAnimation 不提供任何 UI 播放控制,但请查看示例项目,了解如何将 UI 控件连接到覆盖层。

入门

安装

如果您使用 CocoaPods,请将 pod 'TCCMapTileAnimation' 添加到您的 Podfile,然后运行 pod install

您也可以将 TCCMapTileAnimation 目录中的 .m.h 文件手动添加到您的项目中,或者从这些文件创建一个静态库并添加到您的项目中。

必备条件

TCCMapTileAnimation 使用 NSURLCache 来快速查找和渲染已经从网络中获取的覆盖图块。这必须由您的应用程序明确设置,最好在 application:didFinishLaunchingWithOptions 中进行。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    NSURLCache *cache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024
                                                      diskCapacity:20 * 1024 * 1024
                                                          diskPath:nil];
    [NSURLCache setSharedURLCache:cache];
    
    ...
}

创建图层

NSArray *templateURLs = @[@"http://url.to/first_frame/{z}/{x}/{y}", @"http://url.to/second_frame/{z}/{x}/{y}"];
self.overlay = [[TCCAnimationTileOverlay alloc] initWithMapView:self.mapView templateURLs:templateURLs frameDuration:0.50 minimumZ:3 maximumZ:9 tileSize:CGSizeMake(256, 256)];
self.overlay.delegate = self;
[self.mapView addOverlay:self.overlay];

创建图层时设置 URL 会话配置

NSURLSessionConfiguration * configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSArray *templateURLs = @[@"http://url.to/first_frame/{z}/{x}/{y}", @"http://url.to/second_frame/{z}/{x}/{y}"];
self.overlay = [[TCCAnimationTileOverlay alloc] initWithTemplateURLs: templateURLs, configuration: configuration, frameDuration:0.50 minimumZ:3 maximumZ:9 tileSize:CGSizeMake(256, 256)];
self.overlay.delegate = self;
[self.mapView addOverlay:self.overlay];

创建图层渲染器

- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay
{
	if ([overlay isKindOfClass:[TCCAnimationTileOverlay class]]) {
        self.animatedTileRenderer = [[TCCAnimationTileOverlayRenderer alloc] initWithOverlay:overlay];
        // Optional - draws tile grid debug info
        // self.animatedTileRenderer.drawDebugInfo = YES;
        self.animatedTileRenderer.alpha = .75;
        return self.animatedTileRenderer;
	}
	return nil;
}

获取图块并开始动画

[self.overlay fetchTilesForMapRect:self.mapView.visibleMapRect zoomLevel:self.animatedTileRenderer.renderedTileZoomLevel progressHandler:^(NSUInteger currentTimeIndex) {
    // Show loading progress
	[self.downloadProgressView setProgress:(CGFloat)currentTimeIndex / self.animatedTileOverlay.numberOfAnimationFrames animated:YES];
} completionHandler:^(BOOL success, NSError *error) {
	if (success) {
		[self.animatedTileOverlay startAnimating];
        return;
	}
}];

渲染动画

// When the overlay has started animating, it calls this delegate method when each frame of animation ticks.
// It is its responsibility to tell the overlay renderer to redraw for each frame.
- (void)animationTileOverlay:(TCCAnimationTileOverlay *)animationTileOverlay didAnimateWithAnimationFrameIndex:(NSInteger)animationFrameIndex
{
	[self.animatedTileRenderer setNeedsDisplayInMapRect:self.mapView.visibleMapRect];
	...    
}

停止动画

[self.overlay pauseAnimating];

动画帧间擦除

// This action is connected to the "Value Changed" event for the playback slider
- (IBAction)onSliderValueChange:(id)sender
{
    // Only advance the animated overlay to the next frame if the slider no longer matches the current frame index
	NSInteger sliderVal = floor(self.timeSlider.value);
    if (sliderVal == self.animatedTileOverlay.currentFrameIndex) return;
    [self.animatedTileOverlay moveToFrameIndex:frameIndex isContinuouslyMoving:YES];
}

// This action is connected to "Touch Up Inside" and "Touch Up Outside" for the playback slider
- (IBAction)finishedSliding:(id)sender
{
    NSInteger sliderVal = floor(self.timeSlider.value);
    [self.animatedTileOverlay moveToFrameIndex:frameIndex isContinuouslyMoving:NO];
}

地图上对用户输入做出反应

- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
{
    // When the user moves/zooms/rotates the map, it should pause loading or animating, since
    // otherwise we might not have fetched the tile data necessary to display the overlay
    // for the new region.
    if (self.animatedTileOverlay.currentAnimationState == TCCAnimationStateAnimating ||
        self.animatedTileOverlay.currentAnimationState == TCCAnimationStateLoading) {
        [self.animatedTileOverlay pauseAnimating];
    }
}

查看演示项目 MapTileAnimationDemo,以深入了解如何在项目中整合 TCCMapTileAnimation。

技术细节

  1. 它依赖于缓存的HTTP网络响应(来自NSURLCache)来在动画期间提供良好的性能。