Custom legends in Swift Charts for iOS 16 - swift

How do I obtain colour imagery, or more generally, styling information for each legend entry to construct a custom legend in a chart in Swift Charts?
I have a chart here, with a legend positioned on the right, but using the content: argument of chartLegend does not pass any info into the closure to use. I would like to wrap the legend into a scroll view, so when there are too many entries, the chart will appear correctly on the screen, and the user can scroll through the legend below the chart.
Chart(points, id: \.self) { point in
LineMark(
x: .value("time/s", point.timestamp),
y: .value("potential/mV", point.potential)
)
.foregroundStyle(by: .value("Electrode", point.electrode.symbol))
}
.chartLegend(position: .bottom)
// ...
Here is the chart with too many legend entries interfering with the chart sizing, resulting in cropping:
And here is the chart with only a few entries so that the chart is sized correctly, with no cropping, and the legend has text to discern between the electrodes they represent:
Any help is much appreciated.

Not scrolling but the chart legend can be placed on the side with code like this:
.chartLegend(position: .trailing, alignment: .top)
This gives more room for a legend. The legend won't scroll but all the items will be listed even if going past the end of the chart. The frame height can be increased. The example shows a before(default) and after(using the code above).
The colors can be assigned manually using the chartForegroundStyleScale like this after the end of the chart:
.chartForegroundStyleScale([
"Hong Kong": Color.green,
"London": Color.red,
"Taipei": Color.purple,
"New York": Color.teal,
"Paris": Color.pink,
"Sydney": Color.orange
])
Symbols can be created based on the series:
.symbol(by: .value("City", series.city))

Related

ECharts: dataset with bars colored based on category name?

I'd like to be able to control bar colors based on xAxis/category label name, throughout multiple charts, while using the dataset.source option of feeding data.
I'm guessing the solution might involve using visualMap?
customColors = {
x1: '#123',
x2: '#456',
x3: '#789',
...
}
I don't think visualMap is the way to do this, you probably want to set the colors in series:
https://echarts.apache.org/en/option.html#series-bar.data.itemStyle.color
or define a color palette:
https://echarts.apache.org/en/option.html#color
Echarts should color the chart by series by default:
https://echarts.apache.org/en/option.html#series-bar.colorBy

In mixed chart containing bars and a line, how to extend the line outside of the chart in both directions?

I have this chart, which has line and bars:
Is it possible to somehow extend the line outside of the chart in both directions? This line serves an important role, it is sort of a "limit" for bars, I just don't want for it to start at the center of the first bar, and to end at the center of the final bar.
I can extend it to the right by simply extending the dataset of the line, but is it possible to extend it also to the left somehow?
I figured out answer based on answer from this question: Is it able to align line chart at left margin in mixed chart?
I'm extending line type like this:
Chart.controllers.LineNoOffset = Chart.controllers.line.extend({
updateElement: function(point, index, reset) {
Chart.controllers.line.prototype.updateElement.call(this, point, index, reset);
const meta = this.getMeta();
const xScale = this.getScaleForId(meta.xAxisID);
point._model.x = xScale.getPixelForValue(undefined, index-0.5);
},
});
Now the LineNoOffset type of the line will start from the left border of the chart, which fulfills my need.

bar chart display all cateogries

I have a bar chart. It has 25 bars all representing a different category. The chart is fine however it only prints out a few of the categories.
I thought by using the line below that it would display all 25 categories that I have specified in x_labels.
set(gca,'XtickL',x_labels);
I also use the method rotateXLabel and rotate the labels 90 degrees so they are not over writing each other. However still only display some of the categories. How can I display all of them?
update
Here is my data,
'Health Care' 4.72629799981083
'Capital Goods' 4.09458147368759
'Transp' 3.98149295925542
'Media' 1.79439005788530
'Insurance' 1.69956150439052
'Commer Serv' 1.39773924375053
'Food & Staples' 1.37870312358688
'Tech Hardw' 1.14006008338028
'Div Finan' 1.07437424540054
'Retailing' 0.799227696500581
'Cons Durab' 0.484704646767555
'Semiconduct' -0.0668927175281457
'Cons Serv' -0.0994263844790881
'Software' -1.13770277184728
'Auto&Comp' -1.14193637823934
'Materials' -1.52052729345776
'Real Estate' -1.58166267932780
'HH & Prod' -1.68076878183555
'Food Bever' -1.73283367572542
'Pharma' -1.90119783888618
'Telecom' -2.04480219189470
'Utilities' -2.20510498991084
'Energy' -2.36405808621777
'Banks' -5.09421924506606
another update
Found the solution here. Its not quite 100% perfect though as some of my labels are too long so the chart cuts them off. Need to work out how to get round that issue
[pp,h1,h2]=plotyy((1:length(risk_tot)),risk_tot,(1:length(risk_tot)),risk_cont,'bar','stem');
xData = get(h1,'XData');
set(gca,'Xtick',linspace(xData(1),xData(end),length(x_labels(:, 1))));
Is this what you are looking for?:
value is vector with the provided values
label is a cell with the provided strings
bar(value);
set(gca, 'XTick', 1:length(value))
set(gca, 'XTickLabel', label)
grid on
rotateXLabels(gca(), 90)

google charts annotations show right side of point

I am using google charts for plotting a graph
How can I show annotation of the point at right-hand-side of the point but it showing on the top of point
http://i.stack.imgur.com/UHhQH.png
I want it like as follow
http://i.stack.imgur.com/lUBcq.png
Please any one help me out
You can actually change the position of the annotations, by using css tranform.
You should first get a handle to the anntation text, if you want to change all the text, then you can use the text tag name in css
text {
transform: translate(10px, 30px);
}
I was able to adjust annotations to the right by doing 2 things:
1) Entered some white spaces (\u00A0 is white space) and a long dash (—) on the left side of the desired annotation.
2) Added stem length of -3.
var dataTable = new google.visualization.DataTable();
dataTable.addColumn('string', 'Model');
dataTable.addColumn('number', 'T');
dataTable.addColumn({type:'string', role:'annotation'});
dataTable.addRows([
['ABC',30,'\u00A0\u00A0\u00A0\u00A0 — X'],
['DEF',20,'\u00A0\u00A0\u00A0\u00A0 — Y'],
['GHI',10,'\u00A0\u00A0\u00A0\u00A0 — Z'],
]);
var options = {
1: {annotations: {stem: {length: -3}}
};

How the legends on Google charts can be wrapped

I need the legends of Google chart to get wrapped (comes in new line) automatically if it exceeds container area.
I don't want scroll button as it is not enough convenient.
With available customization options, seems it cannot be done.
Any other way?
Use the maxLines property for the legend.
i.e.:
options.legend = {position: 'top', maxLines: 5};
Note that this undocumented property only works if the legend is positioned at the top and there is enough vertical space to render both the chart and multi-line legend.
with the maxLines property for the legends, chartArea with specific set of values can help in rendering the display.
legend: { position: "top", alignment: "start", maxLines: 2 },
chartArea: {top:50,bottom:30,right:0,left:50, 'width': '100%' }
I did a lot of testing of this and it seems that you need to have chartArea width and height set to 'auto'. Still not perfect but sort of OK.