Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Balloon Custom View
//
// BalloonView.swift
// balloonTest
//
// Created by Daiki Ito on 2017/05/27.
// Copyright © 2017年 EAssistant. All rights reserved.
//
import UIKit
class BalloonView: UIView {
var color: CGColor = UIColor.black.cgColor
var squareRect: CGRect = CGRect(x: 100, y: 300, width: 120, height: 100)
var triApexPoint = CGPoint(x: 100, y: 250)
var curveSize: CGFloat = 20
private var arrSquarePoint = [CGPoint]()
private var centerPoint = CGPoint()
var textLabel = UILabel()
var halfBaseLength: CGFloat = 10
var imageView = UIImageView()
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {
let size = self.frame.size
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
guard let context = UIGraphicsGetCurrentContext() else {return}
let image = contextBalloon(context: context, squareRect: squareRect, triApexRect: triApexPoint, color: color, curve: curveSize)
imageView.frame = self.frame
imageView.image = image
self.addSubview(imageView)
setTextLabel();
}
func removeImageView(){
imageView.removeFromSuperview()
}
override func layerWillDraw(_ layer: CALayer) {
self.backgroundColor = UIColor.clear
}
private func setTextLabel(){
textLabel.sizeToFit()
textLabel.center = centerPoint
self.addSubview(textLabel)
}
private func contextBalloon(context: CGContext, squareRect: CGRect, triApexRect: CGPoint, color: CGColor, curve: CGFloat)-> UIImage{
context.setLineWidth(1)
context.setFillColor(color)
//Write Square
//context.beginPath()
let controlPoint_1 = CGPoint(x: squareRect.origin.x, y: squareRect.origin.y)
let controlPoint_2 = CGPoint(x: squareRect.origin.x, y:squareRect.origin.y + squareRect.height)
let controlPoint_3 = CGPoint(x: squareRect.origin.x + squareRect.width, y: squareRect.origin.y + squareRect.height)
let controlPoint_4 = CGPoint(x: squareRect.origin.x + squareRect.width, y: squareRect.origin.y)
let squareMoveToPoint_A1 = CGPoint(x: squareRect.origin.x, y: squareRect.origin.y + curve)
let squareAddLineToPoint_A2 = CGPoint(x: squareRect.origin.x, y: squareRect.origin.y + squareRect.height - curve)
let squareAddLineToPoint_B3 = CGPoint(x: squareRect.origin.x + curve, y: squareRect.origin.y + squareRect.height)
let squareAddLineToPoint_B4 = CGPoint(x: squareRect.origin.x + squareRect.width - curve, y: squareRect.origin.y + squareRect.height)
let squareAddLineToPoint_C5 = CGPoint(x: squareRect.origin.x + squareRect.width, y: squareRect.origin.y + squareRect.height - curve)
let squareAddLineToPoint_C6 = CGPoint(x: squareRect.origin.x + squareRect.width, y: squareRect.origin.y + curve)
let squareAddLineToPoint_D7 = CGPoint(x: squareRect.origin.x + squareRect.width - curve, y: squareRect.origin.y)
let squareAddLineToPoint_D8 = CGPoint(x: squareRect.origin.x + curve, y: squareRect.origin.y)
context.move(to: squareMoveToPoint_A1)
context.addLine(to: squareAddLineToPoint_A2)
context.addQuadCurve(to: squareAddLineToPoint_B3, control: controlPoint_2)
context.addLine(to: squareAddLineToPoint_B4)
context.addQuadCurve(to: squareAddLineToPoint_C5, control: controlPoint_3)
context.addLine(to: squareAddLineToPoint_C6)
context.addQuadCurve(to: squareAddLineToPoint_D7, control: controlPoint_4)
context.addLine(to: squareAddLineToPoint_D8)
context.addQuadCurve(to: squareMoveToPoint_A1, control: controlPoint_1)
context.closePath()
context.fillPath()
// Write triangle
context.beginPath()
arrSquarePoint = [controlPoint_1, controlPoint_2, controlPoint_3, controlPoint_4]
let resultPoints = triangle(arrSquarePoint: arrSquarePoint, apex: triApexRect)
context.move(to: triApexRect)
context.addLine(to: resultPoints[0])
context.addLine(to: resultPoints[1])
context.addLine(to: triApexRect)
context.closePath()
context.fillPath()
context.strokePath()
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
private func triangle(arrSquarePoint: [CGPoint], apex: CGPoint)-> [CGPoint]{
centerPoint = center(arrSquarePoint: arrSquarePoint)
let alpha = atan((apex.y - centerPoint.y) / (apex.x - centerPoint.x)) - CGFloat.pi/2
let basePointX_1 = halfBaseLength * cos(alpha) + centerPoint.x
let basePointY_1 = halfBaseLength * sin(alpha) + centerPoint.y
let basePoint_1 = CGPoint(x: basePointX_1, y: basePointY_1)
let basePointX_2 = halfBaseLength * cos(CGFloat.pi + alpha) + centerPoint.x
let basePointY_2 = halfBaseLength * sin(CGFloat.pi + alpha) + centerPoint.y
let basePoint_2 = CGPoint(x: basePointX_2, y: basePointY_2)
let resultPoints = [basePoint_1, basePoint_2]
return resultPoints
}
private func center(arrSquarePoint: [CGPoint])-> CGPoint{
let A = (arrSquarePoint[0].y - arrSquarePoint[2].y) / (arrSquarePoint[0].x - arrSquarePoint[2].x)
let B = (arrSquarePoint[1].y - arrSquarePoint[3].y) / (arrSquarePoint[1].x - arrSquarePoint[3].x)
let centerX = (B*arrSquarePoint[1].x - A*arrSquarePoint[0].x + arrSquarePoint[0].y - arrSquarePoint[1].y)/(B - A)
let centerY = A*(centerX - arrSquarePoint[0].x) + arrSquarePoint[0].y
let resultPoint = CGPoint(x: centerX, y: centerY)
return resultPoint
}
func slant(point1: CGPoint, point2: CGPoint)-> Float{
let absX = fabs(point1.x - point2.x)
let absY = fabs(point1.y - point1.y)
let powX = powf(Float(absX), 2)
let powY = powf(Float(absY), 2)
let length = sqrtf(powX + powY)
return length
}
}
import UIKit
class ViewController: UIViewController {
let balloonView = BalloonView()
let squareRect = CGRect(x: 150, y: 300, width: 100, height: 100)
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading tvarview, typically from a nib.
balloonView.frame = self.view.frame
balloonView.textLabel.text = ""
balloonView.color = UIColor.gray.cgColor
balloonView.textLabel.textColor = UIColor.white
balloonView.halfBaseLength = 20
balloonView.squareRect = squareRect
balloonView.triApexPoint = CGPoint(x: 150, y: 100)
self.view.addSubview(balloonView)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
let location = touch?.location(in: self.view)
balloonView.triApexPoint = location!
balloonView.removeImageView()
balloonView.draw(self.view.frame)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment