您当前的位置: 首页 >  ui

SwiftUI:如何使用Path API绘制扑克牌阴影?

发布时间:2021-03-04 19:31:49 ,浏览量:0

Image for post

在SwiftUI中,可以使用“路径”和“形状”实现自定义渲染。 可以通过路径创建形状。 这使“路径”成为基本的绘图元素。

在本教程中,我们将使用Path来创建不同色调的扑克牌。 Path的使用参见《SwiftUI从入门到实战》第2章的第25节:通过Path路径绘制不规则的线条和图形 。

首先,让我们学习可以绘制的路径类型。

  • Line 追加一条直线
func addLine(to point: CGPoint)
  • Arc 相对于中心附加弧线。 需要角度,半径,中心点和方向。
func addArc(withCenter center: CGPoint, 
     radius: CGFloat, 
 startAngle: CGFloat, 
   endAngle: CGFloat, 
  clockwise: Bool)
  • Quad Curve 将曲线添加为二次方程式。 二次方程需要三个点才能绘制路径。

Image for post

func addQuadCurve(to endPoint: CGPoint, 
     controlPoint: CGPoint)
  • Cubic Curve 将曲线添加为三次方程。 三次方程式需要四个点才能绘制路径。

Image for post

func addCurve(to endPoint: CGPoint, 
controlPoint1: CGPoint, 
controlPoint2: CGPoint)

现在让我们尝试使用上面的方法创建卡片阴影。 但是在开始绘制之前,让我们先使用一些实用程序功能。 我们将在本练习中多次使用这些功能。

import SwiftUI

extension CGRect {
    /// center of rect
    var center: CGPoint {
        return CGPoint(x: self.midX, y: self.midY)
    }
    /// if rect is not square take centered square to draw
    var centeredSquare: CGRect {
        let width = ceil(min(size.width, size.height))
        let height = width

        let newOrigin = CGPoint(x: origin.x + (size.width - width) / 2, y: origin.y + (size.height - height) / 2)
        let newSize = CGSize(width: width, height: height)
        return CGRect(origin: newOrigin, size: newSize)
    }
    
    func flatten() -> (CGFloat, CGFloat, CGFloat, CGFloat) { 
        return (origin.x, origin.y, size.width, size.height)
    }
}

extension Angle {
    
    static let A180 = Angle(radians: .pi) //180
    
    static let A90 = Angle(radians: .pi/2) //90
    
    static let A270 = Angle(radians: (.pi/2) * 3) //270
    
    static let A360 = Angle(radians: .pi * 2) //360
}

钻石阴影是最容易绘制的阴影。 我们可以使用简单的直线,Curve或Arc来实现。 对于此演示,我们将使用Arcs。

1.移动到底部的中心或任何居中的边缘(左侧,右侧或顶部)
2.保持拐角为中心,在下一个居中边缘绘制圆弧
import SwiftUI

struct Diamond: Shape {
    
    func path(in rect: CGRect) -> Path {
        let (x, y, width, height) = rect.centeredSquare.flatten()
        let lowerPoint = CGPoint(x: x + width / 2, y: (y + height ))
        
        let path = Path { p in
            p.move(to: lowerPoint)
            p.addArc(center: CGPoint(x: x, y: (y + height)),
                radius: (width / 2),
                startAngle: .A360,
                endAngle: .A270,
                clockwise: true)
            p.addArc(center: CGPoint(x: x, y: y),
                radius: (width / 2),
                startAngle: .A90,
                endAngle: .zero,
                clockwise: true)
            p.addArc(center: CGPoint(x: x + width, y: y),
                radius: (width / 2),
                startAngle: .A180,
                endAngle: .A90,
                clockwise: true)
            p.addArc(center: CGPoint(x: x + width, y: y + height),
                radius: (width / 2),
                startAngle: .A270 ,
                endAngle: .A180,
                clockwise: true)
        }
        return path
    }
    
}

爱心图形是两条三次曲线和两条弧线的组合。

1.移至中心底部 2.绘制左中心或右中心的三次曲线。 将控件保持在45度角。 3.从最后一点以半径和中心为25%的宽度到宽度和高度为25%绘制180°弧线。 4.反向重复,即3-2

import SwiftUI

struct Heart: Shape {
    func path(in rect: CGRect) -> Path {
        
        let (x, y, width, height) = rect.centeredSquare.flatten()
        let lowerPoint = CGPoint(x: x + width / 2, y: (y + height ))
        
        let path = Path { p in
            p.move(to: lowerPoint)
            p.addCurve(to: CGPoint(x: x, y: (y + (height / 4))),
                  control1: CGPoint(x: (x + (width / 2)), y: (y + (height * 3 / 4))),
                  control2: CGPoint(x: x, y: (y + (height / 2))))
            p.addArc(center: CGPoint(x: (x + (width / 4)), y: (y + (height / 4))),
                radius: (width / 4),
                startAngle: .A180,
                endAngle: .zero,
                clockwise: false)
            p.addArc(center: CGPoint(x: (x + (width * 3 / 4)), y: (y + (height / 4))),
                radius: (width / 4),
                startAngle: .A180,
                endAngle: .zero,
                clockwise: false)
            p.addCurve(to: lowerPoint,
                  control1: CGPoint(x: (x + width), y: (y + (height / 2))),
                  control2: CGPoint(x: (x + (width / 2)), y: (y + (height * 3 / 4))))
        }
        return path
    }
    
}

.

可以通过将心形阴影形状与矩形合并来构建黑桃阴影。

1.创建高度为90%的心形 2.旋转心脏并获取路径 3.以适当的宽度从中心到底部中心创建矩形 4.合并两条路径

import SwiftUI

struct Spade: Shape {
    func path(in rect: CGRect) -> Path {
        
        let (x, y, width, height) = rect.centeredSquare.flatten()
        
        var heartPath = Heart().rotation(.A180).path(in: CGRect(x: x, y: y, width: width, height: height * 0.9)) //take 10% for bottom rect
        let rectPath = Rectangle().path(in: CGRect(x: x + width * 0.4, y: y + height * 0.5, width: width * 0.2, height: height * 0.5))
        
        heartPath.addPath(rectPath)
        return heartPath
    }
}

梅花底纹,三个圆和一个三角形。

1.将rect分成2x2网格 2.以0-1网格相交处绘制一个圆作为直径 3.画一个圆,以0-2的网格相交为直径 4.画一个与1-3网格相交的圆作为直径 5.从中心到底部绘制60°等边三角形

import SwiftUI

struct Club: Shape {
    func path(in rect: CGRect) -> Path {
        
        let (x, y, width, height) = rect.centeredSquare.flatten()
        let center = rect.centeredSquare.center
        
        let center1 = CGPoint(x: x + width / 2, y: (y + height/4 ))
        let center2 = CGPoint(x: x + width / 4, y: (y + height/2 ))
        let center3 = CGPoint(x: x + width * 3 / 4, y: (y + height/2 ) )
        let radius =  (width / 4)
        let path = Path { p in
            p.move(to: center)
            p.addArc(center: center1,
                     radius: radius,
                startAngle: .A360,
                endAngle: .zero,
                clockwise: true)
            p.addArc(center: center2,
                    radius: radius,
                    startAngle: .A360,
                    endAngle: .zero,
                    clockwise: true)
            p.addArc(center: center3,
                     radius: radius,
                 startAngle: .A360,
                    endAngle: .zero,
                    clockwise: true)
            p.move(to: center)
            p.addLine(to: CGPoint(x: x + width / 4, y: y + height))
            p.addLine(to: CGPoint(x: x + width * 3 / 4, y: y + height))
            p.addLine(to: center)
        }
        
        return path
    }
}

完整 Demo:

prafullakumar/DemoPlayingCard

译自:https://medium.com/dev-genius/swiftui-how-to-draw-playing-cards-shades-using-path-api-f2d6c5425af1

关注
打赏
1688896170
查看更多评论

暂无认证

  • 0浏览

    0关注

    109966博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文
立即登录/注册

微信扫码登录

1.6460s