【问题标题】:How to add shadow to SwiftUI arc?如何为 SwiftUI 弧添加阴影?
【发布时间】:2019-11-09 09:17:04
【问题描述】:

我有以下弧线:

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))
    }
}

如何添加阴影,类似于 Apple Watch 上的活动弧线,以便在整个圆圈处仍可辨别 endAngle?

编辑: 在 360+ 度(如此完整的圆)处还有一个问题,即两个弧端合并并显示为径向线(我看到这一点是因为我应用了 AngularGradient)。当然,Arc 不会像 Apple Watch 弧线那样做高级的事情,比如继续高于 startAngle 的位置。但这正是我想要的。有谁知道如何在 SwiftUI 中做到这一点?

【问题讨论】:

    标签: ios swift gradient swiftui


    【解决方案1】:

    这个呢?好吧...有点“棘手”

    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()
        }
    }
    

    【讨论】:

    • 太好了,没想到添加这个漂亮的阴影会这么简单。 SwiftUI 非常强大。同时,我编辑了我的问题,解释说我希望弧线在startAngle 上方持续整圈及更远,这就是 Apple Watch 弧线的作用。你有什么想法吗?
    • 有可能....看看这个...github.com/maxkonovalov/MKRingProgressView
    • 不幸的是,这似乎不是 SwiftUI。
    【解决方案2】:

    你的意思是这样的吗?

    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)
            }
        }
    }
    

    【讨论】:

    • 没有。这根本不会产生阴影,它只会产生一个彩色圆圈,其中endAngle 在 360 度以上无法辨别,因此看起来根本不像 Apple Watch 活动弧。 osxdaily.com/2016/01/21/…
    【解决方案3】:

    您好,您可以通过在项目文件中编写扩展来修复和处理所有这些功能

        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
    }
    

    现在在情节提要中,您可以处理阴影 或者你不想,而且太多了,你可以只使用你需要的部分。

    【讨论】:

    • 我认为他的意思是 SwiftUI ....当然你可以使用 Representable...我知道 ;)
    • 正如@Chris 所说,我希望在纯 SwiftUI 中使用它。
    猜你喜欢
    • 1970-01-01
    • 2022-01-24
    • 1970-01-01
    • 1970-01-01
    • 2014-10-10
    • 1970-01-01
    • 1970-01-01
    • 2021-06-23
    • 2021-03-23
    相关资源
    最近更新 更多