具有水平缩放的 UIScrollView - 在子视图中绘制的贝塞尔路径模糊

Posted

技术标签:

【中文标题】具有水平缩放的 UIScrollView - 在子视图中绘制的贝塞尔路径模糊【英文标题】:UIScrollView with Horizontal Zoom - Bezier Paths Drawn within Subviews Are Blurry 【发布时间】:2016-06-09 06:33:08 【问题描述】:

我有一个滚动视图,只能在捏合时水平缩放(基于this answer)

内容视图有几个水平均匀分布的子视图,并放置在不同的高度。基本上,我正在绘制一个带点的图表。

每个标记都是一个自定义 UIView 子类,其标签为子视图,并在 drawRect(_:) 内绘制一个红色圆圈。

(滚动视图及其唯一的子视图内容视图使用 Autolayout,但内容视图的所有子视图都放置在运行时计算的框架;除了相对于标记的标签定位之外没有约束)

我已经修改了上面链接的答案,因此 - 当缩放时 - 点的水平间距更大,但保持相同的大小

这是我的内容视图代码的一部分:

override var transform: CGAffineTransform 
    
    get 
        return super.transform
    
    
    set 
        if let unzoomedViewHeight = unzoomedViewHeight 
            // ^Initial height of the content view, captured
            // on layoutSubviews() and used to calculate a
            // a zoom transform that preserves the height  
            // (see linked answer for details)

            // 1. Ignore vertical zooming for this view:
            
            var modified = newValue
            modified.d = 1.0
            modified.ty = (1.0 - modified.a) * unzoomedViewHeight/2
            super.transform = modified
            
            
            // 2. Ignore zooming altogether in marker subviews:
            
            var markerTransform = CGAffineTransformInvert(newValue)
            markerTransform.d = 1.0 // No y-scale
            
            for subview in subviews where subview is MarkerView 
                subview.transform = markerTransform
            
        
    

接下来,我想用直线段连接我的点。问题是,当我缩放滚动视图时,片段变得模糊。

除了模糊之外,因为我只是水平缩放,所以线段会“剪切”一点(取决于它们的斜率),因此线宽度变得不均匀:

(现在我在每对点之间放置一个中间视图,绘制一个段 - 但结果与单个路径相同)

我尝试让分段绘图视图了解其父级应用到它们的变换,还原它,并相应地修改它们的框架(并在新边界内重绘路径);但是它似乎不起作用。

在滚动视图中绘制抗缩放贝塞尔路径的最佳方法是什么?


更新:

我通过关注this answer 来解决类似问题(几乎重复?);在我的情况下,代码转换为:

func scrollViewDidEndZooming(scrollView: UIScrollView, withView view: UIView?, atScale scale: CGFloat)

    for segment in contentView.subviews where segment is SegmentView 
        
        segment.layer.contentsScale = scale
        segment.setNeedsDisplay()
    

...但是,由于仅在水平方向上拉伸(对角线)线段,我仍然遇到线宽不均匀的问题。

【问题讨论】:

【参考方案1】:

我最初的想法是,将图形存储为贝塞尔路径,而不是一组视图线和点视图,并基于单个单位轴。您可以将您的数据转换成这种形式,只是为了绘图。

因此,贝塞尔路径上的所有点都归一化到 0 到 1 的范围内。

完成后,您可以对贝塞尔路径应用变换以平移(移动)和缩放(缩放)到您想要的部分,然后以全分辨率绘制贝塞尔路径。

这将起作用,并且与您当前的情况不同,因为您当前的代码会绘制视图然后进行缩放,以便您获得工件。上面的选项缩放路径然后绘制它。

【讨论】:

哪个视图绘制路径?我需要它与滚动视图一起滚动和缩放。我也有每个标记的标签... 我认为每个段由一个独立的子视图管理可能产生的一个优点是,我可以使它重绘可见段。也许我在这方面有一个误解,虽然...... "上面的选项缩放路径然后绘制它。" - 所以基本上,我应该从不缩放(缩放)但始终保持相同比例的视图中绘制(转换后的)路径,而是使用滚动视图的缩放比例和内容偏移来转换贝塞尔路径?跨度> 您可以重绘视图,您需要将缩放比例传递给它们,而不是对它们使用变换。我的解决方案将涉及使用滚动视图偏移和缩放来修改路径,是的。路径甚至不需要是滚动视图的子视图,滚动视图可能只是用于输入处理...... 我会考虑一下,看看我是否可以在当前设置中以最小的痛苦做到这一点。谢谢你的建议。

以上是关于具有水平缩放的 UIScrollView - 在子视图中绘制的贝塞尔路径模糊的主要内容,如果未能解决你的问题,请参考以下文章

在 UIScrollView 中仅水平缩放 UIView

在子视图上具有最大 y 位置的垂直 UIScrollView

具有多个缩放级别的 UIScrollView?

缩放 UIScrollView 不起作用

图像缩放时在 UIScrollView 中停止滚动图像

UIScrollView,滑动,缩放