编辑代码

//构造器
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)
                }
            }