$(function () {
var gaugeOptions = {
chart: {
type: 'solidgauge'
},
title: null,
pane: {
center: ['50%', '85%'],
size: '140%',
startAngle: -90,
endAngle: 90,
background: {
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || '#EEE',
innerRadius: '60%',
outerRadius: '100%',
shape: 'arc'
}
},
tooltip: {
enabled: false
},
// the value axis
yAxis: {
lineWidth: 0,
minorTickInterval: null,
tickPixelInterval: 400,
tickWidth: 0,
title: {
y: -70
},
labels: {
y: 16
}
},
plotOptions: {
solidgauge: {
dataLabels: {
y: 5,
borderWidth: 0,
useHTML: true
}
}
}
};
// The speed gauge
$('#container-speed').highcharts(Highcharts.merge(gaugeOptions, {
yAxis: {
min: 0,
max: 100,
title: {
text: 'Speed'
}
},
series: [{
name: 'Speed',
data: [75]
}]
}));
});
Using the Highchart's solidgauge. Is there a way to have a gradient color up to the value showing on the gauge?
For example if my gauge is from 0 to 100, and at a specific time the value we are showing is 75, I want to show it as a gradient color transitioning from a green left section to small red right section. Of course the remaining 25% of the gauge in this example should not have any color just showing the background color of the gauge.
Is there a way to do that?
Related
here are two charts.
and I would like to show the data of object and object2 together in one chart.
Would it be possible?
Chart(db.objects, id: \.self) { object in
LineMark(
x: .value("name", object.name),
y: .value("value", Int(object.value) ?? 0)
)
}
Chart(db.objects2, id: \.self) { object2 in
LineMark(
x: .value("name", object2.name),
y: .value("value", Int(object2.value) ?? 0)
)
}
I just found the way from apple developer website
https://developer.apple.com/documentation/charts/chart/
struct ProfitOverTime {
var date: Date
var profit: Double
}
let departmentAProfit: [ProfitOverTime] = [] // ...
let departmentBProfit: [ProfitOverTime] = [] // ...
var body: some View {
Chart {
ForEach(departmentAProfit) {
LineMark(
x: .value("Date", $0.date),
y: .value("Profit A", $0.profit)
)
.foregroundStyle(.blue)
}
ForEach(departmentBProfit) {
LineMark(
x: .value("Date", $0.date),
y: .value("Profit B", $0.profit)
)
.foregroundStyle(.green)
}
RuleMark(
y: .value("Threshold", 500.0)
)
.foregroundStyle(.red)
}
}
This is an alternative solution. Since the data structure is the same, the data could be one source and displayed using one LineMark.
As an example, dept was added to the model to identify each group of data that represents a single line in the chart:
struct ProfitOverTime {
var dept: String
var date: Date
var profit: Double
}
The data combined into one array:
let data: [ProfitOverTime] = [] // ...
The foreground style is based on the department, that is, each line in the chart.
struct DepartmentChart: View {
var body: some View {
Chart(data) {
LineMark(
x: .value("Date", $0.date),
y: .value("Profit", $0.profit)
series: .value("Department", $0.dept)
)
.foregroundStyle(by: .value("Department", $0.dept))
RuleMark(
y: .value("Threshold", 500.0)
)
.foregroundStyle(.red)
}
.chartForegroundStyleScale(["Profit A": .green, "Profit B": .blue])
}
}
Series was added to identify each line by its color:
The chartForegroundStyleScale is optional since each line will automatically be colored differently. But chartForegroundStyleScale can be used to customize the line colors.
Here I am showing the data for a week. So if you want to show more than data then you can increase the number of entries. So that’s it from my side hope you understand.
Now use MultiLineChartView like this.
Complete Code:
import SwiftUI
import Charts
struct ContentView: View {
let days = ["S", "M", "T", "W", "T", "F", "S"]
let entries1 = [
ChartDataEntry(x: 1, y: 1),
ChartDataEntry(x: 2, y: 2),
ChartDataEntry(x: 3, y: 0),
ChartDataEntry(x: 4, y: 0),
ChartDataEntry(x: 5, y: 0),
ChartDataEntry(x: 6, y: 0),
ChartDataEntry(x: 7, y: 1),
]
let entries2 = [
ChartDataEntry(x: 1, y: 2),
ChartDataEntry(x: 2, y: 3),
ChartDataEntry(x: 3, y: 0),
ChartDataEntry(x: 4, y: 0),
ChartDataEntry(x: 5, y: 0),
ChartDataEntry(x: 6, y: 0),
ChartDataEntry(x: 7, y: 2)
]
var body: some View {
VStack{
Spacer()
MultiLineChartView(entries1: entries1, entries2: entries2, days: days)
.frame(height: 220)
Spacer()
}
}
}
struct MultiLineChartView : UIViewRepresentable {
var entries1 : [ChartDataEntry]
var entries2 : [ChartDataEntry]
var days: [String]
func makeUIView(context: Context) -> LineChartView {
let chart = LineChartView()
return createChart(chart: chart)
}
func updateUIView(_ uiView: LineChartView, context: Context) {
uiView.data = addData()
}
func createChart(chart: LineChartView) -> LineChartView{
chart.chartDescription?.enabled = false
chart.xAxis.drawGridLinesEnabled = false
chart.xAxis.drawLabelsEnabled = true
chart.xAxis.drawAxisLineEnabled = false
chart.xAxis.labelPosition = .bottom
chart.rightAxis.enabled = false
chart.leftAxis.enabled = false
chart.drawBordersEnabled = false
chart.legend.form = .none
chart.xAxis.labelCount = 7
chart.xAxis.forceLabelsEnabled = true
chart.xAxis.granularityEnabled = true
chart.xAxis.granularity = 1
chart.xAxis.valueFormatter = CustomChartFormatter(days: days)
chart.data = addData()
return chart
}
func addData() -> LineChartData{
let data = LineChartData(dataSets: [
//Schedule Trips Line
generateLineChartDataSet(dataSetEntries: entries1, color: UIColor(Color(#colorLiteral(red: 0.6235294118, green: 0.7333333333, blue: 0.3568627451, alpha: 1))), fillColor: UIColor(Color(#colorLiteral(red: 0, green: 0.8134518862, blue: 0.9959517121, alpha: 1)))),
//Unloadings Line
generateLineChartDataSet(dataSetEntries: entries2, color: UIColor(Color(#colorLiteral(red: 0.003921568627, green: 0.231372549, blue: 0.431372549, alpha: 1))), fillColor: UIColor(Color(#colorLiteral(red: 0.4745098054, green: 0.8392156959, blue: 0.9764705896, alpha: 1))))
])
return data
}
func generateLineChartDataSet(dataSetEntries: [ChartDataEntry], color: UIColor, fillColor: UIColor) -> LineChartDataSet{
let dataSet = LineChartDataSet(entries: dataSetEntries, label: "")
dataSet.colors = [color]
dataSet.mode = .cubicBezier
dataSet.circleRadius = 5
dataSet.circleHoleColor = UIColor(Color(#colorLiteral(red: 0.003921568627, green: 0.231372549, blue: 0.431372549, alpha: 1)))
dataSet.fill = Fill.fillWithColor(fillColor)
dataSet.drawFilledEnabled = true
dataSet.setCircleColor(UIColor.clear)
dataSet.lineWidth = 2
dataSet.valueTextColor = color
dataSet.valueFont = UIFont(name: "Avenir", size: 12)!
return dataSet
}
}
class CustomChartFormatter: NSObject, IAxisValueFormatter {
var days: [String]
init(days: [String]) {
self.days = days
}
public func stringForValue(_ value: Double, axis: AxisBase?) -> String {
return days[Int(value-1)]
}
}
I have a rudimentary ClockView build with SwiftUI. :) My question is if applying drop shadows to the clock-hands is easily possible with this approach or if i need a different layout and grouping of the elements? I've tried to find a way to add shadows to Path, but got stuck. Thank you.
Code
import SwiftUI
struct ClockView: View {
#Binding var time : TimeValue
let hoursHandWidth = 10
let minutesHandWidth = 10
let secondsHandWidth = 10
var body: some View {
return(
ZStack {
// clock-face
Path { path in
let seconds : Path = Path(CGRect(x: 100, y: -0.5, width: 10, height: 1))
for i in 0...60 {
…
}
}
.fill(Color(red: 0.3, green: 0.3, blue: 0.3, opacity: 1.0))
Path { path in
let hours : Path = Path(CGRect(x: 100, y: -1, width: 12, height: 2))
for i in 0...12 {
…
}
}
.fill(Color(red: 0.3, green: 0.3, blue: 0.3, opacity: 1.0))
Path { path in
let threehours : Path = Path(CGRect(x: 95, y: -2, width: 20, height: 4))
for i in 0...4 {
…
}
}
.fill(Color.red)
// clock-hands
Path { path in
let minutehand : Path = Path(CGRect(x: 0, y: -(minutesHandWidth/2), width: 95, height: minutesHandWidth))
path.addPath(minutehand, …)
}
.fill(Color.blue)
Path { path in
let hourhand : Path = Path(CGRect(x: 0, y: -(hoursHandWidth/2), width: 72, height: hoursHandWidth))
path.addPath(hourhand, …)
}
.fill(Color.blue)
Path { path in
let secondshand : Path = Path(CGRect(x: 0, y: -(secondsHandWidth/2), width: 97, height: secondsHandWidth))
path.addPath(secondshand, …)
}
.fill(Color.yellow)
.animation(.easeInOut)
Path { path in
path.addPath(Path(CGPath(ellipseIn: CGRect(x: -5, y: -5, width: 10, height: 10), transform: nil)))
}
.fill(Color.black)
}
.offset(CGSize(width: 150, height: 150))
.frame(width: 300, height: 300, alignment: .topLeading)
.scaleEffect(1.2)
.background(Color(red: 0.8, green: 0.8, blue: 0.8, opacity: 1.0))
)
}
}
Look
** Update **
I've applied .shadow(..) as user Asperi recommended:
Path { path in
let secondshand : Path = Path(CGRect(x: 0, y: -(secondsHandWidth/2), width: 97, height: secondsHandWidth))
path.addPath(secondshand, transform: .init(rotationAngle: 2.0 * CGFloat.pi * CGFloat(time.seconds-15)/60.0))
}
.fill(Color.yellow)
.shadow(color: .black, radius: 8, x: 1, y: 1)
But the result is not exactly what i expected :)
I've moved the transformation (rotation) from the subpath to the resulting path. Now it looks good.
Old:
Path { path in
let secondshand : Path = Path(CGRect(x: 0, y: -(secondsHandWidth/2), width: 97, height: secondsHandWidth))
path.addPath(secondshand, transform: .init(rotationAngle: 2.0 * CGFloat.pi * CGFloat(time.seconds-15)/60.0))
}
.fill(Color.yellow)
.shadow(color: .black, radius: 2)
New:
Path { path in
let secondshand : Path = Path(CGRect(x: 0, y: -(secondsHandWidth/2), width: 97, height: secondsHandWidth))
path.addPath(secondshand)
}
.fill(Color.yellow)
.shadow(color: .black, radius: 2)
.transformEffect(CGAffineTransform(rotationAngle: 2.0 * CGFloat.pi * CGFloat(time.seconds-15)/60.0))
Look (new):
Here is an example
Path { path in
let secondshand : Path = Path(CGRect(x: 0, y: -(secondsHandWidth/2), width: 97, height: secondsHandWidth))
path.addPath(secondshand)
}
.fill(Color.yellow)
.shadow(color: .black, radius: 8, x: 4, y: 1)
I have 3 stops at 0.4, 0.6 and 0.8 (red, green, blue). The maximum is 100 (for percent)
If I set the data as 50, I expect it to be green but it seems to be a mix of the green and red. It's only when I get to 60 that it's bright green that I expect.
Anyway to remove the gradient?
https://jsfiddle.net/sy3r2hj7/1/
var gaugeOptions = {
chart: {
type: 'solidgauge'
},
title: null,
pane: {
center: ['50%', '85%'],
size: '140%',
startAngle: -90,
endAngle: 90,
background: {
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || '#EEE',
innerRadius: '60%',
outerRadius: '100%',
shape: 'arc'
}
},
tooltip: {
enabled: false
},
// the value axis
yAxis: {
stops: [
[0.40, '#ff0000'],
[0.60, '#00ff00'], // yellow
[0.80, '#0000ff'] // red
],
lineWidth: 0,
minorTickInterval: null,
tickAmount: 2,
title: {
y: -70
},
labels: {
y: 16
}
},
plotOptions: {
solidgauge: {
dataLabels: {
y: 5,
borderWidth: 0,
useHTML: true
}
}
}
};
// The speed gauge
var chartSpeed = Highcharts.chart('container-speed', Highcharts.merge(gaugeOptions, {
yAxis: {
min: 0,
max: 100,
title: {
text: 'Speed'
}
},
credits: {
enabled: false
},
series: [{
name: 'Speed',
data: [60],
dataLabels: {
format: '<div style="text-align:center"><span style="font-size:25px;color:' +
((Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black') + '">{y}</span><br/>' +
'<span style="font-size:12px;color:silver">km/h</span></div>'
},
tooltip: {
valueSuffix: ' km/h'
}
}]
}));
Instead of using stops property, you can change the color of the point programmatically, based on some condition:
events: {
render: function() {
var point = this.series[0].points[0];
if (point.y < 40) {
point.graphic.attr({
fill: '#ff0000'
})
} else if (point.y < 60) {
point.graphic.attr({
fill: '#00ff00'
})
} else {
point.graphic.attr({
fill: '#0000ff'
})
}
}
}
Live demo: https://jsfiddle.net/BlackLabel/fw594Lmg/
I wanted to extract each of the sprites in the following sprite sheet.
Provided with the key-value of sprite origin points in the sheet.
each sprite into its own SKSpriteNode object
I think through using SKTexture somehow
{
CACTUS_LARGE: { x: 652, y: 2 },
CACTUS_SMALL: { x: 446, y: 2 },
CLOUD: { x: 166, y: 2 },
HORIZON: { x: 2, y: 104 },
MOON: { x: 954, y: 2 },
PTERODACTYL: { x: 260, y: 2 },
RESTART: { x: 2, y: 2 },
TEXT_SPRITE: { x: 1294, y: 2 },
TREX: { x: 1678, y: 2 },
STAR: { x: 1276, y: 2 }
}
Sample Chart
When I provide data for Bar Chart it appears with little offset. I thought about stacked Bar Chart, but it was wrong - that how I provide sample data for chart:
var barEntries = [BarChartDataEntry]()
barEntries.append(BarChartDataEntry(x: 0, y: 0))
barEntries.append(BarChartDataEntry(x: 4, y: 1))
barEntries.append(BarChartDataEntry(x: 8, y: 24))
barEntries.append(BarChartDataEntry(x: 12, y: 37))
barEntries.append(BarChartDataEntry(x: 16, y: 27))
barEntries.append(BarChartDataEntry(x: 20, y: 11))
let barDataSet = BarChartDataSet(values: barEntries, label: nil)
let barData = BarChartData(dataSet: barDataSet)
barData.barWidth = 4
barChartView.data = barData
All barEntries was created with BarChartDataEntry initializers for non-stacked bar. Now I have no idea why bar doesn't start at 0.
try set barChartView.leftAxis.axisMinimum = 0 or 'barChartView.rightAxis.axisMinimum = 0' or barChartView.xAxis.axisMinimum = 0. Check ChartsDemo.
initialise barEntries with [BarChartDataEntry(x: 0, y: 0)] rather than appending BarChartDataEntry(x: 0, y: 0).