代码之家  ›  专栏  ›  技术社区  ›  Sweeper

如何在饼图上为标签找到合适的位置?

  •  5
  • Sweeper  · 技术社区  · 6 年前

    我没有使用任何库,因此这不是切片外部饼图条目具有不同位置偏移“>this

    我自己画的馅饼区是这样的:

    var部分:【piechartSection】=[]{
    DIDSET {
    设置需要显示()
    }
    }
    
    覆盖func draw(rect:cgrect){
    设sumofsections=sections.map$0.value.reduce(0,+)
    var路径开始=cgfloat.pi
    让smallerDimension=min(高度、宽度)
    对于分区中的分区{
    /绘图部分
    设百分比=截面值/截面总和
    让pathend=pathstart+cgfloat.pi*百分比.f*2
    让path=uibezierpath(arcenter:cgpoint(x:bounds.midx,y:bounds.midy)),
    半径:小尺寸/4,开始角度:路径开始,结束角度:路径结束,顺时针:真)
    
    /绘制标签
    //这是我计算标签位置的尝试
    让中间角度=(路径开始+路径结束)/2
    让textx=bounds.midx+smallerdimension*3/8*cos(中间角)
    让texty=bounds.midy+smallerDimension*3/8*sin(middangle)
    
    //创建要显示的文本,这不相关吗?
    让attributedString=nsmutablettributedString(string:section.name,attributes:)[
    .背景色:uicolor.black.withalphacomponent(0.15),
    .FONT:uiFONT.systemFONT(OFSIZE:9)
    )
    让格式化程序=数字格式化程序()。
    formatter.maximumFractionDigits=0
    让percentageString=“\n”+formatter.string(从:(percentage*100)作为nsnumber)!+“%”
    attributedString.append(nsattributedString(string:percentageString,attributes:)[
    .背景色:uicolor.black.withalphacomponent(0.5),
    .FONT:uiFONT.systemFONT(OFSIZE:12)
    ))
    attributedString.draw(在:cgpoint(x:textx,y:texty))。
    
    /笔划路径
    path.linewidth=6
    节.color.setstroke())
    路径选择()
    pathStart=路径结束
    }
    }
    < /代码> 
    
    

    并且apiechartsectionis a simple struct:。

    struct piechartsection{
    Let值:Double
    让颜色:uicolor
    let name:字符串
    }
    < /代码> 
    
    

    馅饼看起来不错,但标签有时离馅饼很远,有时离它很近:

    我认为问题在于,nsattriutedstring.drawalways draws the text from the to p left corner,means that theto p left cornersof the text are all equal distance to the pie,which I need to draw the text so that theirclosest points to the pie.are all equal distance to the pie.

    我怎样才能画出那样的文字?

    我没有使用可可荚,因为我发现很难按照我想要的方式使用高级API制作图表。只是太复杂了。我希望对饼图的绘制方式进行较低级别的控制。.

    我自己画的馅饼区是这样的:

    var sections: [PieChartSection] = [] {
        didSet {
            setNeedsDisplay()
        }
    }
    
    override func draw(_ rect: CGRect) {
        let sumOfSections = sections.map { $0.value }.reduce(0, +)
        var pathStart = CGFloat.pi
        let smallerDimension = min(height, width)
        for section in sections {
            // draw section
            let percentage = section.value / sumOfSections
            let pathEnd = pathStart + CGFloat.pi * percentage.f * 2
            let path = UIBezierPath(arcCenter: CGPoint(x: bounds.midX, y: bounds.midY),
                                    radius: smallerDimension / 4, startAngle: pathStart, endAngle: pathEnd, clockwise: true)
    
            //draw labels
            // this is my attempt at calculating the position of the labels
            let midAngle = (pathStart + pathEnd) / 2
            let textX = bounds.midX + smallerDimension * 3 / 8 * cos(midAngle)
            let textY = bounds.midY + smallerDimension * 3 / 8 * sin(midAngle)
    
            // creating the text to be shown, don't this is relevant
            let attributedString = NSMutableAttributedString(string: section.name, attributes: [
                .foregroundColor: UIColor.black.withAlphaComponent(0.15),
                .font: UIFont.systemFont(ofSize: 9)
                ])
            let formatter = NumberFormatter()
            formatter.maximumFractionDigits = 0
            let percentageString = "\n" + formatter.string(from: (percentage * 100) as NSNumber)! + "%"
            attributedString.append(NSAttributedString(string: percentageString, attributes: [
                .foregroundColor: UIColor.black.withAlphaComponent(0.5),
                .font: UIFont.systemFont(ofSize: 12)
                ]))
            attributedString.draw(at: CGPoint(x: textX, y: textY))
    
            // stroke path
            path.lineWidth = 6
            section.color.setStroke()
            path.stroke()
            pathStart = pathEnd
        }
    }
    

    和APieChartSection是一个简单结构:

    struct PieChartSection {
        let value: Double
        let color: UIColor
        let name: String
    }
    

    馅饼看起来不错,但标签有时离馅饼很远,有时离它很近:

    enter image description here

    我想问题是NSAttriutedString.draw总是从左上角绘制文本,这意味着左上角文本与饼图的距离相等,而我需要绘制文本,以便最接近饼图的点与饼的距离相等。

    我怎样才能画出那样的文字?

    我没有使用可可荚,因为我发现很难按照我想要的方式使用高级API制作图表。只是太复杂了。我想对我的饼图的绘制方式进行较低级别的控制。

    1 回复  |  直到 6 年前
        1
  •  7
  •   pacification    6 年前
    < Buff行情>

    我认为问题在于 nsattriutedstring.draw 总是从左上角绘制文本

    < /块引用>

    当然, draw method将把字符串的原点放在您经过的点上。在这种情况下,解决方案很简单-找到字符串的 大小,并确定正确的原点。

    let size=attributedString.size())
    设原点=cgpoint(x:textx-size.width/2,y:texty-size.height/2)
    attributedString.draw(位于:原点)
    < /代码> 
    
    结果:

    当然,draw方法将把字符串的原点放在您经过的点上。在这种情况下,解决方案很简单-找到size正确的原点。

    let size = attributedString.size()
    let origin = CGPoint(x: textX - size.width / 2, y: textY - size.height / 2)
    attributedString.draw(at: origin)
    

    结果:

    enter image description here