//构造器
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
}
//
// ViewController.swift
// UGeometryBand
//
// 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 : 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?
//构造器
init(name: String, origin: CGPoint, start : CGPoint, end : CGPoint,soundfile : String="FA.m4a") {
super.init(name: name, origin: originsoundfile: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实例对象
pathnUIBezierPath()
//调用实例path的move方法移动
path?.move(to: start!)
//调用实例path的addLine方法画线
path?.addLine(to: end!)
//设置实例path的线条宽度
path?.lineWidth = lineWidth!
//设置实例path的线条终端样式.round或者.square
path?.lineCapstylem.round
//设置实例path的线条颜色
lineColor?.setStroke()
//画出线条
path?.stroke()
}
class Rectangle :Shape {
//左上角采用基类Shape中的属性origin
//宽度和高度,一般可以采用CGSize
var size : CGSize?
//圆角的大小
var corner : CGFloat?
//构造器
init(name: String, crigin: CGPoint, size :CGSize, corner : CGFloat,soundFile :String = "LA.m4a") {
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 : corner)
}
//重载drawBezierPath方法画矩形或者正方形
override func drawBezierPath() {
//向控制台输出信息
print("Draw\(name!)")
//建立一个UIBezierPath实例对象
path = UIBezierPath(roundedRect: CGRect(origin: 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 : CGSize?
//构造器
init(name:String,origin:CGPoint,center:CGPoint,raduis: OGFloat,size:CGSize,soundFile :String="MI.mAa") {
super.init(name: name, origin: origin,soundFile:soundFile)
self.centerm = center
self.raduis = mraduis
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:xy:y),center: center,raduis: raduis,size: CSize(width: raduis, height: raduis) {
convenience init(center :GPoint,size :CGSize) {
let x = centerx - size.width/2
let y = centery - size.height/2
self.init(name:"Oval/E1lipse",origin: CGPoint(x:xy:y),center:center, raduis: 0, size: size)
}
//重载drawBezierPath方法画圆或者椭圆
override func drawBezierPath() {
//向控制台榆出信息
print("Draw\(name!)")
//建立一个UIBezierPath实例对象
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)
}
else {
let origin = CGPoint(x:0,y:0)
self.init(name:"Error", origin: origin, points: points)
}
//重载drawBezierPath方法画多边形
override func drawBezierPath() {
//向控制台输出信息
print("Draw \(name!)")
// 如果不能识别,直接返回
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?
//构造器
it(name:String,origin: CGPoint, center : OGPoint, radius : OGFloat,angel CGFloat,soundFile :String ="so.m4a") {
super.init(name: name,origin: origin,soundFile: soundFile)
self.center = center
self.radius = radius
self.angel = angel
}
convenience init(center :CGPoint, radius : CGFloat,angel : CGFloat = 0) {
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)
}
//自定义方法drawBezierPath用于画五角星
override func drawBezierPath() {
//向控制台输出信息
print("Draw \(name!)")
//调用贝塞尔曲线函数UIBezierPath()
pathmUIBezierPath()
//五角星旋转顶点
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 p1 = 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(CGFloat(i)*angle+xzAngle)*radius!
let y=(center?y)! - cos(CGFloat(i)*anglexzAngle)*radius!
path?.addLine(to: CGPoint(x:x,y:y))
path?.close()
if selectedFlag {
let dashes: [CGFloat] = [1,3]
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> []
s.drawBezierPath()
}
//增加实例到数组shapes中
func 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)
}
}