Magnifying glass UIView - ios

Trying to add a magnifying-glass effect to a uiview, but the magnfifying glass is always black.
My code for the Magnifing glass view:
public override func draw(_ rect: CGRect) {
let context = UIGraphicsGetCurrentContext()!
context.translateBy(x: self.frame.size.width/2, y: self.frame.size.height/2)
context.scaleBy(x: self.scale, y: self.scale)
self.viewToMagnify.layer.render(in: context)
}
And in the View-to-Magnify:
self.magnifiedView = MagnifiedView.init(frame: CGRect(x: 200, y: 100, width: 100, height: 100))
self.magnifiedView.viewToMagnify = self.view
self.view.addSubview(magnifiedView)
Edit:
I want to use it in an ARSession on the camera output. The code above works fine for a UIImageView. Updating the View of the camera output in real-time seems to make some problems.

Related

How to add class UIView in addSubview

I have a code that draws an ellipse, but it's in a separate class that inherits from UIView
class DRAW: UIView {
override func draw(_ rect: CGRect) {
var path = UIBezierPath()
path = UIBezierPath(ovalIn: CGRect(x: 36.62, y: 77.54, width: 303.19, height: 495.93))
UIColor.green.setFill()
path.stroke()
path.fill()
}
}
If I try to add it via addSubview(), then it is not on the screen, and if I give it the dimensions, then a black crawl for the entire display and only in the middle is the ellipse I need.
view.addSubview(DRAW.init(CGRect(x: 36.62, y: 77.54, width: 303.19, height: 495.93)))
How do I display only an ellipse without a black square. I would be grateful for your help
You can just simply set the clear background color of your view
let yourView = DRAW.init(frame: CGRect(x: 36.62, y: 77.54, width: 303.19, height: 495.93))
yourView.backgroundColor = .clear
self.view.addSubview(yourView)

How to draw Custom UIView in ios?

How can I draw custom view as shown in image.
I want to draw a small rectangle in main view.
plaese refer any link if you have.
Image
Thank you
It could be as simple as below
import UIKit
class Rectangle:UIView{
override func draw(_ rect: CGRect) {
let path = UIBezierPath(rect: rect)
path.move(to: CGPoint(x:0,y:rect.height))
path.addLine(to: CGPoint(x:rect.width/2,y:rect.height/1.4))
path.addLine(to: CGPoint(x:rect.width,y:rect.height))
UIColor.red.setStroke()
path.stroke()
}
}
let rect=Rectangle(frame: CGRect(x: 0, y: 0, width: 100, height: 100))

How to draw a sloping oval with UIBezierPath

I wanna draw a sloping oval with UIBezierPath. There is only a method UIBezierPath.init(ovalInRect: rect) to draw a oval without slop.What can I do to draw this? thanks
Here is an example of a rotated oval:
class MyView: UIView {
override func draw(_ rect: CGRect) {
// create oval centered at (0, 0)
let path = UIBezierPath(ovalIn: CGRect(x: -75, y: -50, width: 150, height: 100))
// rotate it 30 degrees
path.apply(CGAffineTransform(rotationAngle: 30 * .pi / 180))
// translate it to where you want it
path.apply(CGAffineTransform(translationX: self.bounds.width / 2, y: self.bounds.height / 2))
// set stroke color
UIColor.blue.setStroke()
// stroke the path
path.stroke()
}
}
let view = MyView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
view.backgroundColor = .white
Here it is running in a Playground:

Updating UIView makes a hash of subview's alignment / Swift

I'm new in Swift. I want to make an app with a moving subview. I'm testing the app, and when i touch down the button, the subview moves with the correct value, but when the parent UIView updates because of changing label, the subview jump back to the origin coordinate what i set up in the storyboard. I use core graphics to draw circle. I want to move the circle on the screen by tap a button. How can i solved this problem?
class ViewController: UIViewController {
#IBOutlet weak var movingItem: MovingItem! /* inheritance from UIView */
#IBAction func move() {
self.movingItem.frame = CGRect(x: movingItem.frame.origin.x + 5.0,
y: movingItem.frame.origin.y,
width: movingItem.frame.width,
height: movingItem.frame.height)
}
override func viewDidLoad() {
self.movingItem.frame = CGRect(x: 0.0, y: 0.0, width: 50.0, height: 50.0)
self.movingItem.setNeedsDisplay()
}
//more code...
}
#IBDesignable
class MovingItem: UIView {
override func drawRect(rect: CGRect) {
var context = UIGraphicsGetCurrentContext()
CGContextBeginPath(context)
var rectForCircle = CGRect(x: 0.0, y: 0.0, width: 50.0, height: 50.0)
CGContextAddEllipseInRect(context, rectForCircle)
UIColor.redColor().setFill()
CGContextDrawPath(context, kCGPathFill)
}
}
Try instead of
var rectForCircle = CGRect(x: 0.0, y: 0.0, width: 50.0, height: 50.0)
CGContextAddEllipseInRect(context, rectForCircle)
like this:
CGContextAddEllipseInRect(context, self.frame)
and insert line
self.movingItem.setNeedsDisplay()
after
self.movingItem.frame = CGRect(x: movingItem.frame.origin.x + 5.0,
y: movingItem.frame.origin.y,
width: movingItem.frame.width,
height: movingItem.frame.height)

Union UIBezierPaths rather than apend path

I have an app where I take a UIBezierPath and use it as a brush by a series of appendPath: calls. After a few goes and with really complex brush shapes the memory runs out and the app grinds to a halt. What I really want to do is a full on union exactly like Paint Code does but I can't find any way of doing this.
How would I go about unioning two or more UIBezierPaths?
EDIT:
Here is a visual of what I want to achieve dynamically.
In Paint Code you take two paths and overlap them like this:
BUT I want to merge / union them into one new single path like:
Note that in the bottom panel of Paint Code there is code for now one single shape and this is what I want to be able to get to programatically with maybe 1000 original paths.
You can get desired result easily by following 2 concepts of Core Graphics :-
i)CGBlendMode
ii)OverLap2Layer
Blend modes tell a context how to apply new content to itself. They determine how pixel data is digitally blended.
class UnionUIBezierPaths : UIView {
var firstBeizerPath:UIImage!
var secondBeizerPath:UIImage!
override func draw(_ rect: CGRect) {
super.draw(rect)
firstBeizerPath = drawOverLapPath(firstBeizerpath: drawCircle(), secondBeizerPath: polygon())
secondBeizerPath = drawOverLapPath(firstBeizerpath: polygon(), secondBeizerPath: drawCircle())
let image = UIImage().overLap2Layer(firstLayer:firstBeizerPath , secondLayer:secondBeizerPath)
}
func drawCircle() -> UIBezierPath {
let path = UIBezierPath(ovalIn: CGRect(x: 40, y: 120, width: 100, height: 100) )
return path
}
func polygon() -> UIBezierPath {
let beizerPath = UIBezierPath()
beizerPath.move(to: CGPoint(x: 100, y: 10) )
beizerPath.addLine(to: CGPoint(x: 200.0, y: 40.0) )
beizerPath.addLine(to: CGPoint(x: 160, y: 140) )
beizerPath.addLine(to: CGPoint(x: 40, y: 140) )
beizerPath.addLine(to: CGPoint(x: 0, y: 40) )
beizerPath.close()
return beizerPath
}
func drawOverLapPath(firstBeizerpath:UIBezierPath ,secondBeizerPath:UIBezierPath ) -> UIImage {
UIGraphicsBeginImageContext(self.frame.size)
let firstpath = firstBeizerpath
UIColor.white.setFill()
UIColor.black.setStroke()
firstpath.stroke()
firstpath.fill()
// sourceAtop = 20
let mode = CGBlendMode(rawValue:20)
UIGraphicsGetCurrentContext()!.setBlendMode(mode!)
let secondPath = secondBeizerPath
UIColor.white.setFill()
UIColor.white.setStroke()
secondPath.fill()
secondPath.stroke()
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
func drawImage(image1:UIImage , secondImage:UIImage ) ->UIImage
{
UIGraphicsBeginImageContext(self.frame.size)
image1.draw(in: CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height) )
secondImage.draw(in: CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height) )
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
}
//OverLap2Layer
extension UIImage {
func overLap2Layer(firstLayer:UIImage , secondLayer:UIImage ) -> UIImage {
UIGraphicsBeginImageContext(firstLayer.size)
firstLayer.draw(in: CGRect(x: 0, y: 0, width: firstLayer.size.width, height: firstLayer.size.height) )
secondLayer.draw(in: CGRect(x: 0, y: 0, width: firstLayer.size.width, height: firstLayer.size.height) )
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
}
First Path :-
Second Path :-
Final Result :-
Reference:-
Blend in Core Graphics ,
Creating Image
GitHub Demo
Finally a solution!!
Using https://github.com/adamwulf/ClippingBezier you can find the intersecting points. Then you can walk through the path, turning left if clockwise or vice-versa to stay on the outside. Then you can generate a new path using the sequence of points.
You can use the GPCPolygon, an Objective-C wrapper for GPC
-GPCPolygonSet*) initWithPolygons:(NSMutableArray*)points;
or
- (GPCPolygonSet*) unionWithPolygonSet:(GPCPolygonSet*)p2;

Resources