How to draw Euler diagram with highcharts library? - charts

I want to draw a chart like the following image. How can I do that using Highcharts library?
I am able to get concentric circle in highcharts but not like this. Please help.
Or suggest me a library if the job can be done with that. Thank you in advance.

You can use venn series type and manually position circle elements in the load event, for example:
chart: {
events: {
load: function() {
var points = this.series[0].points,
point1R = points[0].shapeArgs.r;
points[1].graphic.attr({
x: points[1].graphic.getBBox().x - (point1R - points[1].shapeArgs.r)
});
points[2].graphic.attr({
x: points[2].graphic.getBBox().x - (point1R - points[2].shapeArgs.r)
});
}
}
}
Live demo: https://jsfiddle.net/BlackLabel/padhgfe9/1/
API Reference: https://api.highcharts.com/highcharts/series.venn

Related

Echarts dataZoom slider handleIcon shape not working

In the echarts docs at https://echarts.apache.org/en/option.html#dataZoom-slider.handleIcon the handle icon for data zoom slider has shape options like "circle", "rectangle" etc.
However these shapes doesn't seem to work.
If we specify dataZoom: [{ handleIcon: "circle" }] the handle icon just disappears.
Is the implementation for this API still pending or else?
You misinterpreted the documentation. The method handleIcon expects a string of path but not some shape identifier. Please take a look at the tests where you can found how to use this method.
However, you can define the icons outside of the chart configuration and use inside with identifier:
var icons = {
circle: 'M17.498,11.697c...',
square: 'M17.498,11.697c...'
}
var option = {
//...
dataZoom: [{ handleIcon: icons['circle'] }]
}

How to avoid polygon distortion when zooming?

Here is a full jsfiddle example
I use a custom series and draw a polygon:
data = [
[80.9251933067, 207.9047427038],
[52.8853803102, 337.7443022089],
[25.9926385814, 120.3586150136]
];
I use echarts.graphi.clipPointsByRect() (like in this echarts-example) to make sure, the polygon is not drawn outside of the grid.
echarts.graphic.clipPointsByRect(points, {
x: params.coordSys.x,
y: params.coordSys.y,
width: params.coordSys.width,
height: params.coordSys.height
})
Initially the polygon is drawn correctly, like this:
But when I zoom in, the polygon is distorted: e.g. you can click the zoom part buttom below the chart to zoom from 40 to 60 - in this case I'd expect to see the part of the shape (like highlighted in yellow in the image above) - but instead I see this distorted image:
Maybe this function is not meant for this use-case, or is this a bug?
Is there another function for this use-case or does anyone know a workaround?
Update
Version 4.4.x contains a new clip feature. This makes it easy to avoid the distortion:
in the render function we don't need to clip our shapes: i.e. no need to call clipPointsByRect()
instead we just activate clip on the custom series:
New series definition with clip: 'true':
series: [{
type: 'custom',
clip: 'true',
renderItem: renderItem,
data: data
}]
Here is an updated jsfiddle expample
Original Version
it seems that the function is really not working as expected - see echarts-source code comment:
export function clipPointsByRect(points, rect) {
// FIXME: this way migth be incorrect when grpahic clipped by a corner.
// and when element have border.
I've created an issue #10222 for the e-charts project
A workaround for now is to use a custom clipping function
e.g. lineclip supports the Sutherland-Hodgman algorithm for polygon clipping
Here is the updated jsfiddle-example that shows the correct result when you zoom in:

How to link zoom in different charts in echarts

We have multiple charts with zoom. Is there a way to link all this charts so they always have the same zoom factor when the user zoom in one of the charts?
When having multiple grids in the same chart is not a possibility, I use this trick to do the job:
myChart.on('datazoom', function (evt) {
var zoom = myChart.getOption().dataZoom[0];
myOtherChart.dispatchAction({
type: 'dataZoom',
dataZoomIndex: 0,
startValue: zoom.startValue,
endValue: zoom.endValue
});
});
Both charts have dataZoom, in my case I hide the one in myOtherChart.
If you've got more events to track, creating the action can be simplified by letting echarts create it:
["datazoom", "legendselectchanged", /* more events*/].forEach((eventType: string) => {
this.chartInstance1.on(eventType, (event) => {
// Automatically create an action from the event
let newEvent = this.chartInstance1.makeActionFromEvent(event);
// Dispatch it directly
this.chartInstance2.dispatchAction(newEvent);
});
})
For everyone who wants to go further, also synchronizing mouse, legend and magic events, its easier to use the connect function.
Template:
// chart 1
<div echarts (chartInit)="onChartInit($event)"></div>
// chart 2
<div echarts (chartInit)="onChartInit($event)"></div>
Typescript:
import { connect, ECharts } from "echarts";
// ...
onChartInit(chart: ECharts) {
this.charts.push(chart);
if (this.charts.length === 2)
// This will do the magic out of the box
connect([charts[0], charts[1]]);
}

chartJS - points overplotting, jittering, noise?

Hey I'm using chartJS and I have a graph that looks like this:
As you can see the data points overlap each other which makes it harder to read. In RStudio there is a solution for that you simply set position="jittering" and it will add a slight noise around the dots.
Unfortunately, there is no such capability in chart.js today. However, that doesn't mean you can't still get the functionality that you want. There are a couple of options that come to mind.
1) Implement your own jitter function and use it to pre-process your data before passing to chart.js. Here is an example.
var jitter = function(data) {
return data.map(function(e) {
var xJitter = Math.random() * (-1 - 1) + 1;
var yJitter = Math.random() * (-1 - 1) + 1;
return {
x: e.x + xJitter,
y: e.y + yJitter,
}
});
};
Here is a codepen example showing a side by side example of charts with original and jittered data.
2) Use the jitter function above and add it as a chart.js plugin such that you can enable/disable it automatically in any given chart. Here is an example (note that we are using the jitter function above.
Chart.plugins.register({
afterInit: function(chartInstance) {
if (chartInstance.config.options.jitter) {
var helpers = Chart.helpers;
var ctx = chartInstance.chart.ctx;
chartInstance.data.datasets.forEach(function (dataset) {
dataset.data = jitter(dataset.data);
});
}
}
});
Then just add this into your charts options config.
options: {
jitter: true,
}
Here is a codepen example showing a side by side example of charts with original and jittered data using the plugin.
Obviously, you would want to implement a much more robust jitter function that accepts some sort of jitter options so that it can be intelligently applied to any type of dataset. I'll leave that for you to implement if you decide to take this approach.

jqPlot- issue with displaying bar charts -axis padding and inter-bar distance

I'm using the following piece of code to display a set of bar charts in jqPlot. However, I am getting 2 problems:
There is no padding on either side of the range values for the xaxis. The pad attribute seems to have no effect.
When the number of bars is large, the bars overlap on top of each other. The barPadding attribute seems to have no effect.
I looked at this link Having problems with jqPlot bar chart . The answer suggested there was to use a CategoryAxisRenderer. But since I'm using time-series data, I require the DateAxisRenderer.
Please help.
function plotBarGraph(data,myticks,series)
{
$("#placeholder").empty();
$.jqplot('placeholder',data,
{
//stackSeries:true,
seriesDefaults:{
renderer:$.jqplot.BarRenderer,
barMargin:1,
barPadding:0.5
},
axes:
{
xaxis:
{
ticks:myticks,
tickInterval:10,
renderer:$.jqplot.DateAxisRenderer,
pad:2.5,
tickOptions:
{
formatString:'%d-%m-%y'
}
}
},
legend:
{
show:true,
labels:series
}
});
}
In this case if you do not want to use the approach mentioned in the link, you might want to play with min/max values for your date axis.
I think you might also find useful the approach to a similar sort of problem with padding where I chose to set ticks on creation and hide the unwanted ones after the plot is drawn.
Before I can be of any further assistance please provide a sample presenting your problem.
For your second problem, I ran into a similar issue. I set up a selection statement that widened the size of my chart depending on how many bars would be in it. I then made the parent div scrollable (called "dataHolder"), and that solved the problem.
// set div properties depending on how many sets of data are in the
//array so the view is sized properly
$("#chartDiv").html("").css("width", "750px"); // chartDiv's default settings
$("#tabs-6").removeClass("dataHolder").css("width", "900px"); // parent Div's default settings
if (dataArray.length > 10) {
$("#chartDiv").css("width", "1600px");
$("#tabs-6").addClass("dataHolder").css("width", "900px");
} else if (dataArray.length > 6) {
$("#chartDiv").css("width", "1200px");
$("#tabs-6").addClass("dataHolder").css("width", "900px");
}
I found a solution to use Date data with CategoryAxisRenderer. You have to configure de xaxis like follows:
axes: {
xaxis: {
renderer: $.jqplot.CategoryAxisRenderer,
rendererOptions: {
tickRenderer: $.jqplot.DateTickRenderer,
tickOptions: {
formatter: $.jqplot.DateTickFormatter,
formatString:'%d/%m'
}
}
}
}
I hope it helps! ;)