编辑代码

.4·4 项目实现
ViewController.swift
GeometryBand
Created by Zhifeng Chen on 2020/8/4.
Copyright  2020Zhifeng Chen. A1lrights reserved.
importUIKit
import Foundation
importAVFoundation
class Shape (
//名称
var name :String?
/1声音播放器
var soundPlayer :AVAudioPlayer?
//声音文件名称
var soundFile : 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.name = 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 : CGPoint?
//构造器
soundFile :String="FA.m4a")
super.init (name: name, origin: origin,soundFile:soundFile)
end =en at origin,som oint self.end =end
self.start = start
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!
//设置实例patn的线条终端样式.round或者.square
path?.lineCapStyle =.round
//设置实例 path的线条颜色
lineColor?.setStroke()
//画出线条
path?.stroke()
class Rectangle: Shape
//左上角采用基类Shape中的属性origin
//宽度和高度,一般可以采用cGSize
var size : CGSize?
//圆角的大小
var corner : CGFloat?
//构造器
init (nane: String, origin: CGPoint, size: CGSize, corner: CGFloat,sounaFileString="LA.m4a") i
super.init(name: name, origin: origin,soundFile:soundFile) self.size = size
self.corner = corner
convenience init (origin: CGPoint, size : CGSize, corner: CGFloat =0)(self.init (name: "Rectangle", origin: origin, size: size, corner: correr
// 重载 drawBezierPath 方法画矩形或者正方形
override func drawBezierPath()(
//向控制台输出信息
pzint("Draw \(name!)")
// 建立一个 UIBezierPath 实例对象
path = UIBezierPath(roundedRect: CGRect (origin: origin!, size: size!), cornerRadius:corner!)
if selectedFlag f
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 :CGSize?
//构造器
init (name: String, origin: CGPoint, center :CGPoint, raduis : CGFloat, size: CGSize,soundFile : String ="MI.m4a") (
super.init (name: name, origin: origin,soundFile:soundFile) self.center = center
self.raduis = raduis
self.size = size
)
convenience init(center : CGPoint,raduis : CGFloat) [
let x = center.x - raduis
let y = center.y - raduis
self.init(name: "circle", origin: CGPoint(x:x,y:y), center: center, raduis: raduis, size: CGSize(width: raduis, height: raduis))
)
convenience init(center: CGpoint, size : CGsize)
let x= center.x- size.width/2
let y = center.y - size,height/2
self.init (name: "Oval/E1lipse", origin: CGPoint(x:x,y:y), center: center, raduis:0, size: size)
//重载drawBezierPath方法画圆或者椭圆
override func drawBezierPath()(
//向控制台输出信息
print("Draw \(name!)")
//建立一个UTBezierPath 实例对象
path = UIBezierPath(ovalIn: CGRect(origin: origin!, size: size!)) 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 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)
}
eise
let oriqin CGPoint(x:0,y:0)
self.init (name: "Error", origin: origin, points: pointa
//重载drawBezierPath方法画多边形
override func drawBezierPath()
//向控制台输出信息
print("Dxaw\(name!)"
//如果不能识别,直接返回
if (name "Exrcr")
return
//建立一个 UTBezierPath 实例对象
path = UIBezierPath()
//调用实例path的move方法移动
path?.move(to:origin!)
for each in points!(
//调用实例path的addT,ine 方法画线
path?.addLine(to:each)
path?.close()
//设置实例path 的线条宽度
path?.lineWidth =lineWidth!
//设置实例path 的线条颜色
lineColor?.setStroke()
//画出线条
path?.stroke()
path?.fill()
class FiveStar : Shape f
//五角星和正五边形较为类似
//中心坐标
var center :CGPoint?
//半径
var radius : CGFloat?
//旋转的角度
var angel : CGFloat?
//1构造器
init (name: String, origin: 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
1
convenience init(center : CGpoint, radius: CGFloat,angel : CGFloat C)
let x = center.x - radius
let y = center.y -radius
self.init (name: "FiveStar", origin: CGPoint(x:x,y:y), center: center, radius: radius, angel: angel)
)
/1自定义方法drawBezierPath用于画五角星
override func drawBezierPath()(
//向控制台输出信息
print("Draw \(name!)")
// 调用贝塞尔曲线函数 UIBezierPath()
path = UIBezierPath()
//五角星旋转顶点
let i= 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 (
let x=(center?.x)!- sin(CGFicat(i)*angle+xzAngle)*radius! let y=(center?.y)!- cos(CGFloat(i)*angle+xzAngle)*radius! path?.addLine(to: CGPoirt(x: x, y: y))
)
path?.close()
if selectedFlag i
let dashes:[CGFloat] = [1, 3]
path?,setIineDash(dashes, count: dashes.count, phase: 0))
//线条宽度
path?.lineWidth = lineWidth!
//线条颜色为red红色
lineColor?.setStroke()
//画出这个圆
path?.stroke()
1
CzfView: UIView
class
//成员变量(属性) shapes,其类型为Array<Shape>
private var shapes : Array<Shape>=[]
//重载UIView的draw方法
override func draw( rect:CGRect)
一
//调用 shapes这个数组中的每个实例的方法
for s in shapes{
    s.drawBezierPath()
//增加实例到数组 shapes 中
func add(shape : Shape)
shapes.append(shape)
)
// 触摸事件
override funetouchesBegan( touches:Set<UITouch>,withevent: UIEvent?)
// 获得UITouch 集合
let touch:UITouch = touches.fizst! as UITouch
// 获得触摸所在位置的坐标
let point = couch.location(in: self)
//调用shapes 这个数组中的每个实例的方法
for s in shapes
//如果被选中
if s.isSelected(point: point)
//声音播放
s.playAud_o()
//更新屏幕显示
self.setNeedsDisplay()
class ViewController: UIviewController f
override func viewDidLoad()[
super.viewDidLoad()
// Do any additional setup after lcading the view, typicallyfrom a nib.
//此处调用FiveStar类,建立一个对象(实例)star
//五角星的中心坐标为(180,180)
let starCenter = CGPoint(x: 180, y: 180)
/1五角星的半径设定了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
/1此处建立了一个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)
}
}