Tumgik
#GraphView
cmondary · 2 months
Text
CAPACITIES : L'application mobile
📌 CAPACITIES lance officiellement son application mobile 📱 ! Pour rappel, CAPACITIES est un "clone" de NOTION, mais avec des fonctionnalités supplémentaires, comme par exemple le GraphView d'OBSIDIAN.
https://capacities.io/whats-new/release-39 📌 CAPACITIES lance officiellement son application mobile 📱 !Pour rappel, CAPACITIES est un “clone” de NOTION, mais avec des fonctionnalités supplémentaires, comme par exemple le GraphView d’OBSIDIAN. Vous devez pouvoir prendre des notes en déplacement, accéder à vos notes existantes et savoir que vos notes sont synchronisées de manière transparente sur…
Tumblr media
View On WordPress
0 notes
vyechi · 1 year
Text
💝 Meaningful Connection 2023-M06
Welcome to #meaningful #connection 💝, where I share #resonating ideas, thoughts, and realizations from my month of #June. ✨I covered the following topics #drberg, #fourthDimension, #graphview, #love, #body, #reflections #time and #questions
Welcome to meaningful connection, where I share June resonating ideas, thoughts, and realizations for those who want to grow mindfully in 6 mins. I will try to answer the following questions; let me know how I do. Meanwhile, I left you some bonus thought-provoking questions. What is the significance of Vipassana meditation?  How does the graph view in Obsidian help with the author’s publishing…
Tumblr media
View On WordPress
1 note · View note
volodimirg · 4 years
Link
GraphView - безкоштовна бібліотека з відкритим програмним кодом для побудови лінійних графіків, стовпчикових діаграм, точкових діаграм в Java Android програмах.
0 notes
android-arsenal · 4 years
Text
Aesthetic GraphView
A simple graph library with more control for users.
Take the full control over drawing the path.
Change the gradient (start/end) color
Change the circle color and radius
Change the path color and line thickness
Switch On/Off Gridlines (change the grid line color)
Switch On/Off Graduations (change the graduation text color)
Draw graph with different starting point and from the left border (X0 - coordinate)
Draw graph with exact coordinates given and from left border (and stretch until the end of the screen)
from The Android Arsenal https://ift.tt/3gmg5fe
0 notes
sonibhuju · 6 years
Text
Does Online Privacy Matter?
Have you all ever wondered how much privacy we have online and how much of our information is secure. I installed an add on called lightbeam from firefox to to show both the first and third party sites I interact with on the Web. Lightbeam basically shows the visualization of all the third parties that are active on the page you visited. It displays the relationship between the third party sites and the sites you visited.  I was genuinely shocked when I saw the graph. I had only used only 8 sites but had unknowingly connected with 128 third parties sites. We all use internet everyday but we are still unaware of many thing related to it. Nothing in all the world is more dangerous than sincere ignorance and conscientious stupidity. As a concerned netizen, I ask others to try to learn more and use the lightbeam add on themselves to see how many third parties sites they interact with. I will add the picture of my GraphView down below. Always remember the quote by Richard Cecil: “The first step towards knowledge is to know that we are ignorant." Always be on the pursuit of knowledge and insight.
Tumblr media
0 notes
iyarpage · 7 years
Text
Core Graphics Tutorial Part 2: Gradients and Contexts
Update note: This tutorial has been updated to iOS 11, Swift 4, and Xcode 9 by Andrew Kharchyshyn. The original tutorial was written by Caroline Begbie.
Welcome back to our modern Core Graphics with Swift tutorial series!
In the first part of the tutorial series, you learned about drawing lines and arcs with Core Graphics, and using Xcode’s interactive storyboard features.
In this second part, you’ll delve further into Core Graphics, learning about drawing gradients and manipulating CGContexts with transformations.
Core Graphics
You’re now going to leave the comfortable world of UIKit and enter the underworld of Core Graphics.
This image from Apple describes the relevant frameworks conceptually:
UIKit is the top layer, and it’s also the most approachable. You’ve used UIBezierPath, which is a UIKit wrapper of the Core Graphics CGPath.
The Core Graphics framework is based on the Quartz advanced drawing engine. It provides low-level, lightweight 2D rendering. You can use this framework to handle path-based drawing, transformations, color management, and lots more.
One thing to know about lower layer Core Graphics objects and functions is that they always have the prefix CG, so they are easy to recognize.
Getting Started
By the time you’ve got to the end of this tutorial, you’ll have created a graph view that looks like this:
Before drawing on the graph view, you’ll set it up in the storyboard and create the code that animates the transition to show the graph view.
The complete view hierarchy will look like this:
First, download the starter project. It’s pretty much where you left off in the previous part. The only difference is that in Main.storyboard, CounterView is inside of another view (with a yellow background). Build and run, and this is what you will see:
Go to File\New\File…, choose the iOS\Source\Cocoa Touch Class template and click Next. Enter the name GraphView as the class name, choose the subclass UIView and set the language to Swift. Click Next then Create.
Now in Main.storyboard click the name of the yellow view in the Document Outline slowly twice to rename it, and call it Container View. Drag a new UIView from the object library to inside of Container View, below the Counter View.
Change the class of the new view to GraphView in the Identity Inspector. The only thing left is to add constraints for the new GraphView, similar to how you did it in the previous part of the tutorial:
With the GraphView selected, Control-drag from the center slightly left (still within the view), and choose Width from the popup menu.
Similarly, with the GraphView selected, Control-drag from the center slightly up (still within the view), and choose Height from the popup menu.
Control-drag left from inside the view to outside the view and choose Center Horizontally in Container.
Control-drag up from inside the view to outside the view, and choose Center Vertically in Container.
Edit the constraint constants in the Size Inspector to match these:
Your Document Outline should look like this:
The reason you need a Container View is to make an animated transition between the Counter View and the Graph View.
Go to ViewController.swift and add property outlets for the Container and Graph Views:
@IBOutlet weak var containerView: UIView! @IBOutlet weak var graphView: GraphView!
This creates an outlet for the container view and graph view. Now hook them up to the views you created in the storyboard.
Go back to Main.storyboard and hook up the Graph View and the Container View to the outlets:
Seting up the Animated Transition
Still in Main.storyboard, drag a Tap Gesture Recognizer from the Object Library to the Container View in the Document Outline:
Go to ViewController.swift and add this property to the top of the class:
var isGraphViewShowing = false
This simply marks whether the graph view is currently displayed.
Now add the tap method to do the transition:
@IBAction func counterViewTap(_ gesture: UITapGestureRecognizer?) { if (isGraphViewShowing) { //hide Graph UIView.transition(from: graphView, to: counterView, duration: 1.0, options: [.transitionFlipFromLeft, .showHideTransitionViews], completion:nil) } else { //show Graph UIView.transition(from: counterView, to: graphView, duration: 1.0, options: [.transitionFlipFromRight, .showHideTransitionViews], completion: nil) } isGraphViewShowing = !isGraphViewShowing }
UIView.transition(from:to:duration:options:completion:) performs a horizontal flip transition. Other transitions are cross dissolve, vertical flip and curl up or down. The transition uses .showHideTransitionViews constant, which means you don’t have to remove the view to prevent it from being shown once it is “hidden” in the transition.
Add this code at the end of pushButtonPressed(_:):
if isGraphViewShowing { counterViewTap(nil) }
If the user presses the plus button while the graph is showing, the display will swing back to show the counter.
Lastly, to get this transition working, go back to Main.storyboard and hook up your tap gesture to the newly added counterViewTap(gesture:) method:
Build and run the application. Currently you’ll see the graph view when you start the app. Later on, you’ll set the graph view hidden, so the counter view will appear first. Tap it, and you’ll see the transition flipping.
Analysis of the Graph View
Remember the Painter’s Model from Part 1? It explained that drawing with Core Graphics is done from the back of an image to the front, so you need an order in mind before you code. For Flo’s graph, that would be:
Gradient background view
Clipped gradient under the graph
The graph line
The circles for the graph points
Horizontal graph lines
The graph labels
Drawing a Gradient
You’ll now draw a gradient in the Graph View.
Go to GraphView.swift and replace the code with:
import UIKit @IBDesignable class GraphView: UIView { // 1 @IBInspectable var startColor: UIColor = .red @IBInspectable var endColor: UIColor = .green override func draw(_ rect: CGRect) { // 2 let context = UIGraphicsGetCurrentContext()! let colors = [startColor.cgColor, endColor.cgColor] // 3 let colorSpace = CGColorSpaceCreateDeviceRGB() // 4 let colorLocations: [CGFloat] = [0.0, 1.0] // 5 let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: colorLocations)! // 6 let startPoint = CGPoint.zero let endPoint = CGPoint(x: 0, y: bounds.height) context.drawLinearGradient(gradient, start: startPoint, end: endPoint, options: []) } }
There are a few things to go over here:
You set up the start and end colors for the gradient as @IBInspectable properties, so that you’ll be able to change them in the storyboard.
CG drawing functions need to know the context in which they will draw, so you use the UIKit method UIGraphicsGetCurrentContext() to obtain the current context. That’s the one that draw(_:) draws into.
All contexts have a color space. This could be CMYK or grayscale, but here you’re using the RGB color space.
The color stops describe where the colors in the gradient change over. In this example, you only have two colors, red going to green, but you could have an array of three stops, and have red going to blue going to green. The stops are between 0 and 1, where 0.33 is a third of the way through the gradient.
Create the actual gradient, defining the color space, colors and color stops.
Finally, you draw the gradient. CGContextDrawLinearGradient() takes the following parameters:
The CGContext in which to draw
The CGGradient with color space, colors and stops
The start point
The end point
Option flags to extend the gradient
The gradient will fill the entire rect of draw(_:).
Set up Xcode so that you have a side-by-side view of your code and the storyboard using the Assistant Editor (Show Assistant Editor…\Counterparts\Main.storyboard), and you’ll see the gradient appear on the Graph View.
In the storyboard, select the Graph View. Then in the Attributes Inspector, change Start Color to RGB(250, 233, 222), and End Color to RGB(252, 79, 8) (click the color, then Other\Color Sliders):
Now for some clean up duty. In Main.storyboard, select each view in turn, except for the main ViewController view, and set the Background Color to Clear Color. You don’t need the yellow color any more, and the push button views should have a transparent background too.
Build and run the application, and you’ll notice the graph looks a lot nicer, or at least the background of it. :]
Clipping Areas
When you used the gradient just now, you filled the whole of the view’s context area. However, you can create paths to use as clipping areas instead of being used for drawing. Clipping areas allow you to define the area you want to be filled in, instead of the whole context.
Go to GraphView.swift.
First, add these constants at the top of GraphView, which we will use for drawing later:
private struct Constants { static let cornerRadiusSize = CGSize(width: 8.0, height: 8.0) static let margin: CGFloat = 20.0 static let topBorder: CGFloat = 60 static let bottomBorder: CGFloat = 50 static let colorAlpha: CGFloat = 0.3 static let circleDiameter: CGFloat = 5.0 }
Now add this code to the top of draw(_:):
let path = UIBezierPath(roundedRect: rect, byRoundingCorners: .allCorners, cornerRadii: Constants.cornerRadiusSize) path.addClip()
This will create a clipping area that constrains the gradient. You’ll use this same trick shortly to draw a second gradient under the graph line.
Build and run the application and see that your graph view has nice, rounded corners:
Note: Drawing static views with Core Graphics is generally quick enough, but if your views move around or need frequent redrawing, you should use Core Animation layers. Core Animation is optimized so that the GPU, not the CPU, handles most of the processing. In contrast, the CPU processes view drawing performed by Core Graphics in draw(_:).
Instead of using a clipping path, you can create rounded corners using the cornerRadius property of a CALayer, but you should optimize for your situation. For a good lesson on this concept, check out Custom Control Tutorial for iOS and Swift: A Reusable Knob by Mikael Konutgan and Sam Davies, where you’ll use Core Animation to create a custom control.
Tricky Calculations for Graph Points
Now you’ll take a short break from drawing to make the graph. You’ll plot 7 points; the x-axis will be the ‘Day of the Week’ and the y-axis will be the ‘Number of Glasses Drunk’.
First, set up sample data for the week.
Still in GraphView.swift, at the top of the class, add this property:
//Weekly sample data var graphPoints = [4, 2, 6, 4, 5, 8, 3]
This holds sample data that represents seven days. Ignore the warning you get about changing this to a let value, as we’ll need it to be a var later on.
Add this code to the top of the draw(_:):
let width = rect.width let height = rect.height
And add this code to the end of draw(_:):
//calculate the x point let margin = Constants.margin let graphWidth = width - margin * 2 - 4 let columnXPoint = { (column: Int) -> CGFloat in //Calculate the gap between points let spacing = graphWidth / CGFloat(self.graphPoints.count - 1) return CGFloat(column) * spacing + margin + 2 }
The x-axis points consist of 7 equally spaced points. The code above is a closure expression. It could have been added as a function, but for small calculations like this, you can keep them inline.
columnXPoint takes a column as a parameter, and returns a value where the point should be on the x-axis.
Add the code to calculate the y-axis points to the end of draw(_:):
// calculate the y point let topBorder = Constants.topBorder let bottomBorder = Constants.bottomBorder let graphHeight = height - topBorder - bottomBorder let maxValue = graphPoints.max()! let columnYPoint = { (graphPoint: Int) -> CGFloat in let y = CGFloat(graphPoint) / CGFloat(maxValue) * graphHeight return graphHeight + topBorder - y // Flip the graph }
columnYPoint is also a closure expression that takes the value from the array for the day of the week as its parameter. It returns the y position, between 0 and the greatest number of glasses drunk.
Because the origin in Core Graphics is in the top-left corner and you draw a graph from an origin point in the bottom-left corner, columnYPoint adjusts its return value so that the graph is oriented as you would expect.
Continue by adding line drawing code to the end of draw(_:):
// draw the line graph UIColor.white.setFill() UIColor.white.setStroke() // set up the points line let graphPath = UIBezierPath() // go to start of line graphPath.move(to: CGPoint(x: columnXPoint(0), y: columnYPoint(graphPoints[0]))) // add points for each item in the graphPoints array // at the correct (x, y) for the point for i in 1..<graphPoints.count { let nextPoint = CGPoint(x: columnXPoint(i), y: columnYPoint(graphPoints[i])) graphPath.addLine(to: nextPoint) } graphPath.stroke()
In this block, you create the path for the graph. The UIBezierPath is built up from the x and y points for each element in graphPoints.
The Graph View in the storyboard should now look like this:
Now that you verified the line draws correctly, remove this from the end of draw(_:):
graphPath.stroke()
That was just so that you could check out the line in the storyboard and verify that the calculations are correct.
A Gradient Graph
You're now going to create a gradient underneath this path by using the path as a clipping path.
First set up the clipping path at the end of draw(_:):
//Create the clipping path for the graph gradient //1 - save the state of the context (commented out for now) //context.saveGState() //2 - make a copy of the path let clippingPath = graphPath.copy() as! UIBezierPath //3 - add lines to the copied path to complete the clip area clippingPath.addLine(to: CGPoint(x: columnXPoint(graphPoints.count - 1), y:height)) clippingPath.addLine(to: CGPoint(x:columnXPoint(0), y:height)) clippingPath.close() //4 - add the clipping path to the context clippingPath.addClip() //5 - check clipping path - temporary code UIColor.green.setFill() let rectPath = UIBezierPath(rect: rect) rectPath.fill() //end temporary code
A section-by-section breakdown of the above code:
context.saveGState() is commented out for now -- you’ll come back to this in a moment once you understand what it does.
Copy the plotted path to a new path that defines the area to fill with a gradient.
Complete the area with the corner points and close the path. This adds the bottom-right and bottom-left points of the graph.
Add the clipping path to the context. When the context is filled, only the clipped path is actually filled.
Fill the context. Remember that rect is the area of the context that was passed to draw(_:).
Your Graph View in the storyboard should now look like this:
Next, you'll replace that lovely green with a gradient you create from the colors used for the background gradient.
Remove the temporary code with the green color fill from the end of draw(_:), and add this code instead:
let highestYPoint = columnYPoint(maxValue) let graphStartPoint = CGPoint(x: margin, y: highestYPoint) let graphEndPoint = CGPoint(x: margin, y: bounds.height) context.drawLinearGradient(gradient, start: graphStartPoint, end: graphEndPoint, options: []) //context.restoreGState()
In this block, you find the highest number of glasses drunk and use that as the starting point of the gradient.
You can’t fill the whole rect the same way you did with the green color. The gradient would fill from the top of the context instead of from the top of the graph, and the desired gradient wouldn’t show up.
Take note of the commented out context.restoreGState() -- you’ll remove the comments after you draw the circles for the plot points.
At the end of draw(_:), add this:
//draw the line on top of the clipped gradient graphPath.lineWidth = 2.0 graphPath.stroke()
This code draws the original path.
Your graph is really taking shape now:
Drawing the Data Points
At the end of draw(_:), add the following:
//Draw the circles on top of the graph stroke for i in 0..<graphPoints.count { var point = CGPoint(x: columnXPoint(i), y: columnYPoint(graphPoints[i])) point.x -= Constants.circleDiameter / 2 point.y -= Constants.circleDiameter / 2 let circle = UIBezierPath(ovalIn: CGRect(origin: point, size: CGSize(width: Constants.circleDiameter, height: Constants.circleDiameter))) circle.fill() }
This code draws the plot points and is nothing new. It fills a circle path for each of the elements in the array at the calculated x and y points.
Hmmm…but what's showing up in the storyboard are not nice, round circle points! What's going on?
Context States
Graphics contexts can save states. When you set many context properties, such as fill color, transformation matrix, color space or clip region, you're actually setting them for the current graphics state.
You can save a state by using context.saveGState(), which pushes a copy of the current graphics state onto the state stack. You can also make changes to context properties, but when you call context.restoreGState(), the original state is taken off the stack and the context properties revert. That's why you're seeing the weird issue with your points.
Still in GraphView.swift, in draw(_:), uncomment the context.saveGState() that takes place before creating the clipping path, and uncomment the context.restoreGState() that takes place after the clipping path has been used.
By doing this, you:
Push the original graphics state onto the stack with context.saveGState().
Add the clipping path to a new graphics state.
Draw the gradient within the clipping path.
Restore the original graphics state with context.restoreGState(). This was the state before you added the clipping path.
Your graph line and circles should be much clearer now:
At the end of draw(_:), add the code to draw the three horizontal lines:
//Draw horizontal graph lines on the top of everything let linePath = UIBezierPath() //top line linePath.move(to: CGPoint(x: margin, y: topBorder)) linePath.addLine(to: CGPoint(x: width - margin, y: topBorder)) //center line linePath.move(to: CGPoint(x: margin, y: graphHeight/2 + topBorder)) linePath.addLine(to: CGPoint(x: width - margin, y: graphHeight/2 + topBorder)) //bottom line linePath.move(to: CGPoint(x: margin, y:height - bottomBorder)) linePath.addLine(to: CGPoint(x: width - margin, y: height - bottomBorder)) let color = UIColor(white: 1.0, alpha: Constants.colorAlpha) color.setStroke() linePath.lineWidth = 1.0 linePath.stroke()
Nothing in this code is new. All you're doing is moving to a point and drawing a horizontal line.
Adding the Graph Labels
Now you'll add the labels to make the graph user-friendly.
Go to ViewController.swift and add these outlet properties:
//Label outlets @IBOutlet weak var averageWaterDrunk: UILabel! @IBOutlet weak var maxLabel: UILabel! @IBOutlet weak var stackView: UIStackView!
This adds outlets for the two labels that you want to dynamically change text for (the average water drunk label, the max water drunk label), and for a StackView with day names labels.
Now go to Main.storyboard and add the following views as subviews of the Graph View:
UILabel with text "Water Drunk"
UILabel with text "Average: "
UILabel with text "2", next to the average label
UILabel with text "99", right aligned next to the top of the graph
UILabel with text "0", right aligned to the bottom of the graph
A horizontal StackView with labels for each day of a week -- the text for each will be changed in code. Center aligned.
Shift-select all the labels, and then change the fonts to custom Avenir Next Condensed, Medium style.
If you have any trouble setting up those labels, check out the final project from the end of this tutorial.
Connect averageWaterDrunk, maxLabel and stackView to the corresponding views in Main.storyboard. Control-drag from View Controller to the correct label and choose the outlet from the pop up:
Now that you've finished setting up the graph view, in Main.storyboard select the Graph View and check Hidden so the graph doesn't appear when the app first runs.
Go to ViewController.swift and add this method to set up the labels:
func setupGraphDisplay() { let maxDayIndex = stackView.arrangedSubviews.count - 1 // 1 - replace last day with today's actual data graphView.graphPoints[graphView.graphPoints.count - 1] = counterView.counter //2 - indicate that the graph needs to be redrawn graphView.setNeedsDisplay() maxLabel.text = "\(graphView.graphPoints.max()!)" // 3 - calculate average from graphPoints let average = graphView.graphPoints.reduce(0, +) / graphView.graphPoints.count averageWaterDrunk.text = "\(average)" // 4 - setup date formatter and calendar let today = Date() let calendar = Calendar.current let formatter = DateFormatter() formatter.setLocalizedDateFormatFromTemplate("EEEEE") // 5 - set up the day name labels with correct days for i in 0...maxDayIndex { if let date = calendar.date(byAdding: .day, value: -i, to: today), let label = stackView.arrangedSubviews[maxDayIndex - i] as? UILabel { label.text = formatter.string(from: date) } } }
This looks a little burly, but it's required to set up the calendar and retrieve the current day of the week. Take it in sections:
You set today’s data as the last item in the graph’s data array. In the final project, which you can download at the end of Part 3, you'll expand on this by replacing it with 60 days of sample data, and you'll include a method that splits out the last x number of days from an array, but that is beyond the scope of this session. :]
Redraws the graph in case there are any changes to today’s data.
Here you use Swift’s reduce to calculate the average glasses drunk for the week; it's a very useful method to sum up all the elements in an array.
Note: This Swift Functional Programming Tutorial explains functional programming in some depth.
This section sets up DateFormatter in a way that it will get first letter of the name of a day.
This loop goes through all labels inside of stackView and we set text for each label from date formatter.
Still in ViewController.swift, call this new method from counterViewTap(_:). In the else part of the conditional, where the comment says show graph, add this code:
setupGraphDisplay()
Run the application, and click the counter. Hurrah! The graph swings into view in all its glory!
Mastering the Matrix
Your app is looking really sharp! The counter view you created in part one could be improved though, like by adding markings to indicate each glass to be drunk:
Now that you've had a bit of practice with CG functions, you'll use them to rotate and translate the drawing context.
Notice that these markers radiate from the center:
As well as drawing into a context, you have the option to manipulate the context by rotating, scaling and translating the context’s transformation matrix.
At first, this can seem confusing, but after you work through these exercises, it'll make more sense. The order of the transformations is important, so first I’ll outline what you'll be doing with diagrams.
The following diagram is the result of rotating the context and then drawing a rectangle in the center of the context.
The black rectangle is drawn before rotating the context, then the green one, then the red one. Two things to notice:
The context is rotated at the top left (0,0)
The rectangle is still being drawn in the center of the context, but after the context has been rotated.
When you're drawing the counter view’s markers, you'll translate the context first, then you'll rotate it.
In this diagram, the rectangle marker is at the very top left of the context. The blue lines outline the translated context, then the context rotates (red dashed line) and is translated again.
When the red rectangle marker is finally drawn into the context, it'll appear in the view at an angle.
After the context is rotated and translated to draw the red marker, it needs to be reset to the center so that the context can be rotated and translated again to draw the green marker.
Just as you saved the context state with the clipping path in the Graph View, you'll save and restore the state with the transformation matrix each time you draw the marker.
Go to CounterView.swift and add this code to the end of draw(_:) to add the markers to the counter:
//Counter View markers let context = UIGraphicsGetCurrentContext()! //1 - save original state context.saveGState() outlineColor.setFill() let markerWidth: CGFloat = 5.0 let markerSize: CGFloat = 10.0 //2 - the marker rectangle positioned at the top left let markerPath = UIBezierPath(rect: CGRect(x: -markerWidth / 2, y: 0, width: markerWidth, height: markerSize)) //3 - move top left of context to the previous center position context.translateBy(x: rect.width / 2, y: rect.height / 2) for i in 1...Constants.numberOfGlasses { //4 - save the centred context context.saveGState() //5 - calculate the rotation angle let angle = arcLengthPerGlass * CGFloat(i) + startAngle - .pi / 2 //rotate and translate context.rotate(by: angle) context.translateBy(x: 0, y: rect.height / 2 - markerSize) //6 - fill the marker rectangle markerPath.fill() //7 - restore the centred context for the next rotate context.restoreGState() } //8 - restore the original state in case of more painting context.restoreGState()
Here's what you've just done:
Before manipulating the context’s matrix, you save the original state of the matrix.
Define the position and shape of the path -- but you're not drawing it yet.
Move the context so that rotation happens around the context’s original center. (Blue lines in the previous diagram.)
For each mark, you first save the centered context state.
Using the individual angle previously calculated, you determine the angle for each marker and rotate and translate the context.
Draw the marker rectangle at the top left of the rotated and translated context.
Restore the centered context’s state.
Restore the original state of the context that had no rotations or translations.
Whew! Nice job hanging in there for that. Now build and run the application, and admire Flo's beautiful and informative UI:
Where to Go to From Here?
Here is Flo, complete with all of the code you’ve developed so far.
At this point, you've learned how to draw paths, gradients and how to change the context's transformation matrix.
In the third and final part of this Core Graphics tutorial, you'll create a patterned background and draw a vector medal image.
If you have any questions or comments, please join the discussion below!
The post Core Graphics Tutorial Part 2: Gradients and Contexts appeared first on Ray Wenderlich.
Core Graphics Tutorial Part 2: Gradients and Contexts published first on http://ift.tt/2fA8nUr
0 notes
volodimirg · 4 years
Video
youtube
How to create Line Graph on Android (GraphView)
0 notes