Translucent hole with center text in PieChartView - ios-charts

How to create a translucent hole and show center text together?I want to draw an entire translucent hole instead of a part. At the same time, I need to draw the center text
Charts
I have tried to show translucent hole using follow
// draw the hole
chartView.drawHoleEnabled = true
chartView.holeRadiusPercent = 0
chartView.transparentCircleRadiusPercent = 0.382
chartView.transparentCircleColor = UIColor(red: 0.7, green: 0.7, blue: 0.7, alpha: 0.5)
// draw the center text
chartView.drawCenterTextEnabled = true
chartView.centerText = "SUM of\n3,909.00"
but when set the holeRadiusPercent is zero, the center text would not draw in the hole
how could i do it?

Related

How to use alpha component in gradient colors with GKNoise and SKTexture?

I'm using GKNoise with a gradient map to generate color noise, getting a CGImage via SKTexture, on Mac OS. In particular I'm using a GKPerlinNoiseSource and setting two gradient colors, at values -1.0 and 1.0.
It works as expected if the two colors are opaque. If one or both colors has an alpha component less than 1.0, I expect the output to have transparency. However, it looks to me like the alpha is completely ignored in GKNoise's gradient color input (treated as if it's always 1.0) - or, if not ignored there, ignored in the SKTexture rendering of the image output.
I have found a couple of SO questions which reference limitations with SKTexture in other uses, including a possible workaround with SKView rendering, however that doesn't apply here because I'm only using an SKTexture instance to get a CGImage (not using SKView or otherwise using anything from SpriteKit) - and FWIW those questions focus on iOS. For reference:
Export SKTexture to a UIImage with alpha channel
SKSpriteNode created from SKTexture(data:size:) issues with Alpha (Opacity)
I'm looking for ideas on how to make alpha components in the gradient colors work using GKNoise/SKTexture.
Below is the test output image, and the code that reproduces it. In the view, both CGImages draw identically; I expect the one drawn with the red alpha=0.5 to be darker in the red parts when the background is black, lighter when it's white, etc.
import Foundation
import GameplayKit
class GKNoiseGradientIssue {
var redColor_opaque = NSColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0)
var redColor_halfAlpha = NSColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 0.5)
var blueColor_opaque = NSColor(red: 0.0, green: 0.0, blue: 1.0, alpha: 1.0)
var opaqueImage: CGImage
var halfAlphaImage: CGImage
init() {
let noiseSource = GKPerlinNoiseSource(frequency: 0.15,
octaveCount: 7,
persistence: 1.25,
lacunarity: 0.5,
seed: 12345)
let opaqueGradient: [NSNumber: NSColor] = [-1.0: redColor_opaque, 1.0: blueColor_opaque]
let opaqueNoise = GKNoise(noiseSource, gradientColors: opaqueGradient)
let opaqueNoiseMap = GKNoiseMap(opaqueNoise,
size: [200.0, 200.0],
origin: [0.0, 0.0],
sampleCount: [200, 200],
seamless: true)
let opaqueTexture = SKTexture(noiseMap: opaqueNoiseMap)
self.opaqueImage = opaqueTexture.cgImage()
let halfAlphaGradient: [NSNumber: NSColor] = [-1.0: redColor_halfAlpha, 1.0: blueColor_opaque]
let halfAlphaNoise = GKNoise(noiseSource, gradientColors: halfAlphaGradient)
let halfAlphaNoiseMap = GKNoiseMap(halfAlphaNoise,
size: [200.0, 200.0],
origin: [0.0, 0.0],
sampleCount: [200, 200],
seamless: true)
let halfAlphaTexture = SKTexture(noiseMap: halfAlphaNoiseMap)
self.halfAlphaImage = halfAlphaTexture.cgImage()
}
}
class GradientIssueView: NSView {
var issue: GKNoiseGradientIssue?
override func awakeFromNib() {
self.issue = GKNoiseGradientIssue()
}
override func draw(_ dirtyRect: NSRect) {
NSColor.black.setFill()
self.bounds.fill()
if let cgc = NSGraphicsContext.current?.cgContext {
cgc.draw(self.issue!.opaqueImage,
in: CGRect(origin: CGPoint(x: 10.0, y: 10.0),
size: CGSize(width: 200.0, height: 200.0)))
cgc.draw(self.issue!.halfAlphaImage,
in: CGRect(origin: CGPoint(x: 10.0, y: 220.0),
size: CGSize(width: 200.0, height: 200.0)))
}
}
}
Just following up here, for anyone else who might encounter this... While I never got a definitive reply from Apple Developer forums I did come to the conclusion that SKTexture + GKNoise only supports opaque colors, so the question as asked has no answer: one can't do this with SKTexture. Instead, I updated my approach to just use GKNoiseMap directly and calculate my own gradients.
An advantage of this approach is that I can also now create gradients from a noise source using more than two colors. I also have more options for creatively skewing or clamping the noise values before they're converted to colors.
To use GKNoiseMap directly instead of with the two-color gradients and SKTexture approach, create the noise with no reference to gradient colors, and create the GKNoiseMap the same way:
let myNoise = GKNoise(noiseSource)
let noiseMap = GKNoiseMap(myNoise,
size: [myModelWidth, myModelHeight],
origin: [myX, myY],
sampleCount: [myPointWidth, myPointHeight],
seamless: true)
Then when rendering, just call the noiseMap value() method to get the noise value for each point in your view or image output, and then calculate your own color gradient for that point including the alpha (if desired). Note that voronoi noise will be between 0.0 and 1.0 while other perlin-based noise will be between -1.0 and 1.0; to simplify here I'll assume one just wants a gradient between two colors at 0.0 and 1.0.
Given two colors in .deviceRGB color space (rgbColor1 and rgbColor2), and the noise value unitNoiseValue as a CGFloat,
let r_range = rgbColor2.redComponent - rgbColor1.redComponent
let g_range = rgbColor2.greenComponent - rgbColor1.greenComponent
let b_range = rgbColor2.blueComponent - rgbColor1.blueComponent
let a_range = rgbColor2.alphaComponent - rgbColor1.alphaComponent
let r = noiseUnitValue * r_range + rgbColor1.redComponent
let g = noiseUnitValue * g_range + rgbColor1.greenComponent
let b = noiseUnitValue * b_range + rgbColor1.blueComponent
let a = noiseUnitValue * a_range + rgbColor2.alphaComponent
return NSColor(red: r, green: g, blue: b, alpha: a)
In order to make this performant it may be helpful to limit the discrete levels of each gradient (e.g. 256 levels), and to cache calculated colors for large images and store in a hash that can be looked up quickly, and similar techniques. Also, because the conversion here just maps a unit value, you can have other skewing of your noise value if desired before calculation of the gradient color, such as additional fade or normalization or other 'shaping' of the input value.

Use GMSCircle as hole of a polygon instead of GMSPath

I have a polygon shape with a square hole punched out, I've been fiddling with trying to do the same but with a circle, GMSCircle, but haven't had any luck.
Would anyone know the proper way to do it?
Here is my current code block for the polygon hole.
let polygon = GMSPolygon()
polygon.path = GMSPath(path: northAmericaPolygon)
polygon.holes = [GMSPath(path: sanFranciscoHole)]
polygon.fillColor = UIColor(displayP3Red: 255, green: 0, blue: 0, alpha: 0.2)
polygon.strokeColor = .black
polygon.strokeWidth = 2
polygon.map = mapView

How do you fade the bottom of an image into the background? [duplicate]

I've read examples around here but I cannot do it the way I desire, somehow my gradient examples are stuck on the middle of the screen, not working as expected.
I have a UICollectionView which fills the whole screen with vertical scroll.
I want the top and bottom of the UICollectionView to be black and the middle to be transparent (since I'm using a black blackgroundColor).
I tried to apply gradients, but somehow I'm failing to accomplish what I want.
Here's my code:
let gradient = CAGradientLayer()
gradient.frame = view.bounds
gradient.colors = [UIColor.black.cgColor, UIColor.clear.cgColor, UIColor.black.cgColor]
gradient.startPoint = CGPoint(x: 1, y: 0)
gradient.endPoint = CGPoint(x: 1, y: 1)
view.layer.mask = gradient
The code above is placing the gradient in the middle of the screen but inverted. It is transparent on top and bottom of the screen and the middle section if fading to complete black.
I'm trying to create something like this:
Thanks for helping
You can achieve that by changing your color line with this:
gradient.colors = [
UIColor(white: 1.0, alpha: 0).cgColor,
UIColor(white: 1.0, alpha: 1).cgColor,
UIColor(white: 1.0, alpha: 0).cgColor
]
Or if you want to have even more control over your gradient, you can also use the code below and play around with the location and/or color alpha values:
let gradient = CAGradientLayer()
gradient.frame = view.bounds
gradient.colors = [
UIColor(white: 1, alpha: 0).cgColor,
UIColor(white: 1, alpha: 1).cgColor,
UIColor(white: 1, alpha: 1).cgColor,
UIColor(white: 1, alpha: 0).cgColor
]
gradient.locations = [0, 0.4, 0.6, 1]
view.layer.mask = gradient
Reason of this from the documentation;
An optional layer whose alpha channel is used to mask the layer’s content.
The layer’s alpha channel determines how much of the layer’s content and background shows through. Fully or partially opaque pixels allow the underlying content to show through but fully transparent pixels block that content.

Blend Mode between NSWindow and CAShapeLayer

I'm trying to make a semi-transparent window (white), and have a view that sits over the top of it to make it appear clear again.
Essentially, it looks like:
And what I want it to look like is:
My window is defined like:
window!.alphaValue = 0;
// Set level to screensaver level
window!.level = 1000
window!.backgroundColor = NSColor.white;
window!.animator().alphaValue = 0.5;
A white window with 50% opacity. The view on top contains a single CAShapeLayer. This layer is defined like:
shapeLayer = CAShapeLayer();
shapeLayer!.lineWidth = 1.0;
shapeLayer!.strokeColor = NSColor(red: 0.5, green: 0.5, blue: 0.5, alpha: 1).cgColor;
shapeLayer!.fillColor = NSColor(red: 0, green: 0, blue: 0, alpha: 0.5).cgColor;
This window is movable by the user, so I need some kind of dynamic way to clear the contents of the main window and show through to whatever is underneath (the desktop, another application, etc)

How to fill color outside the circle on google map using Swift?

I want the red circle just have the border (no red in centre) and have the rest outside the circle darkened?
I have a issue about that. Could you help me solve it?
With google maps for this, you should do the following steps
Create a GMSCircle object
Set stroke color and fill color for the
circle
Set map for the circle object
Example code:
let circleCenter = CLLocationCoordinate2DMake(9.931233, 76.267303)//change to your center point
let circ = GMSCircle(position: circleCenter, radius: 5000)//radius in meters
circ.fillColor = UIColor(red: 0.35, green: 0, blue: 0, alpha: 0.05)
circ.strokeColor = UIColor.redColor()
circ.strokeWidth = 1
circ.map = mapView //your map view in the UI