Swift 应用于图层的CATTransferM3Drotate无效
你能告诉我为什么CATTransferM3Drotate不适用于我的情况下的图层,图片上的蓝色图层 我有自定义视图,在这里我画自然视图,我想动画改变月亮的相位,这将在白色圆圈层内完成,作为它的遮罩。我想在这里应用3DRotation是个好主意,但由于某些原因,即使没有动画,它也无法工作,请告诉我我做错了什么Swift 应用于图层的CATTransferM3Drotate无效,swift,calayer,catransform3d,Swift,Calayer,Catransform3d,你能告诉我为什么CATTransferM3Drotate不适用于我的情况下的图层,图片上的蓝色图层 我有自定义视图,在这里我画自然视图,我想动画改变月亮的相位,这将在白色圆圈层内完成,作为它的遮罩。我想在这里应用3DRotation是个好主意,但由于某些原因,即使没有动画,它也无法工作,请告诉我我做错了什么 func drawMoonPhase(inRect rect:CGRect, inContext context: CGContext) { let moonShape
func drawMoonPhase(inRect rect:CGRect, inContext context: CGContext) {
let moonShape = UIBezierPath(ovalIn: rect)
moonShape.lineWidth = 4.0
UIColor.white.setStroke()
moonShape.stroke()
moonShape.close()
let moonLayer = CAShapeLayer()
moonLayer.path = moonShape.cgPath
moonLayer.opacity = 0
self.layer.addSublayer(moonLayer)
let circlePath = UIBezierPath(ovalIn: rect)
UIColor.blue.setFill()
circlePath.fill()
circlePath.close()
let circleShape = CAShapeLayer()
circleShape.path = circlePath.cgPath
circleShape.opacity = 0
var transform = CATransform3DIdentity
transform.m34 = -1 / 500.0
transform = CATransform3DRotate(transform, (CGFloat(Double.pi * 0.3)), 0, 1, 0)
circleShape.transform = transform
moonLayer.mask = circleShape
}
提前谢谢
编辑:
也许我想要清楚,我想要的效果如下:
变换发生在层的锚定点周围,默认情况下,锚定点位于中心。因此,在那里发生的情况是形状围绕自身旋转,不会产生可见的结果。:) 在这个图层布局中,你应该使用cos和sin数学函数来确定月亮的x和y位置 如果你需要更多的见解,请告诉我,我很乐意为你提供帮助 另外,请注意,你不需要2个造型师就可以拥有白色笔划的蓝色月亮。CAShapeLayer具有填充和笔划属性,因此您可以简化代码 根据新信息,这里是我的新答案: 我无法通过使用转换获得良好的效果,因此我决定手动编写掩码。结果是:
/**
Draw a mask based on the moon phase progress.
- parameter rect: The rect where the mon will be drawn
- parameter progress: The progress of the moon phase. This value must be between 0 and 1
*/
func moonMask(in rect: CGRect, forProgress progress: CGFloat)->CALayer {
let path = CGMutablePath()
let center = CGPoint(x: rect.midX, y: rect.midY)
path.move(to: CGPoint(x: rect.midX, y: 0))
let relativeProgress = (max(min(progress, 1), 0) - 0.5) * 2
let radius = rect.width/2
let tgX = rect.midX+(relativeProgress * (radius*4/3))
path.addCurve(to: CGPoint(x: rect.midX, y: rect.maxY), control1: CGPoint(x: tgX, y: 0), control2: CGPoint(x: tgX, y: rect.maxY))
path.addArc(center: center, radius: rect.width/2, startAngle: .pi/2, endAngle: .pi*3/2, clockwise: false)
//path.closeSubpath()
let mask = CAShapeLayer()
mask.path = path
mask.fillColor = UIColor.black.cgColor
return mask
}
上面的函数绘制了一个shapelier,可以用作月球层的遮罩。该层将与进度参数相关,您将在函数中传递该参数,其中1表示满月,0表示新月
您可以将所有内容放在一起以获得所需的效果,如果需要,还可以提取路径创建代码以制作一个漂亮的动画
我希望这能回答你的问题。
为了快速测试,我写了以下内容:
import UIKit
let rect = CGRect(origin: .zero, size: CGSize(width: 200, height: 200))
let view = UIView(frame: rect)
view.backgroundColor = .black
let layer = view.layer
/**
Draw a mask based on the moon phase progress.
- parameter rect: The rect where the mon will be drawn
- parameter progress: The progress of the moon phase. This value must be between 0 and 1
*/
func moonMask(in rect: CGRect, forProgress progress: CGFloat)->CALayer {
let path = CGMutablePath()
let center = CGPoint(x: rect.midX, y: rect.midY)
path.move(to: CGPoint(x: rect.midX, y: 0))
let relativeProgress = (max(min(progress, 1), 0) - 0.5) * 2
let radius = rect.width/2
let tgX = rect.midX+(relativeProgress * (radius*4/3))
path.addCurve(to: CGPoint(x: rect.midX, y: rect.maxY), control1: CGPoint(x: tgX, y: 0), control2: CGPoint(x: tgX, y: rect.maxY))
path.addArc(center: center, radius: rect.width/2, startAngle: .pi/2, endAngle: .pi*3/2, clockwise: false)
//path.closeSubpath()
let mask = CAShapeLayer()
mask.path = path
mask.fillColor = UIColor.white.cgColor
return mask
}
let moonLayer = CAShapeLayer()
moonLayer.path = UIBezierPath(ovalIn: rect).cgPath
moonLayer.fillColor = UIColor.clear.cgColor
moonLayer.strokeColor = UIColor.white.cgColor
moonLayer.lineWidth = 2
moonLayer.shadowColor = UIColor.white.cgColor
moonLayer.shadowOpacity = 1
moonLayer.shadowRadius = 10
moonLayer.shadowPath = moonLayer.path
moonLayer.shadowOffset = .zero
layer.addSublayer(moonLayer)
let moonPhase = moonMask(in: rect, forProgress: 0.3)
moonPhase.shadowColor = UIColor.white.cgColor
moonPhase.shadowOpacity = 1
moonPhase.shadowRadius = 10
moonPhase.shadowPath = moonLayer.path
moonPhase.shadowOffset = .zero
layer.addSublayer(moonPhase)
view
非常感谢您的回复,是的,我知道笔划和填充,但假设在这种情况下它是无用的,我添加了gif文件,以显示一个示例我希望达到的效果。我想,应用三维旋转就足够了,但你能解释一下,我应该如何应用cos和sin?好的。现在清楚了!!抱歉,我知道你想绕轨道移动圆!明天我会用修正更新我的答案(这里是11点半,我累了!!XD)顺便说一句,你是对的。3D变换是您所需要的。很抱歉误解了您想要的效果!!