加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

objective-c – OS X上的CATiledLayers

发布时间:2020-12-16 05:06:31 所属栏目:百科 来源:网络整理
导读:这让我很疯狂.我有一个大图像,需要有一个可缩放和可滚动的视图(理想情况下它也应该能够旋转,但我放弃了那部分).由于图像非常大,我打算使用CATiledLayer,但我根本无法让它工作. 我的要求是: 我需要能够缩放(在鼠标中心)和平移 图像不应改变其宽度:高度比(不
这让我很疯狂.我有一个大图像,需要有一个可缩放和可滚动的视图(理想情况下它也应该能够旋转,但我放弃了那部分).由于图像非常大,我打算使用CATiledLayer,但我根本无法让它工作.
我的要求是:

>我需要能够缩放(在鼠标中心)和平移
>图像不应改变其宽度:高度比(不应调整大小,仅缩放).
>这应该在Mac OS 10.9上运行(不是iOS!)
>内存使用量不应该很大(尽管最高可达100 MB).

我有必要的图像在一个文件中完成,并且还平铺成许多(甚至有不同的缩放级别).我更喜欢使用瓷砖,因为内存应该更容易,但两种选择都可用.

大多数在线示例都是指iOS,因此使用UIScrollView进行缩放/平移,但我无法复制NSScrollView的行为.我发现Mac OS X的唯一例子是this,但他的缩放始终是左下角,而不是中间,当我调整代码使用png文件而不是pdf时,内存使用大约400 MB …

到目前为止,这是我最好的尝试:

@implementation MyView{
    CATiledLayer *tiledLayer;
}
-(void)awakeFromNib{
    NSLog(@"Es geht los");
    tiledLayer = [CATiledLayer layer];

    // set up this view & its layer
    self.wantsLayer = YES;
    self.layer = [CALayer layer];
    self.layer.masksToBounds = YES;
    self.layer.backgroundColor = CGColorGetConstantColor(kCGColorWhite);

    // set up the tiled layer
    tiledLayer.delegate = self;
    tiledLayer.levelsOfDetail = 4;
    tiledLayer.levelsOfDetailBias = 5;
    tiledLayer.anchorPoint = CGPointZero;
    tiledLayer.bounds = CGRectMake(0.0f,0.0f,41*256,22*256);
    tiledLayer.autoresizingMask = kCALayerNotSizable;
    tiledLayer.tileSize = CGSizeMake(256,256);
    self.frame = CGRectMake(0.0f,22*256);
    self.layer = tiledLayer;
    //[self.layer addSublayer:tiledLayer];
    [tiledLayer setNeedsDisplay];

}

-(void)drawRect:(NSRect)dirtyRect{
    CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];


    CGFloat scale = CGContextGetCTM(context).a;

    CGSize tileSize = tiledLayer.tileSize;


    tileSize.width /= scale;
    tileSize.height /= scale;

    // calculate the rows and columns of tiles that intersect the rect we have been asked to draw
    int firstCol = floorf(CGRectGetMinX(dirtyRect) / tileSize.width);
    int lastCol = floorf((CGRectGetMaxX(dirtyRect)-1) / tileSize.width);
    int firstRow = floorf(CGRectGetMinY(dirtyRect) / tileSize.height);
    int lastRow = floorf((CGRectGetMaxY(dirtyRect)-1) / tileSize.height);

    for (int row = firstRow; row <= lastRow; row++) {
        for (int col = firstCol; col <= lastCol; col++) {
            NSImage *tile = [self tileForScale:scale row:row col:col];
            CGRect tileRect = CGRectMake(tileSize.width * col,tileSize.height * row,tileSize.width,tileSize.height);

            // if the tile would stick outside of our bounds,we need to truncate it so as
            // to avoid stretching out the partial tiles at the right and bottom edges
            tileRect = CGRectIntersection(self.bounds,tileRect);

            [tile drawInRect:tileRect];
        }
    }
}

-(BOOL)isFlipped{
    return YES;
}

但这会使图像变形,并且不能正确缩放或平移(但至少瓷砖选择有效)……

我不敢相信这很难,任何帮助都会非常感激.谢谢 :)

解决方法

经过大量的研究和尝试,我终于设法使用 this示例来实现这一点.决定发布以供将来参考.打开ZIP> CoreAnimationLayers> TiledLayers,那里有一个很好的例子.那就是CATiledLayer如何与OS X一起工作,并且因为那个例子没有很好地处理缩放,我在这里留下我的缩放代码
-(void)magnifyWithEvent:(NSEvent *)event{
    [super magnifyWithEvent:event];

    if (!isZooming) {
        isZooming = YES;

        BOOL zoomOut = (event.magnification > 0) ? NO : YES;

        if (zoomOut) {
            [self zoomOutFromPoint:event.locationInWindow];

        } else {
            [self zoomInFromPoint:event.locationInWindow];;
        }

    }

}

-(void)zoomInFromPoint:(CGPoint)mouseLocationInWindow{
    if(zoomLevel < pow(2,tiledLayer.levelsOfDetailBias)) {
        zoomLevel *= 2.0f;

        tiledLayer.transform = CATransform3DMakeScale(zoomLevel,zoomLevel,1.0f);
        tiledLayer.position = CGPointMake((tiledLayer.position.x*2) - mouseLocationInWindow.x,(tiledLayer.position.y*2) - mouseLocationInWindow.y);

    }

}

-(void)zoomOutFromPoint:(CGPoint)mouseLocationInWindow{
    NSInteger power = tiledLayer.levelsOfDetail - tiledLayer.levelsOfDetailBias;
    if(zoomLevel > pow(2,-power)) {
        zoomLevel *= 0.5f;

        tiledLayer.transform = CATransform3DMakeScale(zoomLevel,1.0f);
        tiledLayer.position = CGPointMake((tiledLayer.position.x + mouseLocationInWindow.x)/2,(tiledLayer.position.y + mouseLocationInWindow.y)/2);

    }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读