本文转载自微信公众号《Swift社区》,作者魏贤智。转载本文请联系Swift社区公众号。为了进行一些严肃的绘图,我将引导您使用SwiftUI创建一个简单的螺旋仪。“Spirograph”是一种玩具的品牌名称,您可以将铅笔放在一个圆圈中,然后绕着另一个圆圈的圆周旋转,从而创造出各种称为轮盘赌的几何图案——就像赌场游戏一样。此代码包含一个非常具体的公式。我会解释,但如果您不感兴趣,也可以跳过本章——这只是为了好玩,这里没有介绍新的Swift或SwiftUI。我们的算法有四个输入:内圆的半径。外圆的半径。虚拟笔与外圈圆心的距离。抽多少轮盘赌。这是可选的,但我认为它确实有助于显示算法运行时发生的情况。那么,让我们开始吧:structSpirograph:Shape{letinnerRadius:IntletouterRadius:Intletdistance:Intletamount:CGFloat}然后,我们从数据中准备三个值,从内半径和外半径的最大公约数(GCD)开始。计算两个数的GCD通常使用Euclid算法完成,该算法具有稍微简化的形式:funcgcd(_a:Int,_b:Int)->Int{vara=avarb=bwhileb!=0{lettemp=bb=a%ba=temp}returna}将此方法添加到Spirograph结构中。另外两个值是内外半径之差,以及我们需要走多少步才能画出轮子——这是?度乘以外半径除以最大公约数,再乘以我们的数量输入。我们所有的输入在以整数形式提供时效果最好,但在绘制轮盘赌时我们需要使用CGFloats,因此我们还将创建输入的CGFloat副本。现在将此path(in:)方法添加到Spirograph结构中:funcpath(inrect:CGRect)->Path{letdivisor=gcd(innerRadius,outerRadius)letouterRadius=CGFloat(self.outerRadius)letinnerRadius=CGFloat(self.innerRadius)letdistance=CGFloat(self.distance)letdifference=innerRadius-outerRadiusletendPoint=ceil(2*CGFloat.pi*outerRadius/CGFloat(divisor))*amount//morecodetocome}最后,我们可以通过从0循环到我们的终点Bet来绘制轮盘并将该点放置在精确的X/Y坐标处。计算循环中给定点的X/Y坐标(称为“theta:theta”)是真正的数学来源,但老实说,我只是将维基百科的标准方程式翻译成Swift——这不是我梦想中的记忆!X等于半径差乘以θ的余弦,乘以半径差的余弦除以半径乘以θ的距离。Y等于半径差乘以θ的正弦值减去距离乘以半径差乘以半径的正弦值乘以θ。这是核心算法,但我们要做两个小改动:我们将绘图矩形的宽度或高度的一半分别添加到X和Y,以便它在绘图空间中居中;如果θ为0,也就是说,如果这是轮子在板上绘制的第一个点,我们将在我们的路径上调用move(to:)而不是addLine(to:)。这是path(in:)方法的最终代码——将//morecodetocomecomment替换为以下注释:varpath=Path()forthetainstride(from:0,through:endPoint,by:0.01){varx=差异*cos(theta)+距离*cos(差异/outerRadius*theta)vary=差异*sin(theta)-距离*sin(差异/outerRadius*theta)x+=rect.width/2y+=rect.height/2iftheta==0{path.move(to:CGPoint(x:x,y:y))}else{path.addLine(to:CGPoint(x:x,y:y))}}returnpath我意识到这有很多繁重的数学运算,但回报即将到来:我们现在可以在视图中使用该形状,添加各种滑块来控制内半径、外半径、距离、数量,甚至颜色:=25.0@Stateprivatevaramount:CGFloat=1.0@Stateprivatevarhue=0.6varbody:someView{VStack(spacing:0){Spacer()Spirograph(innerRadius:Int(innerRadius),outerRadius:Int(outerRadius),distance:Int(distance),amount:amount).stroke(颜色(色调:色调,饱和度:1,亮度:1),线宽:1).frame(宽度:300,高度:300)Spacer()Group{Text("Innerradius:\(Int(innerRadius))")滑块(值:$innerRadius,在:10...150,step:1).padding([.horizo??ntal,.bottom])Text("Outerradius:\(Int(outerRadius))")Slider(value:$outerRadius,in:10...150,step:1).padding([.horizo??ntal,.bottom])Text("Distance:\(Int(distance))")Slider(value:$distance,in:1...150,step:1).padding([.horizo??ntal,.bottom])Text("Amount:\(amount,specifier:"%.2f")")Slider(value:$amount).padding([.horizo??ntal,.bottom])Text("Color")Slider(value:$hue).padding(.horizo??ntal)}}}}代码很多,但我希望您花时间运行该应用程序并欣赏轮盘赌的轮盘有多漂亮。一种称为次摆线轮盘赌的形式-通过对算法进行小的调整,您可以生成以不同方式呈现美丽的外摆线等。在我结束之前,我想提醒你这里使用的参数方程是数学标准,不是我刚刚发明的东西——我真的去了谷歌关于hypotrochoids[1]的页面并将它们转换为Swift。参考文献[1]次摆线:http://www.durangobill.com/Trochoids.html
