Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rounded bars in bar charts #4375

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ open class BarChartDataSet: BarLineScatterCandleBubbleChartDataSet, IBarChartDat
/// the alpha value (transparency) that is used for drawing the highlight indicator bar. min = 0.0 (fully transparent), max = 1.0 (fully opaque)
open var highlightAlpha = CGFloat(120.0 / 255.0)

/// The multiplier to generate a corner radius for the bar. 0.0 means no round radius.
open var roundRadiusWidthMultiplier: CGFloat = 0.0

// MARK: - NSCopying

open override func copy(with zone: NSZone? = nil) -> Any
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,11 @@ extension ChartDataSet: RandomAccessCollection {

// MARK: RangeReplaceableCollection
extension ChartDataSet: RangeReplaceableCollection {
public func replaceSubrange<C>(_ subrange: Swift.Range<Index>, with newElements: C) where C : Collection, Element == C.Element {
entries.replaceSubrange(subrange, with: newElements)
notifyDataSetChanged()
}

public func append(_ newElement: Element) {
calcMinMax(entry: newElement)
entries.append(newElement)
Expand Down
3 changes: 3 additions & 0 deletions Source/Charts/Data/Interfaces/IBarChartDataSet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,7 @@ public protocol IBarChartDataSet: IBarLineScatterCandleBubbleChartDataSet

/// array of labels used to describe the different values of the stacked bars
var stackLabels: [String] { get set }

/// The multiplier to generate a corner radius for the bar. 0.0 means no round radius.
var roundRadiusWidthMultiplier: CGFloat { get set }
}
67 changes: 65 additions & 2 deletions Source/Charts/Renderers/BarChartRenderer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,36 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer
let isStacked = dataSet.isStacked
let stackSize = isStacked ? dataSet.stackSize : 1

func getIndicesOfTopBar() -> Set<Int>
{

if !(dataSet.roundRadiusWidthMultiplier > 0.0)
{
return Set()
}

var indices = Set<Int>()
for i in stride(from: 0, to: buffer.rects.count, by: stackSize)
{
let rects = Array(buffer.rects[i...i+stackSize - 1])

for index in (0..<rects.count).reversed()
{
let rect = rects[index]

if rect.height > 0 || index == 0
{
indices.insert(i + index)
break
}
}
}

return indices
}

let topRectIndices = Set(getIndicesOfTopBar())

for j in stride(from: 0, to: buffer.rects.count, by: 1)
{
let barRect = buffer.rects[j]
Expand All @@ -431,7 +461,14 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer
context.setFillColor(dataSet.color(atIndex: j).cgColor)
}

context.fill(barRect)
if topRectIndices.contains(j)
{
drawRoundedBar(barRect: barRect, roundRadiusWidthMultiplier: dataSet.roundRadiusWidthMultiplier, context: context)
}
else {
context.fill(barRect)
}


if drawBorder
{
Expand Down Expand Up @@ -459,6 +496,27 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer
context.restoreGState()
}

private func drawRoundedBar(barRect: CGRect, roundRadiusWidthMultiplier: CGFloat, context: CGContext) {
var radius: CGFloat = barRect.width * roundRadiusWidthMultiplier
if radius > barRect.height, barRect.height > 0
{
radius = barRect.height * 0.999
}

let path = CGMutablePath()
path.move(to: CGPoint(x: barRect.minX, y: barRect.maxY))
path.addArc(tangent1End: CGPoint(x: barRect.minX, y: barRect.minY),
tangent2End: CGPoint(x: barRect.maxX, y: barRect.minY),
radius: radius)
path.addArc(tangent1End: CGPoint(x: barRect.maxX, y: barRect.minY),
tangent2End: CGPoint(x: barRect.maxX, y: barRect.maxY),
radius: radius)
path.addLine(to: CGPoint(x: barRect.maxX, y: barRect.maxY))

context.addPath(path)
context.fillPath()
}

open func prepareBarHighlight(
x: Double,
y1: Double,
Expand Down Expand Up @@ -811,7 +869,12 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer

setHighlightDrawPos(highlight: high, barRect: barRect)

context.fill(barRect)
if set.roundRadiusWidthMultiplier > 0.0 && (high.stackIndex == (e.yValues?.count ?? 0) - 1 || high.stackIndex == -1) {
drawRoundedBar(barRect: barRect, roundRadiusWidthMultiplier: set.roundRadiusWidthMultiplier, context: context)
}
else {
context.fill(barRect)
}
}
}

Expand Down