编辑代码

//
ViewController.swift
GraphDemo
//
Created gy Li Tao on 2022/01/42.
Copyright © 2022 Li Tao.All right reserved
//
import UIKit
class CoreGraphUIView : UIView {
    override func touchesBegan(_touches:Set<UITouch>, with event: UIEvent?){
        self.backgroundColor = UIColor.red
        print("Begin:\(touches)")
    }
    override func touchesEnded(_touches: Set<UITouch>, with event: UIEvent?) {
        self.backgroundColor = UIColor.lightGray
        print("Ended:\(touches)")
    }
    override func touchesMoved(_touches: Set<UITouch>, with event: UIEvent?) {
        self.backgroundColor = UIColor.blue
        print("Moved:\(touches)")
    }
}
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        let height = self.view.frame.size.height
        let width = self.view.frame.size.width
        let graphFrame = CGRect(x: 0, y: 0, width: width, height: height)
        let graphView = CoreGraphUIView(frame: graphFrame)
        graphView.backgroundColor = UIColor.white
        self.view.addSubview(graphView)
    }
}
let touch:UITouch = touches.first! as UITouch
print(touch.location(in: view).x)
print(touch.location(in: view).y)

class Shape {
    var name ; String?
    var sides : Int?
    var origin : CGPoint?
    var lineColor : UIColor = UIColor.red
    var fillColor : UIColor = UIColor.green
    var lineWidth : CGFloat = 2
    init(name : String, sides : Int, origin : CGPoint) {
        self.name = name
        self.sides = sides
        self.origin = origin
    }
    func sayHello(){
        print("Shape is \(name!),sides \(sides!), and originCord is(\(origin!.x),\(origin!.y))")
    }
}

//ViewController.swift
//ShapeDemo
//Created by Li Tao on 2023/5/26
//Copyright © 2023 Li Tao .All right reserved.
//
import UIKit
class Shape {
    var name ; String?
    var sides : Int?
    var origin : CGPoint?
    var lineColor : UIColor = UIColor.red
    var fillColor : UIColor = UIColor.green
    var lineWidth : CGFloat = 2
    init(name : String, sides : Int, origin : CGPoint) {
        self.name = name
        self.sides = sides
        self.origin = origin
    }
    func sayHello(){
        print("Shape is \(name!),sides \(sides!), and originCord is(\(origin!.x),\(origin!.y))")
    }
}
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        let myShape = Shape(name:"BaseShape", sides: 0, origin: CGPoint(x: 0, y: 0))
        myShape.sayHello()
    }
}

//重载uiview中的draw函数
import UIKit 
class Shape {
     var name ; String?
    var sides : Int?
    var origin : CGPoint?
    var lineColor : UIColor = UIColor.red
    var fillColor : UIColor = UIColor.green
    var lineWidth : CGFloat = 2
    init(name : String, sides : Int, origin : CGPoint) {
        self.name = name
        self.sides = sides
        self.origin = origin
    }
    func sayHello(){
        print("Shape is \(name!),sides \(sides!), and originCord is(\(origin!.x),\(origin!.y))")
    }
}
class CzfView : UIView {
    var shape : Shape?
    override func draw(_ rect: CGRect) {
        guard let s = shape else {
            return
        }
        s.sayHello()
    }
}
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from anib.
        let myShape = Shape(name:"BaseShape", sides: 0, origin: CGPoint(x:0, y: 0))
        let width = self.view.frame.size.width
        let height = self.view.frame.size.height
        let myView = CzfView(frame: CGRect(x: 0, y: 0, width: width, height: height))
        myView.shape = myShape
        self.view.addSubview(myView)
    }
}
func drawBezierPath () {
    let path = UIBezierPath()
    let center : CGPoint = CGPoint(x: 100, y: 100)
    let radius : CGFloat = 80
    path.addArc(withCenter: center, radius: radius, startAngle: 0, endAngle: CGFloat.pi*2, clockwise: true)
    path.lineWidth = 5
    UIColor.red.setStroke()
    path.stroke()
}
s.drawBezierPath()
myView.backgroundColor = UIColor.clear

class Shape {
    var name : String?
    var origin : CGPoint?
    var lineColor : UIColor? = UIColor.red
    var fillColor : UIColor? = UIColor.green
    var lineWidth : CGFloat? = 5
    init(name : String, origin : CGPoint) {
        self.name = name
        self.origin = origin
    }
    convenience init(origin : CGPoint) {
        self.init(name:"Shape Bassclass", origin: origin)
    }
    func drawBezierPath() {
        print("Draw \(name!)")
    }
}
class Line : Shape {
    var start : CGPoint?
    var end : CGPoint?
    init(name: String, origin: CGPoint, start: CGPoint, end : CGPoint) {
        super.init(name: name, origin: origin)
        self.start = start
        self.end = end
    }
    convenience init(start : CGPoint, end : CGPoint) {
        self.init(name: "Line", origin: start, start: start, end: end)
    }
    override func drawBezierPath(){
        print("Draw \(name!)")
        let path = UIBezierPath()
        path.move(to: start!)
        path.addLine(to: end!)
        path.lineWidth = lineWidth!
        path.lineCapStyle = .round
        lineColor?.setStroke()
        path.stroke()
    }
}

class Rectangle :Shape {
 // 左上角采用基类 Shape 中的属性 origin
 // 宽度和高度,一般可以采用 CGSize 
  var size :CGsize?
  // 构造器
  init(name: String, origin: CGPoint ,size : CGSize){
  super.init(name: name, origin: origin) 
  self.size = size
  }
  convenience init(origin: CGPoint , size : CGSize) {
  self.init(name: "Rectangle", origin: origin, size: size)
  }
  // 重载 drawBezierPath方法
  override func drawBezierPath(){
  // 向控制台输出信息
  print ("Draw \(name!)")
  //建立一个 UIBezierPath 实例对象
  let path = UIBezierPath(rect: CGRect(origin: origin!,size: size!)
  //设置实例 path 的线条宽度
  path.linewidth m linewidth!
  // 设置实例 path 的线条颜色 
 lineColor?.setStroke()
  // 画出线条
  path.stroke()
 }
}

class Rectangle : Shape {
//左上角采用基类 Shape 中的属性 origin
//宽度和高度,一般可以采用 CGSize 
  var size : cgsize?
  //圆角的大小
  var corner : cgfloat?
  //构造器
  init(name: String, origin: CGPoint , size :CGSize , corner :CGFloat) {
    super.init(name: name, origin: origin) seli.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 实例对象
let path = UIBezierPath(roundedRect: CGRect(origin: origin!, size:
size!), cornerRadius: corner!)
// 设置实例 path 的线条宽度
path.linewidth = linewidth!// 设置实例 path 的线条颜色 lineColor?.setstroke()// 画出线条
path.stroke()
}
}

调用代码如下:
let myRect - Rectangle(origin: start, size: CGSize(width: 150, height:100),corner:8.0)
则会生成一个带圆角的矩形。如果调用方法如下:
let myRect - Rectangle(origin: start, size: CGSize(width: 150, height:100))

class circle :Shape {
//圆心坐标
var center : CGPoint?
// 半径长度
var raduis : cgfloat?
//椭圆的宽度和高度,一般可以采用 CGsize  
var size : cGsize?
//构造器
init(name: String, origin: CGPoint, center : CGPoint, raduis : CGFloat,
size : CGSize){
super.init(name: name, origin: origin) 
    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/Ellipse", origin: CGPoint(x:x,y:y), center:center, raduis: 0, size: size)
}
// 重载 drawBezierPath 方法
override func drawBezierPath(){
//向控制台输出信息
print ("Draw \(name!)")
// 建立一个 UIBezierPath 实例对象
let path = UIBezierPath(ovalIn: CGRect(origin: origin!, size:size!))
//设置实例 path 的线条宽度
path.linewidth = lineWidth!
//设置实例path 的线条颜色 
lineColor?.setstroke()
// 画出线条
path.stroke()
}
}

class Polygons : Shape {
//多边形主要是通过多个顶点相互连接来绘图// 顶点数组
var points : Array<cGPoint>?

init(name: String, origin: CGPoint, points : Array<cGPoint> ) {
super.init(name: name, origin: origin) 
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 实例对象 
let 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 : cfloat?
//构造器
hit(name: String, origin: CGPoint,center : CGPoint, radius : CGFloat,ange
:CGFloat ){
super.init(name: name, origin: origin) 
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(){
// 调用贝塞尔曲线函数 UIBezierPath()
 let 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: p1)
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)*angle+xzAngle)*radius! 
path.addLine(to: CGPoint(x: x,y: y))
}
path.close()
// 线条宽度
path.linewidth = lineWidth!
// 线条颜色为 red 红色
lineColor?.setstroke()
// 画出这个圆 
path.stroke()
}

// ViewController.swift 
// GeometryBand 
// 
// Created by Li Tao on 2023/6/2.
// Copyright  2023 年 Li Tao  . 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?
    ar 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: 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 m lineWidth!
        //设置实例 path 的线条终端样式,round 或者.square 
        path?.lineCapStyle =.round
        //设置实例path的线条颜色
        lineColor?.setstroke()
        //画出线条
        path?.stroke()
    }
}
class Rectangle : Shape {
    // 左上角采用基类 Shape 中的属性 origin
    //宽度和高度,一般可以采用 CGSize 
    var size : cgsize?
    //圆角的大小
    var corner : cgfloat?
    //构造器
    init(name: String, origin: CGPoint, size : GSize, corner : CGFloat,soundrile :String - "LA.m4a") {
        super.init(name: name, origin: origin,noundfileisoundfile) 
        self.sire -size
        self.corner - corner
    }
    convenience init(origin: capoint, size : cGSize, corner : CGFloat - 0) {
        self.init(name: "Pectangle", 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 : CGFloat, size :GSize, soundFile :String - "MI.m4a") {
        super,init(name: name, origin: origin,soundfile:soundfile) 
        self.centers center 
        self.raduis m 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 xm center.x- size.width/2 
    let y-center.y- size.height/2
    self.init (name:"Oval/Ellipse", origin: CGPoint(xix,y:y), centertcenter, 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; o, y: 0)
        self.initiname:"Error", origin: origin, points: points)
        }
    }
    //重载 drawBezierPath 方法画多边形 
    override fune 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?
    //构造器
    init(name: String, origin: CGPoint, center : OGPoint, radius : CGFloat,angel CGFloat,soundFile : String ="so.m4a") {
        super.init(name: name, origin: origin,soundfile: soundFile) 
        self.centerm center 
        self.radius = radius 
        self.angel = angel
    }
   convenience init(center :CGPoint, radius : CGFloat,angel : CGFloat=0){
       let x = center.x- radius 
       let ym 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() 
        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(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]= [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>= []
    // 重载 UIView 的draw 方法
    override func draw(_ rect; cGRect) {
        // 调用 shapes 这个数组中的每个实例的方法 
        for s in shapes {
            s.drawBezierPath()
        }
    }
    // 增加实例到数组 shapes 中 
    func add(shape : Shape){
        shapes.append(shape)
        //触提事件
        override fune touchesBegan! touchest 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 anib.
         // 此处调用 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)
    }
}