[英]How to add shadow to SwiftUI arc?
I have the following arc:我有以下弧线:
struct Arc : Shape
{
@Binding var endAngle: Double
var center: CGPoint
var radius: CGFloat
func path(in rect: CGRect) -> Path
{
var path = Path()
path.addArc(center: center, radius: radius, startAngle: .degrees(270), endAngle: .degrees(endAngle), clockwise: false)
return path.strokedPath(.init(lineWidth: 50, lineCap: .round))
}
}
How can I add shadow, similar to the activity arcs on Apple Watch, such that at full circle the endAngle is still discernible?如何添加阴影,类似于 Apple Watch 上的活动弧线,以便在整个圆圈处 endAngle 仍然可辨别?
EDIT: There's the additional issue at 360+ degrees (so full circle), that both arc ends get combined and are shown as a radial line (I see this because I've a applied an AngularGradient
).编辑:在 360+ 度(如此完整的圆)处还有一个额外的问题,即两个弧端合并并显示为径向线(我看到这一点是因为我应用了AngularGradient
)。 Of course Arc
won't do advanced things like continuing above the startAngle
position, like the Apple Watch arcs do.当然Arc
不会像 Apple Watch arcs 那样做高级的事情,比如在startAngle
position 之上继续。 But this was what I was looking for.但这正是我想要的。 Does anyone know how to do that in SwiftUI?有谁知道如何在 SwiftUI 中做到这一点?
what about this?那这个呢? ok...bit "tricky"好吧...有点“棘手”
import SwiftUI
struct Arc : Shape
{
@Binding var startAngle: Double
@Binding var endAngle: Double
var center: CGPoint
var radius: CGFloat
var color: Color
func path(in rect: CGRect) -> Path
{
var path = Path()
let cgPath = CGMutablePath()
cgPath.addArc(center: CGPoint(x: rect.midX, y: rect.midY), radius: radius, startAngle: CGFloat(startAngle), endAngle: CGFloat(endAngle), clockwise: true)
// path.addArc(center: center, radius: radius, startAngle: .degrees(270), endAngle: .degrees(endAngle), clockwise: false)
path = Path(cgPath)
return path.strokedPath(.init(lineWidth: 50, lineCap: .round))
}
}
struct ContentView: View {
var body: some View {
ZStack() {
// Arc(endAngle: .constant(269), center: CGPoint(x: 200, y: 200), radius: 150, color: .red).foregroundColor(.red).opacity(0.2)
Arc(startAngle: .constant(80 + 271), endAngle: .constant(80 + 271 + 340), center: CGPoint(x: 205, y: 205), radius: 150, color: .red).foregroundColor(.red)//.shadow(color: .black, radius: 5, x: -30, y: -170)
Arc(startAngle: .constant(90), endAngle: .constant(80 + 270), center: CGPoint(x: 200, y: 200), radius: 150, color: .red).foregroundColor(.red).shadow(color: .black, radius: 5, x: -114, y: -230)
}.background(Color.black)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
do you mean something like this?你的意思是这样的吗?
struct Arc : Shape
{
@Binding var endAngle: Double
var center: CGPoint
var radius: CGFloat
var color: Color
func path(in rect: CGRect) -> Path
{
var path = Path()
path.addArc(center: center, radius: radius, startAngle: .degrees(270), endAngle: .degrees(endAngle), clockwise: false)
return path.strokedPath(.init(lineWidth: 50, lineCap: .round))
}
}
struct ContentView: View {
var body: some View {
ZStack() {
Arc(endAngle: .constant(269), center: CGPoint(x: 200, y: 200), radius: 150, color: .red).foregroundColor(.red).opacity(0.2)
Arc(endAngle: .constant(90), center: CGPoint(x: 200, y: 200), radius: 150, color: .red).foregroundColor(.red)
}
}
}
Hi you can fix and handle all of these features by writing an extension in your project file嗨,您可以通过在项目文件中编写扩展来修复和处理所有这些功能
import UIKit
extension UIView {
func roundCorners(corners: UIRectCorner, radius: CGFloat) {
let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.path = path.cgPath
self.layer.mask = mask
}
// MARK: Shadow extension UIView {
func dropShadow(scale: Bool = true) {
layer.masksToBounds = false
layer.shadowColor = UIColor.blue.cgColor
layer.shadowOpacity = 1.0
layer.shadowOffset = CGSize(width: -1.5, height: 3)
layer.shadowRadius = 3
layer.shadowPath = UIBezierPath(rect: bounds).cgPath
layer.shouldRasterize = true
layer.rasterizationScale = scale ? UIScreen.main.scale : 1
}
func dropShadow(color: UIColor, opacity: Float = 0.5, offSet: CGSize, radius: CGFloat = 1, scale: Bool = true) {
layer.masksToBounds = false
layer.shadowColor = color.cgColor
layer.shadowOpacity = opacity
layer.shadowOffset = offSet
layer.shadowRadius = radius
layer.shadowPath = UIBezierPath(rect: self.bounds).cgPath
layer.shouldRasterize = true
layer.rasterizationScale = scale ? UIScreen.main.scale : 1
}
func setAnchorPoint(_ point: CGPoint) {
var newPoint = CGPoint(x: bounds.size.width * point.x, y: bounds.size.height * point.y)
var oldPoint = CGPoint(x: bounds.size.width * layer.anchorPoint.x, y: bounds.size.height * layer.anchorPoint.y)
newPoint = newPoint.applying(transform)
oldPoint = oldPoint.applying(transform)
var position = layer.position
position.x -= oldPoint.x
position.x += newPoint.x
position.y -= oldPoint.y
position.y += newPoint.y
layer.position = position
layer.anchorPoint = point
}
class func fromNib<T: UIView>() -> T {
guard let view = Bundle.main.loadNibNamed(String(describing: T.self), owner: nil, options: nil)?.first as? T else { fatalError() }
return view
}
now in storyboard you can handle shadows or you don't want to, and it's too much, you can use the only part you need.现在在 storyboard 中,您可以处理阴影或不想处理阴影,而且太多了,您可以使用唯一需要的部分。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.