I'm trying to create some simple funcs to create different shapes (diamond, rectangle and capsule) with different colors and different shading (filled, stroked and striped). To abstract some of the repetition away I've tried to pass the shape but get the dreaded "Protocol 'Shape' can only be used as a generic constraint because it has Self or associated type requirements". I've also tried passing an Int and using a Switch statement to recreate the shape in function but that has also not worked.
This function works for any color, but only one shape:
func stripedSymbol (_ solidColor: Color) -> some View {
let shape = Diamond()
return ZStack {
shape.fill(gradientFill(solidColor))
shape.stroke(solidColor)
}
}
Would like to be able to call the function with color AND shape (either directly or encoded in Int or enum) something like this:
func stripedSymbol (_ solidColor: Color, shape: Shape) -> some View {
return ZStack {
shape.fill(gradientFill(solidColor))
shape.stroke(solidColor)
}
}
Any suggestions?
Shape is self-referenced so it can only be used to add constraints. This should work:
func stripedSymbol<S: Shape> (_ solidColor: Color, shape: S) -> some View {
return ZStack {
shape.fill(gradientFill(solidColor))
shape.stroke(solidColor)
}
}
Related
I want to use a custom shape that I have drawn using a path to the marks of my chart. So instead of points or bars or whatever marking the data, I want the shape to be a specific symbol I have drawn. I am quite new to swift so I apologise if I add unnecessary information.
So I have a graph that looks like this:
graph image
here is the code for it:
Chart {
PointMark(x: .value("Boat", "Pace Boat"), y: .value("Pace Boat", (viewModel.duration*(Double(viewModel.split) / paceBoat))))
PointMark(x: .value("Boat", "You"), y: .value("Your Pace", viewModel.boat.last?.1.distance ?? 0))
}
This is code for the way I produce a shape:
struct BoatShape: Shape {
func path(in rect: CGRect) -> Path {
var path = Path()
path.move(to: CGPoint(x: rect.midX, y: rect.minY))
//... do drawing blah
path.closeSubpath()
return path
}
}
I have seen I might be able to use the ChartSymbolShape protocol but I can't find much on the internet on implementation and I am quite new to swift. Any direction would be much appreciated
Additionally:
I would like to be to add text over the top of the shape just sort of pinning it to the x and y of the shape on the graph. Although this is not the main priority
Basically, what you should be doing is use any of the marks provided by Apple however set the opacity to 0 so that they don't appear. And then use the annotation therein you render your view.
Code is the following:
List(selection: $selectedBoard) {
ForEach(boards) { board in
NavigationLink(tag: board, selection: $selectedBoard) {
BoardView(board: board)
} label: {
Text(board.name ?? "Board")
}
.listRowBackground(self.selectedBoard == board ? Color.App.boardSelection : Color.App.boardBackground)
The effect is the following:
See the gray space on the left and right? This is the accent color that I don't know how to remove. The whole row should be the same, uniform color of a bit lighter black.
Working example: https://github.com/igr/Clmn
https://github.com/igr/Clmn/blob/main/Clmn/Views/BoardList/BoardsNavigationListView.swift#L32
This happens when List is used in NavigationView for iteration of NavigationLink elements.
This seems to be a bug.
Let say I have a SwiftUI component and I want it to change color according to a parameter I choose like :
Component(colorValue: "1")
Component(colorValue: "2")
Component(colorValue: "3")
colorValue: 1 would change the color of my component to red, 2 to green, 3 to blue for example.
When I only had 2 colors in the beggining of my project I used a boolean in my component :
Rectangle().fill(Color(colorValue ? "red" : "blue"))
But now that I have multiple choice, how can I achieve the color change by checking the value of the colorValue String ?
Thanks in advance !
just use a function
func getColorValue() -> Color {
if colorValue == 1 { return .red }
// and so on
}
Rectangle().fill(Color(getColorValue()))
I am facing a weird problem with MKMapView. I have used a MKOverlayRenderer. Now the problem is when I am zooming out image showing correctly. But in case of zoom in, some portion of the image are cutting off. It's looking like a portion of MapView is coming above the overlay. Following is my overlay renderer code.
class MapOverlayRenderer: MKOverlayRenderer {
var overlayImage: UIImage
var plan: Plan
init(overlay: MKOverlay, overlayImage: UIImage, plan: Plan) {
self.overlayImage = overlayImage
self.plan = plan
super.init(overlay: overlay)
}
override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in ctx: CGContext) {
let theMapRect = overlay.boundingMapRect
let theRect = rect(for: theMapRect)
// Rotate around top left corner
ctx.rotate(by: CGFloat(degreesToRadians(plan.bearing)));
// Draw the image
UIGraphicsPushContext(ctx)
overlayImage.draw(in: theRect, blendMode: CGBlendMode.normal, alpha: 1.0)
UIGraphicsPopContext();
}
func degreesToRadians(_ x:Double) -> Double {
return (M_PI * x / 180.0)
}
}
Though I don't know the actual reason but when I am commenting ctx.rotate(by:) function this problem is been fixed. But that's not my solution cause image has to be in position.
Please Try below.
override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in ctx: CGContext) {
DispatchQueue.main.async {
let theMapRect = overlay.boundingMapRect
let theRect = rect(for: theMapRect)
// Rotate around top left corner
ctx.rotate(by: CGFloat(degreesToRadians(plan.bearing)));
// Draw the image
UIGraphicsPushContext(ctx)
overlayImage.draw(in: theRect, blendMode: CGBlendMode.normal, alpha: 1.0)
UIGraphicsPopContext();
}
}
I have a diamond-sprite and I want to be able to change the colour of the diamond from white, it's original colour to green. However, I can not figure out how to do this.
public class MoveControl : MonoBehaviour {
// Update is called once per frame
void Update () {
if (Input.GetKey(KeyCode.A) )
{
if (GetComponent<Renderer>().material.color == Color.white)
{
GetComponent<Renderer>().material.color = Color.green;
}
}
}
}
This above code is what I have right now and it only works if the material applied to the sprite, being white, is a sprites/default shader. This may not sound like a big problem but whenever I apply a different material of a different colour, such as blue, and change its settings so it has a sprites/default shader, the sprite becomes invisible.
I'm new at Unity and if someone could help me out, it would be very much appreciated
I'm not sure what you're trying to do but this may help you.
public class Material : MonoBehaviour {
Renderer renderer;
Color currentColor;
Color originalColor;
// Use this for initialization
void Start () {
renderer = gameObject.GetComponent<Renderer>(); //If you don't know the gameObject is the object this script is attached to
originalColor = renderer.material.color; //The original color ( in your case white )
}
// Update is called once per frame
void Update () {
if (Input.GetKey(KeyCode.A)) {
if (renderer.material.color == originalColor) { //Here we are checking if the color on the object is the original color
renderer.material.color = Color.blue;
currentColor = renderer.material.color; //Here we are assining the current color
}
}
}
}
I created a material and assigned it to the gameObject in the editor.