在swift中将CAShapelayer转换为特定大小

时间:2015-05-25 09:01:02

标签: ios swift animation cashapelayer

我正在尝试制作一个带有bezier路径的CAShapeLayer,并以视图展开(当然是动画的)。我知道我可以用CATransform3DMakeScale(,,)改变路径的大小但是这不允许我使路径成为精确的大小(以点为单位)。

有人知道怎么做吗?

1 个答案:

答案 0 :(得分:12)

你会用优秀的老式数学来做到这一点。

简单解决方案

用不同的方式表达你的问题:你有一个大小的东西(路径/形状层),你想要缩放它,使它变成另一个大小。

要知道您想要沿X和Y(单独)缩放多少,您可以将当前尺寸除以您想要适合的尺寸。您可以使用

获取路径的边界框
let boundingBox = CGPathGetBoundingBox(path)

我假设你已经有一些你想要缩放它的大小(这里我称之为我的containingSize)。

使用这两个,你可以通过将你缩放的尺寸除以你要缩放的尺寸来计算两个比例因子

let xScaleFactor = containingSize.width  / boundingBox.width
let yScaleFactor = containingSize.height / boundingBox.height

使用这些,您可以创建所需的比例变换

let scaleTransform = CATransform3DMakeMakeScale(xScaleFactor, yScaleFactor, 1.0)

缩放此形状图层

Unscaled image

使用这两个比例因子,将缩放形状图层以填充容器大小。如果容器大小与路径具有相同的宽高比,则所有内容都将按预期显示。如果没有,缩放图层将显示拉伸。

enter image description here

拟合而不是填充

这个问题(除非你想要的)可以通过计算统一的比例因子来解决,这是两者中较小的一个,因此缩放的路径适合容器而不是填充容器。

我们通过找出哪个比例因子是最受限制的因子,然后将其应用于X和Y来实现这一目的

let boundingBoxAspectRatio = boundingBox.width/boundingBox.height
let viewAspectRatio = containingSize.width/containingSize.height

let scaleFactor: CGFloat
if (boundingBoxAspectRatio > viewAspectRatio) {
    // Width is limiting factor
    scaleFactor = containingSize.width/boundingBox.width
} else {
    // Height is limiting factor
    scaleFactor = containingSize.height/boundingBox.height
}

let scaleTransform = CATransform3DMakeMakeScale(scaleFactor, scaleFactor, 1.0)

这将缩放路径而不改变其宽高比

enter image description here

缩放图层或缩放路径?

您可能还注意到,在缩放形状图层时,线宽也会缩放,就像它是图像一样。缩放图层和缩放路径之间存在差异。

如果您只想在缩放形状图层的路径时显示它,那么您应该缩放路径而不是图层。您可以通过创建转换的新路径,并在形状图层中使用 路径来完成此操作。请注意,仍然使用未缩放路径的边界框计算比例因子。

var affineTransform = CGAffineTransformMakeScale(scaleFactor, scaleFactor)
let transformedPath = CGPathCreateCopyByTransformingPath(path, &affineTransform)
yourShapeLayer.path = transformedPath

这将扩大路径,而不会影响形状图层的线宽等。

enter image description here