i am developing an image edittor app for IOS.How can i add an eraser option? - ios

Currently i am adding the changes as subview to the original image. I want to add an eraser tool so that when the user draws on the screen, the subviews will be cleared and the underlined image will be seen . Same as an eraser tool in "Paint".Below is the code used for drawing a rectangle.How can i add an eraser tool using the same method. Thank you
case 2:
let path = UIBezierPath()
let sh = CAShapeLayer()
sh.strokeColor = selectedcolor.cgColor
sh.lineWidth = 3
sh.fillColor = UIColor.clear.cgColor
tempImage.layer.sublayers?.removeAll()
sh.fillColor = UIColor.clear.cgColor
path.move(to: startPoint)
sh.path = UIBezierPath(rect: rect).cgPath
tempImage.layer.addSublayer(sh)
if usermoving == 0
{
sh.setValue(tag, forKey: "tag")
mainImage.layer.addSublayer(sh)
}
break

Its Objective C Code
If you are using an image as background then you can set the same image as brush pattern to draw the bezierpath it will virtually give you the eraser effect.
Swift:-
UIColor(patternImage: UIImage(named: "background.png"))

Related

Swift ios cut out rounded rect from view allowing colour changes

I'm using this approach to cut out a rounded rect "window" from a background view:
override func draw(_ rect: CGRect) {
guard let rectsArray = rectsArray else {
return
}
for holeRect in rectsArray {
let holeRectIntersection = rect.intersection(holeRect)
if let context = UIGraphicsGetCurrentContext() {
let roundedWindow = UIBezierPath(roundedRect: holeRect, cornerRadius: 15.0)
if holeRectIntersection.intersects(rect) {
context.addPath(roundedWindow.cgPath)
context.clip()
context.clear(holeRectIntersection)
context.setFillColor(UIColor.clear.cgColor)
context.fill(holeRectIntersection)
}
}
}
}
In layoutSubviews() I update the background colour add my "window frame" rect:
override func layoutSubviews() {
super.layoutSubviews()
backgroundColor = self.baseMoodColour
isOpaque = false
self.rectsArray?.removeAll()
self.rectsArray = [dragAreaView.frame]
}
I'm adding the rect here because layoutSubviews() updates the size of the "window frame" (i.e., the rect changes after layoutSubviews() runs).
The basic mechanism works as expected, however, if I change the background colour, the cutout window fills with black. So I'm wondering how I can animate a background colour change with this kind of setup? That is, I want to animate the colour of the area outside the cutout window (the window remains clear).
I've tried updating backgroundColor directly, and also using didSet in the accessor of a custom colour variable in my UIView subclass, but both cause the same filling-in of the "window".
var baseMoodColour: UIColor {
didSet {
self.backgroundColor = baseMoodColour
self.setNeedsDisplay()
}
}
Try to use UIView.animate, you can check it here
UIView.animate(withDuration: 1.0, delay: 0.0, options: [.curveEaseOut], animations: {
self.backgroundColor = someNewColour
//Generally
//myView.backgroundColor = someNewColor
}, nil)
The problem in the short run is that that is simply what clear does if the background color is opaque. Just give your background color some transparency — even a tiny bit of transparency, so tiny that the human eye cannot perceive it — and now clear will cut a hole in the view.
For example, your code works fine if you set the view's background color to UIColor.green.withAlphaComponent(0.99).
By the way, you should delete the lines about UIColor.clear; that's a red herring. You should also cut the lines about the backgroundColor; you should not be repainting the background color into your context. They are two different things.
The problem in the long run is that what you're doing is not how to punch a hole in a view. You should be using a mask instead. That's the only way you're going to get the animation while maintaining the hole.
Answering my own question, based on #matt's suggestion (and linked example), I did it with a CAShapeLayer. There was an extra "hitch" in my requirements, since I have a couple of views on top of the one I needed to mask out. So, I did the masking like this:
func cutOutWindow() {
// maskedBackgroundView is an additional view, inserted ONLY for the mask
let r = self.maskedBackgroundView.bounds
// Adjust frame for dragAreaView's border
var dragSize = self.dragAreaView.frame.size
var dragPosition = self.dragAreaView.frame.origin
dragSize.width -= 6.0
dragSize.height -= 6.0
dragPosition.x += 3.0
dragPosition.y += 3.0
let r2 = CGRect(x: dragPosition.x, y: dragPosition.y, width: dragSize.width, height: dragSize.height)
let roundedWindow = UIBezierPath(roundedRect: r2, cornerRadius: 15.0)
let mask = CAShapeLayer()
let path = CGMutablePath()
path.addPath(roundedWindow.cgPath)
path.addRect(r)
mask.path = path
mask.fillRule = kCAFillRuleEvenOdd
self.maskedBackgroundView.layer.mask = mask
}
Then I had to apply the colour change to maskedBackgroundView.layer.backgroundColor (i.e., to the layer, not the view). With that in place, I get the cutout I need, with animatable colour changes. Thanks #matt for pointing me in the right direction.

ios swift create rounded profile image like twitter, instagram,

I would like to create a very simple image editor, same as twitter (for the profile image)
I know how to pinch or move an image.
But i don’t know how to create the "circle layer" and just keep this part of the image, like this :
Make sure to import QuarzCore.
func maskRoundedImage(image: UIImage, radius: CGFloat) -> UIImage {
let imgView: UIImageView = UIImageView(image: image)
let layer = imgView.layer
layer.masksToBounds = true
layer.cornerRadius = radius
UIGraphicsBeginImageContext(imgView.bounds.size)
layer.render(in: UIGraphicsGetCurrentContext()!)
let roundedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return roundedImage!
}
https://github.com/andreaantonioni/AAPhotoCircleCrop
Each view has an underlying layer onto which you apply a corner radius. Then you must apply clipToBounds on that layer in order to apply that mask to the overlying UIView. The corner radius must be half the width of the view in order to get a circle effect. Otherwise the corners of the view will be rounded.
For example:
let square = UIView()
square.center = view.center
square.bounds.size = CGSize(width: 100, height: 100)
square.backgroundColor = .red
view.addSubview(square)
square.layer.cornerRadius = 50
square.clipsToBounds = true
Above mentioned ways are good, But you can not achieved exact output as in above image E.g You can not get alpha effect.
I suggest simple way to do it.
1) Add new image to project with transparent background with Opocity and circle.
2) Add new imageView above to mainview as below.
let image = UIImageView(frame: view.bounds)
mage.image = UIImage.init(named:"imageName")
view.addSubview(image)
Then output should be as per your requirement.

Filing UIBezierPath in Swift

How can I color the inside of the UIBezier path? I am making a simple triangle and want to color inside of the triangle with red color.
class GraphView : UIView {
override func drawRect(rect: CGRect) {
UIColor.redColor().setFill()
UIColor.greenColor().setStroke()
let path = UIBezierPath(rect: rect)
path.moveToPoint(CGPointMake(100,620))
path.addLineToPoint(CGPointMake(300,100))
path.addLineToPoint(CGPointMake(500,620))
path.addLineToPoint(CGPointMake(100,620))
path.closePath()
path.fill()
path.stroke()
}
}
let graphView = GraphView(frame: CGRectMake(0,0,960,640))
XCPlaygroundPage.currentPage.liveView = graphView
The above code is written in the playground: Here is the result:
The problem is with how you're creating your UIBezierPath. You're creating it with a rectangle of the view's bounds, and then adding a triangle inside that rectangle. Therefore they're both getting filled – resulting in the entire view being red.
If you set usesEvenOddFillRule to true, you'll better see the result of the unwanted rectangle in your path:
If you just want to fill a triangle then replace this line:
let path = UIBezierPath(rect: rect)
with this:
let path = UIBezierPath()
This will create a new empty UIBezierPath that you can add your triangle to.

How can UIVisualEffectView be used inside of a circle?

I'm making a custom control circle. Part of the circle may be transparent. It would make more visual sense and look better if it was translucent instead of transparent.
Because views are rectangular, and I only want the circle to be translucent, not the rest of the rectangle, this is a problem.
The UIVisualEffectView is behind the custom control.
(Without anything rendered inside of the circle for debugging purposes)
As you can see, the view is blurring things outside of the circle.
I don't know how to blur inside only the view, and the prerelease documentation is practically empty. My only thought is to create many 1x1 views to cover the circle, but this seems like it would not really work, and even if it did it would be a slow and ugly solution. How can I blur the content inside the view, without blurring anything outside it?
Set the circle view's layer mask to a filled circle:
CircleControlView *circleView = yourCircleView();
CAShapeLayer *mask = [CAShapeLayer layer];
mask.path = [UIBezierPath bezierPathWithOvalInRect:circleView.bounds].CGPath;
circleView.layer.mask = mask;
UPDATE
Swift playground example:
import UIKit
import XCPlayground
import QuartzCore
UIGraphicsBeginImageContext(CGSize(width: 100, height: 100))
let viewPath = UIBezierPath(ovalInRect:CGRect(x:1,y:1,width:98,height:98))
viewPath.lineWidth = 2
viewPath.stroke()
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let view = UIView(frame:CGRect(x:0,y:0,width:100,height:100))
XCPShowView("view", view)
let label = UILabel(frame:view.bounds)
label.text = "This is the text in the background behind the circle."
label.numberOfLines = 0
view.addSubview(label)
let effectView = UIVisualEffectView(effect:UIBlurEffect(style:.ExtraLight))
effectView.frame = view.bounds
view.addSubview(effectView)
let circleView = UIImageView(image:image)
effectView.addSubview(circleView)
let maskPath = UIBezierPath(ovalInRect:circleView.bounds)
let mask = CAShapeLayer()
mask.path = maskPath.CGPath
effectView.layer.mask = mask
Result:

How to draw horizontal bar graphs without showing axises

I need to implement a horizontal bar graph similar to the one shown below. Here I don't need to show axises along with the graph, still I need to imagine there is one:
How can I achieve this?
You can easily do this by using
UIBezierPath with CAShapeLayer
You can use the following function to draw an horizontal bar
func drawLine(startpoint start:CGPoint, endpint end:CGPoint, linecolor color: CGColor , linewidth widthline:CGFloat){
var path = UIBezierPath()
path.moveToPoint(start)
path.addLineToPoint(end)
var shapeLayer = CAShapeLayer()
shapeLayer.path = path.CGPath
shapeLayer.strokeColor = color
shapeLayer.lineWidth = widthline
view.layer.addSublayer(shapeLayer)
}
How to call this function in swift is
let start = CGPoint(x:20,y:100)
let end = CGPoint(x:200,y:100)
//red part of line
drawLine(startpoint: start, endpint: end,linecolor: UIColor.redColor().CGColor,linewidth:11.0)
You can find out complete code in here
http://bestarticlesall.blogspot.com/2014/12/draw-horizontal-bar-chart-using-swift.html

Resources