水平缩放的 UIScrollView - 在子视图中绘制的贝塞尔曲线路径模糊
UIScrollView with Horizontal Zoom - Bezier Paths Drawn within Subviews Are Blurry
我有一个滚动视图,它只能在捏合时水平缩放(基于 )
内容视图有几个水平均匀分布且放置在不同高度的子视图。基本上,我正在绘制一个带点的图表。
每个标记都是一个自定义的 UIView 子类,它有一个标签作为子视图,并在 drawRect(_:)
内绘制一个红色圆圈。
(滚动视图及其唯一的子内容视图使用自动布局,但内容视图的所有子视图都放置在运行时计算的框架中;除了相对于标记的标签定位外没有其他限制)
我已经修改了上面链接的答案,因此 - 在缩放时 - 点的水平间距更大,但保持相同的大小。
这是我的内容视图的部分代码:
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()
}
}
...但是,由于仅在水平方向拉伸(对角线)线段,我仍然遇到线宽不均匀的问题。
我最初的想法是将图形存储为贝塞尔曲线路径而不是一组视图线和点视图,并基于单个单位轴。您可以将您的数据转换成这种形式只是为了绘图。
因此,贝塞尔曲线路径上的所有点都归一化到 0 到 1 的范围内。
完成后,您可以对贝塞尔曲线路径应用变换以平移(移动)和缩放(缩放)到您想要的部分,然后以全分辨率绘制贝塞尔曲线路径。
这将起作用并且与您当前的情况不同,因为您当前的代码绘制视图然后缩放然后您得到工件。上面的选项缩放路径然后绘制它。
我有一个滚动视图,它只能在捏合时水平缩放(基于
内容视图有几个水平均匀分布且放置在不同高度的子视图。基本上,我正在绘制一个带点的图表。
每个标记都是一个自定义的 UIView 子类,它有一个标签作为子视图,并在 drawRect(_:)
内绘制一个红色圆圈。
(滚动视图及其唯一的子内容视图使用自动布局,但内容视图的所有子视图都放置在运行时计算的框架中;除了相对于标记的标签定位外没有其他限制)
我已经修改了上面链接的答案,因此 - 在缩放时 - 点的水平间距更大,但保持相同的大小。
这是我的内容视图的部分代码:
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()
}
}
...但是,由于仅在水平方向拉伸(对角线)线段,我仍然遇到线宽不均匀的问题。
我最初的想法是将图形存储为贝塞尔曲线路径而不是一组视图线和点视图,并基于单个单位轴。您可以将您的数据转换成这种形式只是为了绘图。
因此,贝塞尔曲线路径上的所有点都归一化到 0 到 1 的范围内。
完成后,您可以对贝塞尔曲线路径应用变换以平移(移动)和缩放(缩放)到您想要的部分,然后以全分辨率绘制贝塞尔曲线路径。
这将起作用并且与您当前的情况不同,因为您当前的代码绘制视图然后缩放然后您得到工件。上面的选项缩放路径然后绘制它。