Closed ivishalsingh1986 closed 5 months ago
Hi @ivishalsingh1986!
We are looking into this matter. Thank you for your patience. I will let you know as soon as I have more information.
Could you tell me how do you get this maxPoint
and minPoint
?
Hi @MikolajMichalczak Thanks for looking into it.
maxPoint
and minPoint
are dynamic values and can varies, we draw the HIPolotLines()
on these points on xAxis, We gets one more point Z
between maxPoint
and minPoint
, Its our requirement to draw the circle considering the Z
point as center of the circle and it should touch the maxPoint
/ minPoint
which ever is nearest or touch the both if its in exact center of both points, so we can calculate the distance on xAxis and using as radius of the circle but the circle is not plot as expecting radius on graph. Please let me know if you need any other details.
@ivishalsingh1986, thank you for the detailed explanation.
First of all, scatter.marker.radius
is specified in pixels, so in your example, a 6 px radius is indeed small. As you noticed, there is no native method for mobile wrappers like toPixels()
. Therefore, I suggest utilizing HIFunction
with a JavaScript function passed as a string.
Let's use the following chart as an example:
let options = HIOptions()
let minPoint = 180 as NSNumber
let maxPoint = 190 as NSNumber
let chart = HIChart()
chart.type = "scatter"
options.chart = chart
let xAxis = HIXAxis()
xAxis.title = HITitle()
xAxis.title.text = "Height (cm)"
let yAxis = HIYAxis()
yAxis.title = HITitle()
yAxis.title.text = "Weight (kg)"
options.yAxis = [yAxis]
let plotLines = HIPlotLines()
plotLines.width = 2
plotLines.value = minPoint
let plotLines2 = HIPlotLines()
plotLines2.width = 2
plotLines2.value = maxPoint
xAxis.plotLines = [plotLines, plotLines2]
options.xAxis = [xAxis]
let series = HIScatter()
series.color = HIColor(name: "rgba(223, 83, 83, .5)")
series.data = [[175.0, 65.6], [195.3, 71.8], [193.5, 80.7], [185, 72.6], [187.2, 78.8]]
options.series = [series]
As we can see, there is one point with an x
value of 185 and two HIPlotLines()
at minPoint
(180) and maxPoint
(190):
Next, we can use the following JavaScript, where we select a specific point (or iterate over all points if needed) and set its marker radius to half the distance between minPoint
and maxPoint
converted to pixels:
function() {
const chart = this;
const point = chart.series[0].points[3];
const pxMin = chart.xAxis[0].toPixels(minPoint, true);
const pxMax = chart.xAxis[0].toPixels(maxPoint, true);
const pxDistance = pxMax - pxMin;
point.update({
marker: {
enabled: true,
radius: pxDistance / 2
}
});
}
We need to add this function to the load event:
let options = HIOptions()
let minPoint = 180 as NSNumber
let maxPoint = 190 as NSNumber
let chart = HIChart()
chart.type = "scatter"
options.chart = chart
chart.events = HIEvents()
chart.events.load = HIFunction(jsFunction: "function() { const chart = this; const point = chart.series[0].points[3]; var pxMin = chart.xAxis[0].toPixels(\(minPoint), true); var pxMax = chart.xAxis[0].toPixels(\(maxPoint), true); var pxDistance = pxMax - pxMin; point.update({ marker: { enabled: true, radius: pxDistance/2 } }); }")
Hi @MikolajMichalczak , Thanks a lot for your support, Your given solution is worked fine as per our need. Thanks!
I have a related question, As we draw a big circle if another smaller circle comes inside that big one I need to change the color of small circle if its outside the big circle it should be different color. I tried using the C1C2 = sqrt((x1 – x2)2 + (y1 – y2)2)
formula with in the HIFunction
bit it did't work out as I think X and Y axis have different pixel values.
Please suggest how can we achieve this using the same graph, Is HIchart using scatter graph API itself have any inbuilt function to determine this.
Thanks :)
@ivishalsingh1986 Do you mean when it is fully inside or just when it intersects?
@MikolajMichalczak I mean fully inside
@ivishalsingh1986 First of all, when one marker covers another, there is a slight distinction between their colors (I mean the intensity of the color). Therefore, if you want completely different colors, you have to implement it by yourself.
Basically, you need to convert the coordinates of both points to pixels and then check if a circle lies inside another using the formula (distance + radiusSmall <= radiusBig
). The JavaScript code could look as follows:
function() {
const chart = this;
const pointBig = chart.series[0].points[3];
const pxMin = chart.xAxis[0].toPixels(\(minPoint), true);
const pxMax = chart.xAxis[0].toPixels(\(maxPoint), true);
const pxDistance = pxMax - pxMin;
const radiusBig = pxDistance / 2;
const radiusSmall = 20;
pointBig.update({
marker: {
enabled: true,
radius: radiusBig
}
});
const pointSmall = chart.series[0].points[4];
const pointSmallXPx = chart.xAxis[0].toPixels(pointSmall.x, true);
const pointSmallYPx = chart.yAxis[0].toPixels(pointSmall.y, true);
const pointBigXPx = chart.xAxis[0].toPixels(pointBig.x, true);
const pointBigYPx = chart.yAxis[0].toPixels(pointBig.y, true);
const markersDist = parseInt(Math.sqrt(((pointSmallXPx - pointBigXPx) * (pointSmallXPx - pointBigXPx)) + ((pointSmallYPx - pointBigYPx) * (pointSmallYPx - pointBigYPx))));
if (markersDist + radiusSmall <= radiusBig) {
pointSmall.update({
marker: {
fillColor: 'blue'
}
});
};
}
The iOS code will look like this:
let options = HIOptions()
let minPoint = 180 as NSNumber
let maxPoint = 190 as NSNumber
let chart = HIChart()
chart.type = "scatter"
options.chart = chart
chart.events = HIEvents()
chart.events.load = HIFunction(jsFunction: "function() {const chart = this; const pointBig = chart.series[0].points[3]; const pxMin = chart.xAxis[0].toPixels(\(minPoint), true);const pxMax = chart.xAxis[0].toPixels(\(maxPoint), true);const pxDistance = pxMax - pxMin;const radiusBig = pxDistance / 2; const radiusSmall = 20; pointBig.update({marker: {enabled: true,radius: radiusBig}}); const pointSmall = chart.series[0].points[4]; const pointSmallXPx = chart.xAxis[0].toPixels(pointSmall.x, true); const pointSmallYPx = chart.yAxis[0].toPixels(pointSmall.y, true); const pointBigXPx = chart.xAxis[0].toPixels(pointBig.x, true); const pointBigYPx = chart.yAxis[0].toPixels(pointBig.y, true); const markersDist = parseInt(Math.sqrt(((pointSmallXPx - pointBigXPx) * (pointSmallXPx - pointBigXPx)) + ((pointSmallYPx - pointBigYPx) * (pointSmallYPx - pointBigYPx)))); if (markersDist + radiusSmall <= radiusBig) { pointSmall.update({ marker: { fillColor: 'blue'} });};}")
let xAxis = HIXAxis()
xAxis.title = HITitle()
xAxis.title.text = "Height (cm)"
let yAxis = HIYAxis()
yAxis.title = HITitle()
yAxis.title.text = "Weight (kg)"
options.yAxis = [yAxis]
let plotLines = HIPlotLines()
plotLines.width = 2
plotLines.value = minPoint
let plotLines2 = HIPlotLines()
plotLines2.width = 2
plotLines2.value = maxPoint
xAxis.plotLines = [plotLines, plotLines2]
options.xAxis = [xAxis]
let series = HIScatter()
let marker = HIMarker()
marker.radius = 20
series.marker = marker
series.color = HIColor(name: "rgba(223, 83, 83, .5)")
series.data = [[175.0, 65.6], [195.3, 71.8], [193.5, 80.7], [185, 72.6], [187.2, 72.8]]
options.series = [series]
I simply changed one point's coordinates to be inside another marker and retrieved them by indexes statically. If you would like to make it more dynamic, you have to iterate over all points and enhance it by yourself.
Hi @MikolajMichalczak Thanks a lot for your support :), Your given solution is worked fine as per our need. Thanks...
In iOS swift I used Scatter graph to draw circle, to get the radius of circle I have two points min and max on xAxis, radius = (maxPoint - minPoint)/2, but it plot very small circle
In attached graph radius = (22 - 9) / 2 = 6 but its plotting very small graphs, How can convert this pointValue to pixelValue to touch this circle to vertical line, please suggest.