Specifically I am looking to add text annotations to specific locations to a JFreeChart that is being output to a png file for web use. Can/how do annotations get added to pie charts. I have been able to successfully add annotations to XYPlots, but don't know how to overlay or add one to a PiePlot.
My full task is to use the PiePlot to create a sort of clock. So far everything has worked great, but now I need to add labels at the 12, 3, 6, and 9 o'clock locations and completely stumped.
Adam
Bit of an old question, but here's how I did something similar (annotation at 1, 2, 3, ... o'clock positions) using a polar plot. It uses a ChoiceFormatter and the NumberTickUnit:
final JFreeChart chart = ChartFactory.createPolarChart(
"HAPI Hourly Usage (UTC)", ds, true, true, false);
final PolarPlot plot = (PolarPlot) chart.getPlot();
// Create a ChoiceFormat to map the degrees to clock positions
double[] limits = new double[12];
String[] formats = new String[12];
limits[0] = 0;
formats[0] = "12";
// degrees = 360/12
for (int i = 1; i < limits.length; i++) {
limits[i] = degrees * (i);
formats[i] = Integer.toString(i);
}
ChoiceFormat clock = new ChoiceFormat(limits, formats);
TickUnit tickUnit = new NumberTickUnit(degrees, clock);
// now configure the plot
plot.setAngleTickUnit(tickUnit); // sets the ticks
plot.setAngleLabelsVisible(true); // makes the labels visible
plot.setAngleLabelPaint(Color.LIGHT_GRAY); // user choice
plot.setAngleGridlinesVisible(true); // must set this to display the
// labels
plot.setAngleGridlinePaint(Color.BLACK); // plot's background color
// (makes lines invisible)
plot.setRadiusGridlinesVisible(false); //turn off the radius value circles
ValueAxis axis = plot.getAxis();
axis.setTickLabelsVisible(false); //turn off the radius value labels
winds up looking like http://img522.imageshack.us/img522/6693/hapihours.jpg
After a fairly strenuous search I don't believe this is currently possible (JFreeChart 1.0.13).
Possible options are:
Create a second chart with an XYPlot to generate a second image with needed annotations. Overlay this image on the page. This option is bad because it doubles the number of chart images to be uploaded.
Set the image as a background on the page and HTML the text over the image. Bad because it isn't maintainable and makes a headache of data transfer.
Personally I am just going to find another way to communicate the information in the title, but I wanted to post my findings for the next person.
Adam
Related
Im newbie in js and anychart
I have anychart chart like this
how can i fill the color based on range like risk matrix.
*Result What i want
This is my code
// create data
var data = [
{x: 2.88, value: 3.12},
{x: 1.9, value: 2.3}
];
// create a chart
var chart = anychart.scatter();
// adjust scale min/max
chart.xScale().minimum(0).maximum(5.0);
chart.yScale().minimum(0).maximum(5.0);
// divide scale by three ticks
chart.xScale().ticks().interval(1.0);
chart.yScale().ticks().interval(1.0);
// create a bubble series and set the data
var series = chart.marker(data);
// enable major grids
chart.xGrid().enabled(true).stroke('0.1 blue');
chart.yGrid().enabled(true).stroke('0.1 blue');
var yAxis = chart.xAxis();
// set the chart title
chart.title("Quadrant-like Scatter Bubble Chart");
// set the container id
chart.container("container").draw();
});```
To get a risk matrix in the result, it’s better to use the Heatmap module.
Heatmap from your screenshot is recreated in this sample here: https://playground.anychart.com/0RAcumgI/3
Did we understand your question correctly?
I am building plotly figures with R. The figures have legends. Each legend has a colored point that represents a level of the data. Here is a minimal example:
library(plotly)
data(iris)
plot_ly(
x = ~Petal.Length, y = ~Petal.Width,
color = ~Species,
data = iris)
By default, double-clicking on a point in the legend completely hides all unrelated points. For example, double-clicking on the "versicolor" point in the legend hides all "setosa" and "virginica" points in the plot. In plotly argot, it "filters" the data in the plot.
But I would rather that clicking on a point in the legend highlight points in the plot. For example, I would like clicking (or double-clicking) on the versicolor point in the legend to dim the "setosa" and "virginica" points in the plot, perhaps by reducing their opacity. The versicolor points in the plot would then be "highlighted." Can this behavior be implemented?
I've read through the plotly documentation and searched SO and the plotly forums for related questions. That search suggests two potential solutions, but they seem rather complicated:
Write a custom "click event" function in JS. https://plotly.com/javascript/plotlyjs-events/#legend-click-events seems to suggest that this approach can work. I don't know whether I can implement this approach from R.
Disable the default legend (showlegend = FALSE), then create a new legend by adding traces that have customized click events.
Are these the best approaches? If they are, and if more than one is workable, which one should I pursue?
Other notes: I'm not using Shiny. And I know about the itemclick and itemdoubleclick legend attributes, and about highlight_key(), but they don't seem relevant. (Please correct me if I'm wrong.)
The key is to disable legend-click events in R, and then to write a custom event handler that changes the figure when plotly_legendclick is triggered. Here is an example:
library(plotly)
data(iris)
myPlot <- plot_ly(
x = ~Petal.Length, y = ~Petal.Width,
color = ~Species,
data = iris)
# Disable default click-on-legend behavior
myPlot <- layout(
myPlot,
legend = list(itemclick = FALSE, itemdoubleclick = FALSE))
# Add an event handler
onRender(
myPlot,
"function (el) {
const OPACITY_START = el._fullData[0].marker.opacity;
const OPACITY_DIM = 0.3;
el.on('plotly_legendclick', function (data) {
// Get current opacity. The legend bubble on which we click is given by
// data.curveNumber: data.curveNumber == 0 means that we clicked on the
// first bubble, 1 means that we clicked on the second bubble, and so on.
var currentOpacity = data.fullData[data.curveNumber].marker.opacity
if (currentOpacity < OPACITY_START) { // if points already dimmed
var update = { 'marker.opacity' : OPACITY_START }; // could also set to null
} else { // if points not already dimmed
var update = { 'marker.opacity' : OPACITY_DIM };
}
Plotly.restyle(el, update, data.curveNumber);
} );
}"
)
When a user clicks on a legend bubble, this code toggles the corresponding bubbles in the plot between "normal" and "dim" states.
To instead toggle the other bubbles in the plot -- that is, to modify the other traces -- a small modification will be needed. In particular, data.curveNumber is always the number of the trace that corresponds to the clicked bubble in the legend. To instead modify the other traces, we need to pass the other trace numbers to Plotly.restyle(), not the trace that is indexed by data.curveNumber. See the Plotly.restyle() documentation for more on this point.
The title is quite clear, I'm using Leaflet and I need to show only the vertices of a polyline. For exemple see this image :
Currently I can only have the black line, I'd like only the red squares. Using markers is not an option for performance issue, my lines can be huge (500 000 vertices) and the use of smoothFactor is a need.
Is that possible? If not, does someone knows a plugin that does that, or have a hint on how could I do that by extending the Polyline class?
What you could do here is every time the polyline gets rendered, get the segments of it's SVG path, use those points to add SVG rectangle elements to the polyline's container:
var polyline = L.Polyline([]).addTo(map),
list = polyline._path.pathSegList
// Iterate segments
for (var i = 0; i < list.length; i++) {
// Create SVG rectangle element
rectangle = document.createElementNS('http://www.w3.org/2000/svg', 'rect')
// Set rectangle size attributes
rectangle.setAttributeNS(null, 'height', 4)
rectangle.setAttributeNS(null, 'width', 4)
// Set position attributes, compensate for size
rectangle.setAttributeNS(null, 'x', list[i].x - 2)
rectangle.setAttributeNS(null, 'y', list[i].y - 2)
// Set rectangle color
rectangle.setAttributeNS(null, 'fill', 'red')
// Append rectangle to polyline container
polyline._container.appendChild(rectangle)
}
Seems to work as far as i had time to test it ;) Had to use a timeout though, don't know why, look in to that when i've got more time on my hands.
Example on Plunker: http://embed.plnkr.co/vZI7aC/preview
I generate a transparent chart that lets the background of a web page be seen through it.
So far I've done this (omited the populating of dataset for brevity):
lineChartObject=ChartFactory.createLineChart("Title","Legend","Amount",line_chart_dataset,PlotOrientation.VERTICAL,true,true,false);
CategoryPlot p = lineChartObject.getCategoryPlot();
Color trans = new Color(0xFF, 0xFF, 0xFF, 0);
lineChartObject.setBackgroundPaint(trans);
p.setBackgroundPaint(trans);
for (int i=0;i<=3;i++){
lineChartObject.getCategoryPlot().getRenderer().setSeriesStroke(i, new BasicStroke(3.0f));
lineChartObject.getCategoryPlot().getRenderer().setBaseItemLabelsVisible(false);
}
Which renders this:
I cannot find a way of:
Removing border of plot (1)
Removing border of leyend as well as making it transparent (3)
Making the labels on the X axis (2) to behave intelligently as the labels of Y axis do (A). Labels of Y axis space themselves so as to not clutter the graph, for example if I rendered the graph smaller, it would show fewer labels, like this:
Edit: X label domain is dates.
For (1) try:
plot.setOutlineVisible(false);
For (2), a common reason for having too many categories along the x-axis is that the data is actually numerical, in which case you should be using XYPlot rather than CategoryPlot. With XYPlot, the x-axis scale adjusts in the same way that the y-axis does.
Edit from OP: Using a TimeSeriesChart with a TimeSeriesCollection as XYDataSet did the work! (fotgot to say X domain is dates)
For (3) try:
LegendTitle legend = chart.getLegend();
legend.setFrame(BlockBorder.NONE);
legend.setBackgroundPaint(new Color(0, 0, 0, 0));
I'm trying to customize the appearance of an ASP Web Forms RadChart where the series have FillType = Solid while still allowing visibility of the lesser point values behind larger ones. What I really want is each series to have an outline placed on top of all the fills (basically the effect of having a ChartSeriesType.Line on top of a ChartSeriesType.Area).
I've experimented with setting LineAppearance.Shadow, color transparency, and combinations of those but it's still too difficult to discern background series values.
Is there not a simple way to turn on an outline for each series when using a solid fill? OR to set the transparency of the background fill only, not the edges?
Note the transparency in the above image. I'm afraid allowing more transparency improves the visibility of background values but results in a horrible collection of pastel colors.
I suggest you to go through telerik documentation page RadControls for ASP.NET AJAX Documentation -Styling Chart Elements and this nice example Creating RadChart Programmatically - more complex example.
Code snippet:
// Define chart and titleRadChart radChart = new RadChart();
radChart.ChartTitle.TextBlock.Text = "My RadChart";
radChart.ChartTitle.TextBlock.Appearance.TextProperties.Color = System.Drawing.Color.Blue;
// Define chart series
ChartSeries chartSeries = new ChartSeries();
chartSeries.Appearance.LabelAppearance.Visible = false;
chartSeries.Name = "GDP";
chartSeries.Type = ChartSeriesType.Line;
chartSeries.Appearance.LineSeriesAppearance.Color = System.Drawing.Color.BlueViolet;
// Define the items in the series
chartSeries.AddItem(1);
chartSeries.AddItem(1.5);
chartSeries.AddItem(2.0);
chartSeries.AddItem(2.5);
chartSeries.AddItem(3.5);
// visually enhance the datapoints
chartSeries.Appearance.PointMark.Dimensions.AutoSize = false;
chartSeries.Appearance.PointMark.Dimensions.Width = 5;
chartSeries.Appearance.PointMark.Dimensions.Height = 5;
chartSeries.Appearance.PointMark.FillStyle.MainColor = System.Drawing.Color.Black;
chartSeries.Appearance.PointMark.Visible = true;
// Define chart series
ChartSeries chartSeries2 = new ChartSeries();
chartSeries2.Appearance.LabelAppearance.Visible = false;
chartSeries2.Name = "GNP";
chartSeries2.Type = ChartSeriesType.Line;
chartSeries2.Appearance.LineSeriesAppearance.Color = System.Drawing.Color.Green;
// Define the items in the series
chartSeries2.AddItem(2);
chartSeries2.AddItem(3);
chartSeries2.AddItem(3.5);
chartSeries2.AddItem(4);
chartSeries2.AddItem(4.5);
// visually enhance the data points
chartSeries2.Appearance.PointMark.Dimensions.AutoSize = false;
chartSeries2.Appearance.PointMark.Dimensions.Width = 5;
chartSeries2.Appearance.PointMark.Dimensions.Height = 5;
chartSeries2.Appearance.PointMark.FillStyle.MainColor = System.Drawing.Color.Black;
chartSeries2.Appearance.PointMark.Visible = true;
// set the plot area gradient background fill
radChart.PlotArea.Appearance.FillStyle.FillType = Telerik.Charting.Styles.FillType.Gradient;
radChart.PlotArea.Appearance.FillStyle.MainColor = System.Drawing.Color.FromArgb(65, 201, 254);
radChart.PlotArea.Appearance.FillStyle.SecondColor = System.Drawing.Color.FromArgb(0, 107, 186);
// Set text and line for X axis
radChart.PlotArea.XAxis.AxisLabel.TextBlock.Text = "Years";
radChart.PlotArea.XAxis.AxisLabel.TextBlock.Appearance.TextProperties.Color = System.Drawing.Color.Red;
radChart.PlotArea.XAxis.Appearance.Width = 3;
radChart.PlotArea.XAxis.Appearance.Color = System.Drawing.Color.Red;
// Set text and line for Y axis
radChart.PlotArea.YAxis.AxisLabel.TextBlock.Text = "%";
radChart.PlotArea.YAxis.AxisLabel.TextBlock.Appearance.TextProperties.Color = System.Drawing.Color.Red;
radChart.PlotArea.YAxis.Appearance.Width = 3;
radChart.PlotArea.YAxis.Appearance.Color = System.Drawing.Color.Red;
// Add the series to the chart, chart to page.radChart.Series.Add(chartSeries);radChart.Series.Add(chartSeries2);this.Page.Controls.Add(radChart)
Hope this help..