使用CATiledLayer的drawLayer:inContext:

发布于 2024-10-15 03:06:16 字数 335 浏览 11 评论 0原文

我正在尝试使用 CATiledLayer + UIScrollView 来实现我自己的地图引擎。

在我的实现的 drawLayer:inContext: 方法中,如果我有当前边界框所需的某个图块图像,我会立即在上下文中绘制它。

但是,当我在本地缓存数据结构中没有可用的数据时,图块图像将从图块服务器异步请求/下载,并且不会在上下文中绘制任何内容。

问题是,当我不在上下文中绘制任何内容时,视图的该部分显示为空白图块。预期的行为是显示先前缩放级别的放大平铺视图。

如果你们遇到过类似的问题并找到了解决方案,请告诉我。

I am trying to implement my own map engine by using CATiledLayer + UIScrollView.

In drawLayer:inContext: method of my implementation, if I have a certain tile image needed for the current bounding box, I immediately draw it in the context.

However, when I do not have one available in the local cache data structure, the tile image is asynchronously requested/downloaded from a tile server, and not draw anything in the context.

The problem is, when I don't draw anything in the context, that part of the view is shown as a blank tile. And the expected behavior is to show the zoom-in scaled tile view from the previous zoom level.

If you guys have faced any similar problem and found any solution for this, please let me know.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

可是我不能没有你 2024-10-22 03:06:16

一旦获得数据,您就必须为图块设置 setNeedsDisplayInRect: 。在图块可用之前,您必须忍受它是空白的,因为您无法影响 CATiledLayer 正在创建哪些图块。

You have to setNeedsDisplayInRect: for the tile as soon as you have the data. You have to live with it being blank until the tile is available because you have no way to affect which tiles CATiledLayer is creating.

三生路 2024-10-22 03:06:16

我也做了同样的事情,阻塞线程直到图块下载完成。性能不错,运行流畅。我使用队列来存储每个图块请求,因此我还可以取消那些不再有用的图块请求。

为此,请在启动异步图块请求后立即使用锁来停止线程,并在缓存图块后立即将其解锁。

你听起来不错吗?这对我有用!

I do the same, blocking the thread until the tile has been downloaded. The performance is good, it runs smoothly. I'm using a queue to store every tile request, so I can also cancel those tile requests that are not useful anymore.

To do so, use a lock to stop the thread just after you launch your async tile request, and unlock it as soon as you have your tile cached.

Sounds that good to you? It worked for me!

北方。的韩爷 2024-10-22 03:06:16

您的 CATiledLayer 应该按照您的预期提供之前缩放级别的图块。平铺图层的 levelsOfDetaillevelsOfDetailBias 设置为多少?

Your CATiledLayer should be providing this tile from the previous zoom level as you expect. What are your levelsOfDetail and levelsOfDetailBias set to for the tiled layer?

月亮邮递员 2024-10-22 03:06:16

您必须调用 setNeedsDisplay 或 setNeedsDisplayInRect: 但问题是,如果您调用此方法,那么它将重绘滚动视图中的每个图块。因此,尝试使用 UIView 的子类而不是 CATiledLayer 子类,并像这样实现 TiledView (UIView 的子类),

+(类)layerClass {
    返回 [CATiledLayer 类];
}

-(void)drawRect:(CGRect)r {
    CGRect 平铺 = r;
    int x =tile.origin.x/TILESIZE;
    int y =tile.origin.y/TILESIZE;
    NSString *tileName = [NSString stringWithFormat:@"Shed_1000_%i_%i", x, y];
    NSString *路径 =
        [[NSBundle mainBundle] pathForResource:tileName ofType:@"png"];
    UIImage *image = [UIImage imageWithContentsOfFile:path];
    [图像drawAtPoint:tile.origin];
    // 取消注释以下内容以查看图块边界
    /*
    UIBezierPath* bp = [UIBezierPath bezierPathWithRect: r];
    [[UIColor 白色颜色] setStroke];
    [血压冲程];
    */
}

对于

滚动视图,

UIScrollView* sv = [[UIScrollView alloc] initWithFrame:
                    [[UIScreen mainScreen] applicationFrame]];
sv.backgroundColor = [UIColor whiteColor];
self.view = sv;
CGRect f = CGRectMake(0,0,3*TILESIZE,3*TILESIZE);
TiledView* content = [[TiledView alloc] initWithFrame:f];
float tsz = TILESIZE * content.layer.contentsScale;
[(CATiledLayer*)content.layer setTileSize: CGSizeMake(tsz, tsz)];
[self.view addSubview:content];
[sv setContentSize: f.size];

You have to call setNeedsDisplay or setNeedsDisplayInRect: But the problem is if you call this then it will redraw every tile in the scrollView. So try using subclass of UIView instead of CATiledLayer subclass, and implement TiledView (subclass of UIView) like this,

+ (Class) layerClass {
    return [CATiledLayer class];
}

-(void)drawRect:(CGRect)r {
    CGRect tile = r;
    int x = tile.origin.x/TILESIZE;
    int y = tile.origin.y/TILESIZE;
    NSString *tileName = [NSString stringWithFormat:@"Shed_1000_%i_%i", x, y];
    NSString *path =
        [[NSBundle mainBundle] pathForResource:tileName ofType:@"png"];
    UIImage *image = [UIImage imageWithContentsOfFile:path];
    [image drawAtPoint:tile.origin];
    // uncomment the following to see the tile boundaries
    /*
    UIBezierPath* bp = [UIBezierPath bezierPathWithRect: r];
    [[UIColor whiteColor] setStroke];
    [bp stroke];
    */
}

and

for scrollView,

UIScrollView* sv = [[UIScrollView alloc] initWithFrame:
                    [[UIScreen mainScreen] applicationFrame]];
sv.backgroundColor = [UIColor whiteColor];
self.view = sv;
CGRect f = CGRectMake(0,0,3*TILESIZE,3*TILESIZE);
TiledView* content = [[TiledView alloc] initWithFrame:f];
float tsz = TILESIZE * content.layer.contentsScale;
[(CATiledLayer*)content.layer setTileSize: CGSizeMake(tsz, tsz)];
[self.view addSubview:content];
[sv setContentSize: f.size];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文