草庐IT

ios - 在可缩放 View 上绘图

coder 2023-09-22 原文

我正在开发一个小型绘图应用程序,它具有支持放大/缩小的基本要求。我有两个主要问题:

  1. 当 View 缩放/变换时,绘图显得不清晰。有没有更好的方法,或者有没有办法在 View 缩放时改进绘图?

  2. 在 1200 x 1200 pts Canvas 上(在 iPhone 上)绘图时,绘图性能很慢。我有机会针对大 Canvas 尺寸改进它吗?

缩放代码:

- (void)scale:(UIPinchGestureRecognizer *)gestureRecognizer {
    [self adjustAnchorPointForGestureRecognizer:gestureRecognizer];

    UIView *canvas = [gestureRecognizer view];

    if ([gestureRecognizer state] == UIGestureRecognizerStateBegan ||
        [gestureRecognizer state] == UIGestureRecognizerStateChanged) {

        // Calculate the drawing view's size
        CGSize drawingViewSize = ...;

        // Calculate the minimum allowed tranform size
        // Developer's Note: I actually wanted to use the size 1/4th of the view
        // but self.view.frame.size doesn't return the correct (actual) width and height
        // It returns these values inverted i.e. width as height, and vice verse.
        // The reason is that the view appears to be transformed (90 degrees).
        // Since there's no work-around this, so for now, I'm just using fixed values.
        CGSize minTranformSize = CGSizeMake(100.0f, 100.0f);

        if ((minTranformSize.width > drawingViewSize.width) && (minTranformSize.height > drawingViewSize.height)) {
            minTranformSize = drawingViewSize;
        }

        // Transform the view, provided
        // 1. It won't scale more than the original size of the background image
        // 2. It won't scale less than the minimum possible transform
        CGSize transformedSize = CGSizeMake(canvas.frame.size.width * [gestureRecognizer scale],
                                            canvas.frame.size.height * [gestureRecognizer scale]);

        if ((transformedSize.width <= drawingViewSize.width) && (transformedSize.height <= drawingViewSize.height) &&
            (transformedSize.width >= minTranformSize.width) && (transformedSize.height >= minTranformSize.height)) {

            canvas.transform = CGAffineTransformScale([canvas transform],
                                                      [gestureRecognizer scale],
                                                      [gestureRecognizer scale]);
        }

        [gestureRecognizer setScale:1.0];

    } else if ([gestureRecognizer state] == UIGestureRecognizerStateEnded) {

        // Recenter the container view, if required (piece is smaller than the view and it's not aligned)
        CGSize viewSize = self.view.bounds.size;

        if ((canvas.frame.size.width < viewSize.width) ||
            (canvas.frame.size.height < viewSize.height)) {

            canvas.center = CGPointMake(viewSize.width/2, viewSize.height/2);
        }

        // Adjust the x/y coordinates, if required (piece is larger than the view and it's moving outwards from the view)
        if (((canvas.frame.origin.x > 0) || (canvas.frame.origin.y > 0)) &&
            ((canvas.frame.size.width >= viewSize.width) && (canvas.frame.size.height >= viewSize.height))) {

            canvas.frame = CGRectMake(0.0,
                                      0.0,
                                      canvas.frame.size.width,
                                      canvas.frame.size.height);
        }

        canvas.frame = CGRectIntegral(canvas.frame);
    }
}

绘图代码

- (void)draw {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);

    if (self.fillColor) {
        [self.fillColor setFill];
        [self.path fill];
    }

    if ([self.strokeColor isEqual:[UIColor clearColor]]) {
        [self.path strokeWithBlendMode:kCGBlendModeClear alpha:1.0];

    } else if (self.strokeColor) {
        [self.strokeColor setStroke];
        [self.path stroke];
    }

    CGContextRestoreGState(context);
}

最佳答案

这是一个相当复杂的问题,我一直在努力解决。

我最终将绘图转换为矢量。

  1. 在一层中绘制所有线条,在另一层中绘制所有填充。
  2. 使用 potrace ( http://potrace.sourceforge.net/ ) 将线条图转换为 Vector
  3. 使用 SVGKit 绘制矢量 ( https://github.com/SVGKit/SVGKit ) 并隐藏 1) 中绘制的层

它运行良好且速度相当快,但需要大量工作。我们公司有一个应用程序应用了这种技术:

https://itunes.apple.com/us/app/ideal-paint-hd-mormor/id569450492?mt=8 .

如果您唯一的问题是性能,请尝试查看 CATiledLayer。 (也用在上面提到的应用程序中)。它将极大地提高性能(您可以在此处找到非常好的教程 http://www.cimgf.com/2011/03/01/subduing-catiledlayer/ )。

祝你好运! :)

关于ios - 在可缩放 View 上绘图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18181707/

有关ios - 在可缩放 View 上绘图的更多相关文章

  1. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  2. ruby-on-rails - 渲染另一个 Controller 的 View - 2

    我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

  3. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  4. ruby-on-rails - 如何在 Rails View 上显示错误消息? - 2

    我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c

  5. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  6. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  7. ruby-on-rails - 复数 for fields_for has_many 关联未显示在 View 中 - 2

    目前,Itembelongs_toCompany和has_manyItemVariants。我正在尝试使用嵌套的fields_for通过Item表单添加ItemVariant字段,但是使用:item_variants不显示该表单。只有当我使用单数时才会显示。我检查了我的关联,它们似乎是正确的,这可能与嵌套在公司下的项目有关,还是我遗漏了其他东西?提前致谢。注意:下面的代码片段中省略了不相关的代码。编辑:不知道这是否相关,但我正在使用CanCan进行身份验证。routes.rbresources:companiesdoresources:itemsenditem.rbclassItemi

  8. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  9. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  10. ruby-on-rails - 在 haml View 中重构条件 - 2

    除了可访问性标准不鼓励使用这一事实指向当前页面的链接,我应该怎么做重构以下View代码?#navigation%ul.tabbed-ifcurrent_page?(new_profile_path)%li{:class=>"current_page_item"}=link_tot("new_profile"),new_profile_path-else%li=link_tot("new_profile"),new_profile_path-ifcurrent_page?(profiles_path)%li{:class=>"current_page_item"}=link_tot("p

随机推荐