I am trying to figure out a way to programmatically highlight or select a data point on a HighCharts graph.
So far I have not figured out how to pull a HIPoint out of a series, much less select that point. Also, if there is a way to get the tooltip hover to show up programmatically, rather than simply selecting the data point, that would be even better.
I have found many examples of how to do this in JavaScript, but the method of series[i].data[i].select() doesn't work in Swift, because data is [Any], and you can only set select on a HIPoint.
options.series[0].data[3].select() // doesn't work
(options.series[0].data[3] as! HIPoint).select() // crashes, because Any can't be converted into HIPoint
Data point on series[0] point[3] should be selected, or bring up the tooltip, but I can't figure out how to access the HIPoint to do anything with it at all.
You can add the HIPoint class object to the data:
let options = HIOptions()
let chart = HIChart()
chart.type = "line"
options.chart = chart
let title = HITitle()
title.text = "Demo chart"
options.title = title
let line = HILine()
let point = HIPoint()
point.y = 71.5
line.data = [29.9, point, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
options.series = [line]
And refer to the point in this way:
let point = self.chartView.options.series[0].data[1] as! HIPoint
point.select()
Related
I need to bind click event handler for the icon in the red rectangle zone,bind different click event handler for the blue rectangle zone.
right now ,i have no idea how to make it work, any help will be appreciate
example and codes
I figure out an solution.
You can add an icon dom after the label by manual, like below codes.
var myChart = echarts.init(document.getElementById('main'));
var option = {
// your options
};
const parent = myChart.getDom().parentElement;
const xPixel = myChart.convertToPixel({ xAxisIndex: 0 }, 2) // to get the x postion of target category
var div = document.createElement('img')
div.style = `position: absolute;top: 366px;height: 12px;left:${xPixel + 2 * 14}px` // 2 * 14 is in order to correct the left
div.src = 'image path'
div.addEventListener('click', () => {})
if (parent) parent.appendChild(div)
You can change top or left to correct the icon position.
If somebody have greater solution, plz let me know.
I've spent a few days trying to bind my data model to a lineseries. I works fine; however, I want to change the line color. I knew where to change the color, yet the chart and series would ignore my binding (was a SolidColorBrush). If I hard-coded the color in XAML it would work; however, if I tried to bind the same property to the color property in my view model it would not work. After too much time was spent I gave up for 2 reasons.
It just wouldn't work
I realized I was going to need to bind 'x'
number of view models to the chart to show more than one line series
at a time.
I eventually just defined my line series in the code behind like so...
LineSeries BuildLine(DosePointsViewModel model)
{
LineSeries series = new LineSeries();
// styles
Style poly = new Style(typeof(Polyline));
poly.Setters.Add(new Setter(Polyline.StrokeProperty, model.LineColor));
poly.Setters.Add(new Setter(Polyline.StrokeThicknessProperty, 3d));
series.PolylineStyle = poly;
Style pointStyle = new Style(typeof(LineDataPoint));
pointStyle.Setters.Add(new Setter(LineDataPoint.BackgroundProperty, model.LineColor));
series.DataPointStyle = pointStyle;
// binding
series.IsSelectionEnabled = false;
series.IndependentValueBinding = new System.Windows.Data.Binding("Distance");
series.DependentValueBinding = new System.Windows.Data.Binding("Dose");
// X axis
LinearAxis xAxis = new LinearAxis();
xAxis.Title = "Distance";
xAxis.ShowGridLines = false;
xAxis.Interval = 1;
xAxis.Orientation = AxisOrientation.X;
series.IndependentAxis = xAxis;
// Y axis
LinearAxis yAxis = new LinearAxis(); //series.DependentRangeAxis as LinearAxis;
yAxis.Maximum = 5000d;
yAxis.Minimum = -100d;
yAxis.Minimum = model.Points.Min(d => d.Dose) - model.Points.Min(d => d.Dose) * 0.50;
yAxis.Maximum = model.Points.Max(d => d.Dose) + model.Points.Max(d => d.Dose) * 0.05;
yAxis.ShowGridLines = true;
yAxis.Orientation = AxisOrientation.Y;
yAxis.Title = "Dose";
Style s = new Style(typeof(Line));
s.Setters.Add(new Setter(Line.StrokeProperty, new SolidColorBrush(Colors.LightBlue)));
s.Setters.Add(new Setter(Line.StrokeThicknessProperty, 1d));
yAxis.GridLineStyle = s;
series.DependentRangeAxis = yAxis;
return series;
}
Now, the color for my line series works. Of course, the primary reason for this is that I'm directly setting the color via ...
poly.Setters.Add(new Setter(Polyline.StrokeProperty, model.LineColor));
pointStyle.Setters.Add(new Setter(LineDataPoint.BackgroundProperty, model.LineColor));
So, my question is this. I want to be able to add multiple line series to the chart; however, when I try to do this, only the last item is being bound. Inside the code, this is done for each line series being created. Only the last line series is added to the chart.
DosePointsViewModel model = new DosePointsViewModel(_snc, m.Id);
LineSeries series = BuildLine(model);
DoseChart.Series.Clear();
DoseChart.Series.Add(series);
Wow, as I'm reading my question I realize that I am calling
DoseChart.Series.Clear();
Well that was an interesting find.
Im trying to make a graph like this:
https://www.google.com/finance?q=BCBA:PAMP
I have a line chart in chart.js, now I want to add labels (like the letters A, B, C) for certain dates.
Can't find a doc/example to start from. Any idea?
If its more simple to do with another library a recommendation is more than welcome.
Thanks!
Unfortunately, there is no native support in chart.js for what you are wanting. However, you can certainly add this capability using the plugin interface. This requires that you implement your own logic to draw the canvas pixels at the locations that you want them. It might sound challenging, but its easier than it sounds.
Here is an example plugin that will add a value above specific points in the chart (based upon configuration).
Chart.plugins.register({
afterDraw: function(chartInstance) {
if (chartInstance.config.options.showDatapoints || chartInstance.config.options.showDatapoints.display) {
var showOnly = chartInstance.config.options.showDatapoints.showOnly || [];
var helpers = Chart.helpers;
var ctx = chartInstance.chart.ctx;
var fontColor = helpers.getValueOrDefault(chartInstance.config.options.showDatapoints.fontColor, chartInstance.config.options.defaultFontColor);
// render the value of the chart above the bar
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize + 5, 'normal', Chart.defaults.global.defaultFontFamily);
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
ctx.fillStyle = fontColor;
chartInstance.data.datasets.forEach(function (dataset) {
for (var i = 0; i < dataset.data.length; i++) {
if (showOnly.includes(dataset.data[i])) {
var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model;
var scaleMax = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._yScale.maxHeight;
var yPos = (scaleMax - model.y) / scaleMax >= 0.93 ? model.y + 20 : model.y - 5;
ctx.fillText(dataset.data[i], model.x, yPos);
}
}
});
}
}
});
It allows you to configure which points you want to annotate using this new configuration. The showOnly option contains the points that you want to label.
options: {
showDatapoints: {
display: true,
showOnly: [3, 10, 9]
},
}
Obviously, this only adds the datapoint value at the specified points, but you can just change the plugin to paint whatever you want to show instead. Simply replace ctx.fillText(dataset.data[i], model.x, yPos) with different code to render something different on the canvas.
Here is a codepen example to show you want it looks like.
Wow, I've really fallen down the rabbit hole. I'm trying to have text on the background of part of a UI and a text field as another part, e.g. the birthday in:
I then want to repurpose that text filed to allow text entry. So I do something like:
myTextFieldName.editable = true
myTextFieldName.backgroundColor = NSColor.textBackgroundColor()
and I get something like:
Which is all well and good, but then I note the nice thin border around the text field below it. So I think, I need a border! I add one with:
myTextFieldName.bordered = true
...and I get:
Pow! What a hideous strange thick border! It doesn't look like the default text field border at all! For the life of me, I can't figure out how to make the border of my "activated" text field match that of the default. Any ideas?
Many thanks in advance!
Need to set border and border color:
myTextFieldName.wantsLayer = true
myTextFieldName.layer?.borderColor = NSColor(red:204.0/255.0, green:204.0/255.0, blue:204.0/255.0, alpha:1.0).cgColor
myTextFieldName.layer?.borderWidth = 1.0
myTextFieldName.layer?.cornerRadius = 0.0
Set corner radius if you want rounded corner.
You can add borders to NSTextfield and customise it according how you want it.
let border = CALayer()
border.borderColor = NSColor.gray.cgColor
border.autoresizingMask = [.layerHeightSizable, .layerWidthSizable]
border.borderWidth = 1.0
myTextFieldName.wantsLayer = true
myTextFieldName.layer?.addSublayer(border)
myTextFieldName.layer?.masksToBounds = true
I want to select two or more markers in a chart and perform an action using their coordinates.
Selecting the points is the main problem since I didn't find anything on this topic and I'm not sure if it can be done.
I did something like this in a Pie Chart.
What I did was use "connectToPlot" to change the series color when the user click on it.
This is a resume of the work that I did: change series color when user click on it
See that when you click on the serie, the color changes to gray and if you click again the series returns to it original color (saved it in the attribute "originalColor").
pieChart.connectToPlot("default", function(evt) {
var shape = evt.shape;
var type = evt.type;
if (type == "onclick") {
var fillColor = "rgb("+shape.fillStyle.r+", "+shape.fillStyle.g+", "+shape.fillStyle.b+")"; console.log(shape.fillStyle);
if(shape.rawNode.getAttribute("originalColor")==null)
shape.rawNode.setAttribute("originalColor",fillColor);
var strokeColor = "rgb("+shape.strokeStyle.color.r+", "+shape.strokeStyle.color.g+", "+shape.strokeStyle.color.b+")";
if(fillColor=='rgb(238, 238, 238)'){
shape.setFill(shape.rawNode.getAttribute("originalColor"));
shape.setStroke(shape.rawNode.getAttribute("originalColor"));
}else{
shape.setFill('rgb(238, 238, 238)');
shape.setStroke(shape.rawNode.getAttribute("originalColor"));
}
}