【问题标题】:Multiple UIViews pixelated when zooming缩放时多个 UIView 像素化
【发布时间】:2014-02-17 09:05:22
【问题描述】:

我有两个 UIView(BlueView 和 RedView),它们绘制了一个 UIBeizerPath(它必须是 uibeizarpath)。

我的 MainView 初始化两个视图并控制缩放功能。

我可以让视图缩放,但是,当它们缩放时 UIBeizerPaths 像素化。我尝试过使用[viewname].layer.contentsScale = [[UIScreen mainScreen] scale] * currentScale;,但这不起作用。

任何帮助将不胜感激!

通过 Photoshop 的魔力,这里有一些我正在尝试完成的插图。

视图未缩放的样子:

我的放大结果:

缩放时想要的结果:

有什么建议吗?将不胜感激。这是我的代码:

MainView.h

#import <UIKit/UIKit.h>
#import “RedLine.h”
#import “BlueLine.h

@interface MainView : UIViewController {
    CGRect screenRect;

    //ZOOM
    CGFloat zoomScale;
    CGFloat _previousScale;
    CGPoint _originalCenter; 

RedLine * redLine;
BlueLine * blueLine;
}
@end

MainView.m

#import "MainView.h"
#import "BlueLine.h"
#import "RedLine.h"

// ZOOM SCALE
#define MAX_SCALE 4.0
#define MIN_SCALE 1.0


@interface MainView ()

@end

@implementation MainView

- (void)viewDidLoad
{
    [super viewDidLoad];
    screenRect = [[UIScreen mainScreen] bounds];

    zoomScale = 1.0;


    //Draw the lines
    blueLine = [[BlueLine alloc] initWithFrame:self.view.frame];
    [self.view addSubview:blueLine];

    redLine = [[RedLine alloc] initWithFrame:self.view.frame];
    [self.view addSubview:redLine];



    UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(zoomTool:)];
    [self.view addGestureRecognizer:pinchGesture];

}

#pragma mark - ZOOM 

//ZOOM VIEW
- (void) zoomTool:(UIPinchGestureRecognizer *)recognizer
{
    NSLog(@"Pinch scale: %f", recognizer.scale);
    if ([recognizer state] == UIGestureRecognizerStateBegan) {
        _previousScale = zoomScale;
    }

    CGFloat currentScale = MAX(MIN([recognizer scale] * zoomScale, MAX_SCALE), MIN_SCALE);
    CGFloat scaleStep = currentScale / _previousScale;
    [redLine setTransform: CGAffineTransformScale(redLine.transform, scaleStep, scaleStep)];
    redLine.layer.contentsScale = [[UIScreen mainScreen] scale] * currentScale;
    [blueLine setTransform: CGAffineTransformScale(blueLine.transform, scaleStep, scaleStep)];
    blueLine.layer.contentsScale = [[UIScreen mainScreen] scale] * currentScale;

    _previousScale = currentScale;

    if ([recognizer state] == UIGestureRecognizerStateEnded ||
        [recognizer state] == UIGestureRecognizerStateCancelled ||
        [recognizer state] == UIGestureRecognizerStateFailed) {
        // Gesture can fail (or cancelled?) when the notification and the object is dragged simultaneously
        zoomScale = currentScale;
    }


}
@end

BlueLine.m

#import "BlueLine.h"

@implementation BlueLine

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}

- (void)drawRect:(CGRect)rect {
    UIBezierPath *thisLine = [UIBezierPath bezierPath];

    [thisLine moveToPoint:CGPointMake(100, 100)];
    [thisLine addLineToPoint:CGPointMake(250, 250)];
    thisLine.lineWidth = 10;
    [[UIColor blueColor] setStroke];
    [thisLine stroke];

}
@end

RedLine.m

#import "RedLine.h"

@implementation RedLine

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}

- (void)drawRect:(CGRect)rect {
    UIBezierPath *thisLine = [UIBezierPath bezierPath];

    [thisLine moveToPoint:CGPointMake(300, 300)];
    [thisLine addLineToPoint:CGPointMake(100, 450)];
    thisLine.lineWidth = 10;
    [[UIColor redColor] setStroke];
    [thisLine stroke];

}
@end

【问题讨论】:

    标签: ios objective-c uiview uibezierpath uipinchgesturerecognizer


    【解决方案1】:

    Transform 只会拉伸视图,因此它会被像素化,而不是按照以下过程。

    当发生缩放时,调用视图的 setNeedsLayout 方法。并将 lineWidth 增加比例乘以原始宽度。它将完美绘制。

    在您的视图中添加一个新的公共属性。在缺少的行下方。

    @property CGFloat zoomScale;
    
    -(void)viewDidLoad{
     zoomScale=1.0;
    }
    
    -(void)drawRect{
        thisLine.lineWidth = 10*zoomScale;
    }
    

    所以每当缩放发生时,

    blueView.zoomScale =zoomScale;
    [blueView setNeedsDisplay];
    

    完整代码(用于红线)

    - (void) zoomTool:(UIPinchGestureRecognizer *)recognizer
    {
        NSLog(@"Pinch scale: %f", recognizer.scale);
        if ([recognizer state] == UIGestureRecognizerStateBegan) {
            _previousScale = zoomScale;
        }
    
        CGFloat currentScale = MAX(MIN([recognizer scale] * zoomScale, MAX_SCALE), MIN_SCALE);
        redLine.scale=currentScale;
        [redLine setNeedsDisplay];
        _previousScale = currentScale;
    
        if ([recognizer state] == UIGestureRecognizerStateEnded ||
            [recognizer state] == UIGestureRecognizerStateCancelled ||
            [recognizer state] == UIGestureRecognizerStateFailed) {
            // Gesture can fail (or cancelled?) when the notification and the object is dragged simultaneously
            zoomScale = currentScale;
        }
    }
    

    RedLine.h

    #import <UIKit/UIKit.h>
    
    @interface RedLine : UIView
    @property CGFloat scale;
    @end
    

    RedLine.m

    #import "RedLine.h"
    
    @implementation RedLine
    @synthesize scale =scale;
    - (id)initWithFrame:(CGRect)frame {
        self = [super initWithFrame:frame];
        if (self) {
            // Initialization code
            scale=1.0f;
        }
        return self;
    }
    
    - (void)drawRect:(CGRect)rect {
    
    
        [self setBackgroundColor:[UIColor clearColor]];
    
        CGPoint p1 =CGPointMake(50, 50);
        CGPoint p2 =CGPointMake(300, 300);
    
        CGFloat offsetX =self.center.x *(scale-1);
        CGFloat offsetY =self.center.y *(scale-1);
    
        p1.x =p1.x*scale -offsetX;
        p1.y =p1.y*scale -offsetY;
    
        p2.x =p2.x*scale -offsetX;
        p2.y =p2.y*scale -offsetY;
    
    
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
        CGContextSetLineWidth(context, 10*scale);
    
        CGContextMoveToPoint(context, p1.x, p1.y);
        CGContextAddLineToPoint(context, p2.x, p2.y);
    
        CGContextStrokePath(context);
    
    }
    @end
    

    【讨论】:

    • 我尝试了你的建议。然而,虽然线条的大小会按比例缩放,但它们仍然是像素化的。
    • 您还在应用转换吗?现在不要应用转换
    • 不应用transfrom,只是在调整line.s大小时保持UIView的大小相同
    • 基于zoomScale,只需平移(移动)这些视图,drawRect就会画出更大的线条,完全提供缩放无像素效果。
    • 我不确定你希望我如何实现它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-12
    • 1970-01-01
    • 2011-11-18
    • 1970-01-01
    • 2011-07-18
    相关资源
    最近更新 更多