编辑代码

//
//	ViewController.swift	
//	GeometryBand	
//
//	Created by Zhifeng Chen on 2020/8/4.	
//	Copyright  2020 年 Zhifeng Chen. All rights reserved.	
//

import uikit
import Foundation import AVFoundation

class Shape {
//名称
var name:String?
//声音播放器
var soundPlayer ! AVAudioplayer?//声音文件名称
var soundFile t String?//UIBezierPath
var path : UIBezierPath?//selected?
var selectedFlag : Bool- false//左上角的位置坐标
var origin : CGPoint?//线条颜色
var lineColor :UIColor?=UIColor.red//填充颜色
var fillColor :UIColor?=UIColor.green//线条宽度
var lineWidth :CGFloat?=5//构造器函数init
init(name:String, origin : CGPoint,soundFile : String = "DO.m4a" )!
self.namem name
self.origin-origin
self.soundFile - soundFile}
//便利构造器函数init
convenience init(origin :CGPoint){
self.init(name:"Shape Bassclass", origin: origin)

//自定义方法 drawBezierPath 用于画图 func drawBezierPath(){
//向控制台输出信息
print("Draw \(name!)")
func playAudio(){
print("Play sound:\(soundFile!)")
let path - Bundle.main.path(forResource: soundFile,ofType:nil) let url=URL(fileURLWithPath:path!)
soundPlayer =try? AVAudioPlayer(contentsOf:url) soundPlayer?.play()
func isSelected(point :CGPoint)-> Bool{
if (path?.contains(point))! {
selectedFlag = true return true

else {
selectedFlag=false return false
class Line : Shape (
//残段的起点
var start : cGPoint?//线段的终点
var end :CGPoint7
// 构造器
init(name: String, origin: CGPoint, start : CGPoint, end : CGPoint,
soundFile :String ="FA.m4a") {
super.init(name: name, origin: origin,soundFile:soundFile) self.start - start self.end- end
convenience init(start : CGPoint, end :CGPoint)(
self.init(name: "Line", origin: start, start: start, end: end)
//重载drawBezierPath方法
override func drawBezierPath(){
//向控制台输出信息
print("Draw \(name!)")
//建立一个 UIBezierPath实例对象 path -UIBezierPath()
//调用实例path的move 方法移动 path?.move(to: start!)
//调用实例path的addLine 方法画线 path?.addLine(to: end!)//设置实例path的线条宽度
path?.lineWidth=lineWidth!
//设置实例path的线条终端样式.round或者.square path?.lineCapStyle-.round//设置实例path的线条颜色 lineColor?.setStroke()//画出线条
path?.stroke()

class Rectangle :Shape (
//左上角采用基类 Shape 中的属性 origin//宽度和高度,一般可以采用 CGSize var size : CGSize?//圆角的大小
var corner :cfloat?
//构造器
init(nme:String,origin: CGPoint, size i CCSize, CoEner : CCFLost,ScndFile
String-"LA.min")(
super.init(name: name, origin: origin,soundFlle:soundfile) self.size- size
self.corner=corner
convenience initiorigin: CGPoint, size iCGSize, corner : CGLont - o) t
self.init(name: "Rectangle", origin: origin, size: size, corner :corner)
//重载drawBezierPath方法画矩形或者正方形 override func drawBezierPath(){
//向控制台输出信息
print("Draw\(name!)")
//建立一个UIBezierPath实例对象
Path-UIBezierPath(roundedRect: CGRect(origint origin!, size:
size!), cornerRadius: corner!)
if selectedFlag {
let dashes: [CGFloat] - [1,3]
path?.setLineDash(dashes, count: dashes.count,phase:0)
//设置实例path的线条宽度
path?.lineWidth = lineWidth!//设置实例path的线条颜色 lineColor?.setStroke()//画出线条
path?.stroke(()
}
class Circle :Shape {
//圆心坐标
var center : CGPoint?//半径长度
var raduis :CGFloat?
//椭圆的宽度和高度,一般可以采用CGSize var size :csize?

//构造器
init(name: String, origin:CGPoint,center:CGPoint,raduis:CGFloat,size:
CGSize,soundFile :String = "MI.m4a"){
super.init(name: name, origin: origin,soundFile:soundFile) self.centermcenter self.raduis = raduis self.size = size

convenience init(center :CGPoint,raduis :CGFloat){
let xm center.x-raduis
let y=center.y-raduis	章	
self.init(name:"Circle",origin:CGPoint(xxyy), center: center,
raduis:raduis,size: GSize(width: raduis, height: raduis))
convenience init(center :CGPoint, size :CGSize)(
letx=center.x-size.width/2 lety=center.y-size.height/2
self.init(name:"Oval/Ellipse", origin: CGPOint(xix,y:y), center
center, raduis: 0, size:size)
//重载drawBezierPath方法画圆或者椭圆 override func drawBezierPath(){
//向控制台输出信息
print("Draw\(name!)")
//建立一个UIBezierPath实例对象
path=uIBezierPath(ovalIn: CGRect(origin: originl, size: size!)) if selectedFlag{
let dashes: [CGFloat]=[1,3]
path?setlineDash(dashes, count: dashes.coant, phase: a)}
//设置实例path的线条宽度
path?lineWidth=lineWidth!//设置实例path的线条颜色 lineColor?.setStroke()//画出线条
path?.stroke()}
}
class Polygons :Shape {
//多边形主要是通过多个顶点相互连接来绘图//顶点数组
var points : Array<cGPoint>?//构造器
init(name: String,origin:CGPoint,points :Array<CGPoint>soundFile:String
="RE.m4a") {
super.init(name: name, origin: origin,soundfile: soundfile) self.points=points}
convenience init(points :Array<cGPoint> ){
if points.count== 3{
self.init(name: "Triangel", origin: points.first!, points:
points)
}
else if points.count >= 3 {
self.init(name: "Polygons", origin: points.first!, points:
points)
else (
let origin = CGPoint(x: 0, y:0)
self.init(name: "Error", origin: origin, points: points)
}
//重载drawBezierPath方法画多边形 override func drawBezierPath(){
//向控制台输出信息
print("Draw\(name!)")7/如果不能识别,直接返回 if(name== "Error") {
return
}
//建立一个UIBezierPath实例对象 path=UIBezierPath()
//调用实例path的move方法移动 path?.move(to: origin!) for each in points! {
//调用实例path的addLine方法画线 path?.addLine(to: each)
}
path?.close()
//设置实例path的线条宽度
path?.lineWidth = lineWidth!//设置实例path的线条颜色 lineColor?.setStroke()//画出线条
path?.stroke() path?.fill()
}
class FiveStar : Shape {
//五角星和正五边形较为类似//中心坐标
var center : CGPoint?//半径
var radius : CGFloat?//旋转的角度
var angel : CGFloat?//构造器
init(name:Strina, oriain:CGPoint, center :CGPoint, radius : CGFloat,angel :
CGFloat,soundFile : String="so.m4a"){
super.init(name: name, origin: origin,soundfile: soundfile) self.center=center self.radius =radius self.angel=angel
-0) {	convenience init(center :CGPoint, radius i CGFloatiangel : CGrlont	
let x= center.x- radius let y-center.y-radius
se1f.init(name:FiveStar",origint CGPointixixyiyl, Center: canter.
radius: radius, angel: angel)
// 自定义方法 drawBezierPath 用于画五角星 override func drawBezierPath()(
//向控制台榆出信息
print("Draw\(name!)")
//调用贝塞尔曲线函数UIBezierPath() path =UIBezierPath()//五角星旋转顶点
leti=360/angel!
let xzAngle=CGFloat.pi*2/i
let xzX= (center?.x)!-sin(xzAngle)*radius! let xzY=(center?.y)!-cos(xzAngle)*radius! let pl-CGPoint(x: xzX,y:xzY) path?.move(to:pl)
let angle-CGFloat.pi*4/5 for i in 1...5 {
letx=(center?.x)! - sin(CGFloat(i)*angle+xzAngle)*radius! let y=(center?.y)! - cos(CGFloat(i)*angle+xzAngle)*radius! path?.addLine(to: CGPoint(x:x,y:y))
path?.close()
if selectedFlag {
let dashes:[CGFloat]=[13]
path?.setLineDash(dashes, count:dashes.count, phase:0)
// 线条宽度
path?.lineWidth = lineWidth!//线条颜色为red红色
lineColor?.setStroke()//画出这个圆
path?.stroke()
)
class CzfView :UIView{
//成员变量(属性)shapes,其类型为Array<Shape> private var shapes :Array<Shape>=[]//重载UIView的draw方法
override func draw( rect: CGRect){
//调用shapes 这个数组中的每个实例的方法 for s in shapes{
s.drawBezierPath0

//增加实例到数组shapes中 fune add(shape :Shape)(
shapes.append(shape)
//触摸事件
override func touchesBegan( touches: Set<UITouch>, with event:
UIEvent?){
// 获得 UITouch 集合
let touch:UITouch - touches.first! as UITouch
// 获得触摸所在位置的坐标
let point = touch.location(in: self)//调用 shapes 这个数组中的每个实例的方法 for s in shapes {
//如果被选中
if s.isSelected(point: point)(
// 声音播放
s.playAudio()//更新屏幕显示
self.setNeedsDisplay(

}
class ViewController: UIViewController {
override func viewDidLoad(){
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a
nib.
//此处调用FiveStar类,建立一个对象(实例)star//五角星的中心坐标为(180,180)
let starCenter = CGPoint(x: 180, y:180)//五角星的半径设定了 90,旋转角度为15度
let star = FiveStar(center: starCenter, radius: 50, angel:45) star.lineColor=UIColor.blue
// 此处调用 Circle 类,建立一个对象oval
let ovalCenter = CGPoint(x:100, y:300)
let ovalSize = CGSize(width: 100, height: 60)
let oval = Circle(center: ovalCenter, size: ovalsize)//此处调用 Rectangle 类,建立一个对象rect let rectOrigin = CGPoint(x:60, y:50)
let	rectSize=cGsize(width: 100,height:50)	
let rect=Rectangle(origin: rectorigin, size: rectsize, corner: 6) rect.lineColor =UIColor.gray
//此处建立了一个Czfview的实例myView
let myView = Czfview(frame: CGRect(x: 0, y: 0, width: self view.
frame.size width, height: self.view.frame.size height)
//清除背景色
myView.backgroundColor =UIColor.clear//赋值给myView中的成员变量(属性)shape myView.add(shape: star) myView.add(shape: oval) myView.add(shape: rect)//显示myView
self.view.addSubview(myView)