简体   繁体   中英

What would be equal in Swift to draw path/rect with a specific color

in Android (in Java) I could do something like this (here I tried to draw Triangle figure which is filled with different colors, first half with red color and second with green, also black stroke around Triangle figure:

@Override
public void onDraw(Canvas canvas) {

        ....

        canvas.clipPath(pathBoundary); // triangle figure path
        canvas.drawPath(pathBoundary, paintBlack); // draw black stroke around figure
        canvas.drawRect(rectRed, paintRed); // fill first half with red color
        canvas.drawRect(rectGreen, paintGreen); // fill second half with green color

in iOS I just learned how to draw Triangle figure with only one color, would like to also draw with two colors (like in Android)

  override func draw(_ rect: CGRect) {
        guard let context = UIGraphicsGetCurrentContext() else { return }
        context.beginPath()
        context.move(to: CGPoint(x: rect.minX, y: rect.maxY))
        context.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
        context.addLine(to: CGPoint(x: (rect.maxX / 2.0), y: rect.minY))
        context.setFillColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 0.60)
        context.fillPath()
        context.clip()
        ... how to draw path with specific color?
        ... how to draw rect with specific color?

在此处输入图片说明

You can do just like you do on Android: stroke the triangle path, set it as clipping path, stroke a rectangle in red, stroke a rectangle in green.

UIGraphicsBeginImageContext(CGSize(width: 200, height: 200))
let context = UIGraphicsGetCurrentContext()!
context.beginPath()
context.move(to: CGPoint(x: 100, y: 0))
context.addLine(to: CGPoint(x: 0, y: 200))
context.addLine(to: CGPoint(x: 200, y: 200))
context.closePath()
let path = context.path!
context.setStrokeColor(UIColor.black.cgColor)
context.strokePath()
context.addPath(path)
context.clip()
context.setFillColor(UIColor.red.cgColor)
context.fill(CGRect(x: 0, y: 0, width: 200, height: 150))
context.setFillColor(UIColor.green.cgColor)
context.fill(CGRect(x: 0, y: 150, width: 200, height: 50))
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

You can run the code above in a playground. In the right column hover over the last line (the one for image), click on the eye icon and you'll see a preview of the image that was drawn.

The way you do it is basically by drawing two different paths. Each with a different fill color. Here is an example:

  override func draw(_ rect: CGRect) {
    super.draw(rect)

    guard let context = UIGraphicsGetCurrentContext() else { return }
    let leftVertex = CGPoint(x: rect.minX, y: rect.maxY)
    let topVertex = CGPoint(x: rect.midX, y: rect.minY)

    let r = sqrt(pow(leftVertex.x - topVertex.x, 2) + pow(leftVertex.y - topVertex.y, 2))
    let leftAngle = atan(rect.maxY/rect.midX)

    context.beginPath()
    context.move(to: leftVertex)
    context.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
    context.addLine(to: topVertex)
    context.closePath()
    context.setFillColor(red: 0.0, green: 1.0, blue: 0.0, alpha: 1)
    context.fillPath()

    let smallLeftVertex = CGPoint(x: r/2*cos(leftAngle), y: rect.midY)

    context.beginPath()
    context.move(to: smallLeftVertex)
    context.addLine(to: topVertex)
    context.addLine(to: CGPoint(x: rect.maxX - smallLeftVertex.x, y: rect.midY))
    context.closePath()
    context.setFillColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1)
    context.fillPath()

  }

There is some math to evaluate which would be the vertices of the inner (smaller) triangle.

Here is the result: 在此处输入图片说明

If you want you can try it in a playground:

//: Playground - noun: a place where people can play

import UIKit

class TriangleView: UIView {
  override func draw(_ rect: CGRect) {
    super.draw(rect)

    guard let context = UIGraphicsGetCurrentContext() else { return }
    let leftVertex = CGPoint(x: rect.minX, y: rect.maxY)
    let topVertex = CGPoint(x: rect.midX, y: rect.minY)

    let r = sqrt(pow(leftVertex.x - topVertex.x, 2) + pow(leftVertex.y - topVertex.y, 2))
    let leftAngle = atan(rect.maxY/rect.midX)

    context.beginPath()
    context.move(to: leftVertex)
    context.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
    context.addLine(to: topVertex)
    context.closePath()
    context.setFillColor(red: 0.0, green: 1.0, blue: 0.0, alpha: 1)
    context.fillPath()

    let smallLeftVertex = CGPoint(x: r/2*cos(leftAngle), y: rect.midY)

    context.beginPath()
    context.move(to: smallLeftVertex)
    context.addLine(to: topVertex)
    context.addLine(to: CGPoint(x: rect.maxX - smallLeftVertex.x, y: rect.midY))
    context.closePath()
    context.setFillColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1)
    context.fillPath()

  }
}


let triangle = TriangleView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
triangle.backgroundColor = .white

**

Edit:

**

You can also avoid to draw two overlapping triangles by using the clip feature of CGContext. In this case the code would look like this:

  override func draw(_ rect: CGRect) {
    super.draw(rect)

    guard let context = UIGraphicsGetCurrentContext() else { return }
    let leftVertex = CGPoint(x: rect.minX, y: rect.maxY)
    let topVertex = CGPoint(x: rect.midX, y: rect.minY)

    var path = CGMutablePath()
    path.move(to: leftVertex)
    path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
    path.addLine(to: topVertex)
    path.closeSubpath()

    context.addPath(path)
    context.clip()

    context.setFillColor(red: 1, green: 0, blue: 0, alpha: 1)
    context.fill(CGRect(x: 0, y: 0, width: rect.width, height: rect.height/2))
    context.setFillColor(red: 0, green: 1, blue: 0, alpha: 1)
    context.fill(CGRect(x: 0, y: rect.midY, width: rect.width, height: rect.height/2))
  }

In the first part of the code we create the triangle, we extract the path just drown in the context and we add it as clipping path. Then we can fill the two rectangles with the two different colours.

Hope this answers your question.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM