【问题标题】:Zoom with a drawing view使用图纸视图缩放
【发布时间】:2012-08-23 01:42:15
【问题描述】:
我正在寻找一种解决方案,以便在绘图视图上进行漂亮的缩放。
在我的应用程序中,我有一个带有其他 UIView 的视图(用作绘图视图),当我在其上绘制笔画时,笔画是完美的。但是当我放大视图时,我有一个非常丑陋的效果(像素化笔画):
(来源:imagup.com)
url image
是否有解决方案才能获得正确的笔画?
我的 UIViewController 有这样的层次结构:
- UIViewController
- 滚动视图
- 可缩放视图(使用 viewForZoomingInScrollView 方法定义)
非常感谢!
问候,
塞巴斯蒂安 ;)
【问题讨论】:
标签:
objective-c
ios
uiview
zooming
drawrect
【解决方案1】:
我正在制作矢量绘图应用程序,让我告诉你,要正确完成这不是一项简单的任务,需要大量工作。
需要注意的一些问题:
- 如果您不使用矢量图形(例如,CGPaths
矢量)您将无法消除像素化。一个 UIImage,
例如,只有这么多分辨率。
- 为了让您的绘图看起来不像素化,您将
必须重绘一切。如果你有很多绘图,这可以是
执行一项昂贵的任务。
- 几乎不可能在缩放时获得良好的分辨率,因为它需要非常大的上下文,并且您的绘图可能会超出设备的功能
我使用核心图形进行绘图,因此我解决此问题的方法是分配和管理多个 CGContext 并将它们用作缓冲区。我有一个上下文始终保持在我的最小缩放级别(比例因子为 1)。该上下文始终被引入并使其在完全取消缩放时不会花费时间重新绘制,因为它已经完成了。缩放时单独使用另一个上下文进行绘图。未缩放时,该上下文将被忽略(因为无论如何都必须根据新的缩放级别重新绘制它)。我如何执行缩放的高级算法如下:
- (IBAction)handlePinchGesture:(UIGestureRecognizer *)sender
{
if(sender.state == UIGestureRecognizerStateBegan)
{
//draw an image from the unzoomedContext into my current view
//set the scale transformation of my current view to be equal to "currentZoom", a property of the view that keeps track of the actual zoom level
}
else if(sender.state == UIGestureRecognizerStateChanged)
{
//determine the new zoom level and transform the current view, keeping track in the currentZoom property
//zooming will be pixelated.
}
else if(sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateCancelled)
{
if(currentZoom == 1.0)
{
//you are done because the unzoomedContext image is already drawn into the view!
}
else
{
//you are zoomed in and will have to do special drawing
//perform drawing into your zoomedContext
//scale the zoomedContext
//set the scale of your current view to be equal to 1.0
//draw the zoomedContext into the current view. It will not be pixelated!
//any drawing done while zoomed needs to be "scaled" based on your current zoom and translation amounts and drawn into both contexts
}
}
}
这对我来说变得更加复杂,因为我有额外的缓冲区用于缓冲区,因为绘制路径的图像比绘制大量路径时要快得多。
在管理多个上下文、调整代码以有效地绘制到多个上下文、遵循适当的 OOD、根据当前缩放和平移缩放新绘图等之间,这是一项艰巨的任务。希望这可以激励您并让您走上正确的道路,或者您认为摆脱这种像素化并不值得:)
【解决方案2】:
我遇到了同样的问题并找到了解决方案:告诉视图使用CATiledLayer 作为支持层,然后告诉视图它支持多少级别的缩放。这对我有用,当(父)视图缩放时,我的绘图方法会自动调用。
levelsOfDetail和levelsOfDetailBias的简单解释:
-
levelsOfDetail 确定总共有多少缩放级别
-
levelsOfDetailBias 确定其中有多少正在放大。
所以在我的示例中,我有 4 个缩放级别,3 个被放大,1 个是非缩放级别,这意味着我的视图仅在放大时重绘。
@imprementation MyZoomableView
+ (Class)layerClass
{
return [CATiledLayer class];
}
- (id)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame])) {
((CATiledLayer *)self.layer).levelsOfDetail = 4;
((CATiledLayer *)self.layer).levelsOfDetailBias = 3;
}
return self;
}
@end
【解决方案3】:
在您的 scrollViewDidEndZooming: 委托方法中使用 [self setContentScaleFactor:scale];。