I need help with changing the line width(or color) on one specific grid-line on a Chartjs chart.
In the example below I would like to increase the grid-line width(or change color) of the horizontal gridline at y-axis 60 only. I have tried my best to find a solution within the Chartjs documentation but failed. Perhaps there is no support for this at the moment, and if so I'd like to know if anyone could help me add this feature.
Thank you !
You can extend the chart to override the scale draw function and draw a thicker / differently coloured line where you want
Preview
Script
Chart.types.Bar.extend({
name: "BarAlt",
initialize: function(data){
Chart.types.Bar.prototype.initialize.apply(this, arguments);
var originalScaleDraw = this.scale.draw;
this.scale.draw = function() {
originalScaleDraw.apply(this, arguments);
this.ctx.save();
this.ctx.beginPath();
this.ctx.lineWidth = this.gridLineWidth * 5;
this.ctx.strokeStyle = "rgba(120,120,220,1)";
this.ctx.moveTo(Math.round(this.xScalePaddingLeft), this.calculateY(60));
this.ctx.lineTo(this.width, this.calculateY(60));
this.ctx.stroke();
this.ctx.closePath();
this.ctx.restore();
}
}
});
and then
...
new Chart(ctx).BarAlt(data);
Fiddle - http://jsfiddle.net/udojrq57/
Related
I have a requirement to show data labels of two graphs on the same axes.
Only when they intersect, one of the two labels won't show. This can be demonstrated below:
As you can see on the 2nd, 5th and 6th columns from the left with values 0%, 7% and 8% respectively
only the orange line values are shown but the blue column values are missing.
This is the final html of the graph after rendering:
So data-datapoint-id 142, 145 and 146 are missing from the html.
I tried using the plotArea.dataLabel.renderer function as a manipulation of what was proposed here but nothing changed, still not rendering.
Anyone encountered a similar problem? Is that a sapui5 issue or can it be fixed by manually inserting the labels into the HTML if so how?
Thanks,
Ori
Using SVG text and jQuery I managed to manually insert the labels into the top middle of the blue rectangle columns.
This is the result, not perfect but works:
and this is the code:
chart.setVizProperties({
plotArea: {
dataLabel: {
formatString: {'פחת כללי': FIORI_PERCENTAGE_FORMAT_2},
renderer: function (oLabel) {
// Create empty text node to be returned by the function such that the label won't be rendered automatically
var node = document.createElement("text");
if (oLabel.ctx.measureNames === "כמות פחת כללי") {
var kamutLabelIdx = oLabel.ctx._context_row_number;
// Use jQuery and SVG to manipulate the HTML
var kamutLabelQuery = '[data-id=\"' + kamutLabelIdx + '\"]';
var kamutColumn = $(kamutLabelQuery)[0];
// Create text element as child of the column
kamutColumn.innerHTML += "<text>" + oLabel.text + "</text>";
var labelNode = $(kamutLabelQuery += ' text');
// Set the label position to be at the middle of the column
const labelLength = 60;
const xPos = (labelLength + oLabel.dataPointWidth) / 2;
const yPos = oLabel.styles['font-size'];
labelNode.attr({
"textLength" : labelLength,
"x" : xPos,
"y" : yPos,
"font-size" : yPos
});
return node;
}
}
}
}
});
The oLabel parameter of the renderer function provides useful info about the data label to be created:
I still wonder if that's a bug with sapui5 vizframe and if there is a simpler way to do this.
Please let me know of your thoughts
I am trying to create a semi circle donut chart to show some progress data. This I was able to complete. Further I needed to place text inside/ center of the donut chart which again I was able to do successfully. Now I have a new requirement where I need to show some text on the start and end positions of the graph(I need 0% and 100% to be shown on either axis). I tried several ways without any ado. Can you please help me with a possible solution.
Please find the dojo I created here:
http://dojo.telerik.com/Exike
This is roughly what I would like my end result to appear like:
Any suggestions for the same?
Thanks in advance.
You could add a couple of text boxes to your render function and use the bounding box to place them:
render: function (e) {
var draw = kendo.drawing;
var geom = kendo.geometry;
var chart = e.sender;
// The center and radius are populated by now.
// We can ask a circle geometry to calculate the bounding rectangle for us.
var circleGeometry = new geom.Circle(center, radius);
var bbox = circleGeometry.bbox();
// Render the text
var text = new draw.Text("33%", [0, 0], {
font: "18px Verdana,Arial,sans-serif"
});
// Align the text in the bounding box
draw.align([text], bbox, "center");
draw.vAlign([text], bbox, "center");
var text0 = new draw.Text("0%", [bbox.origin.x, bbox.origin.y + bbox.size.height / 2 ], {
font: "10px Verdana,Arial,sans-serif"
});
var text100 = new draw.Text("100%", [bbox.origin.x + bbox.size.width - 28, bbox.origin.y + bbox.size.height / 2 ], {
font: "10px Verdana,Arial,sans-serif"
});
// Draw it on the Chart drawing surface
e.sender.surface.draw(text);
e.sender.surface.draw(text0);
e.sender.surface.draw(text100);
}
Use DonutCenterTemplate for that:
<ng-template kendoChartDonutCenterTemplate>
<h3>99.5%</h3>
Accepted
</ng-template>
I would like to change the background colour of the line graph produced by chart.js. There doesn't appear to be an option for this, and the documentation doesn't help. Extensive searching on the interweb has yielded no results. Is this possible?
I must confess I don't really know much about the HTML5 canvas so I'm struggling a bit!
With v2.1 of Chart.js, you can write your own plugin to do this
Preview
Script
Chart.pluginService.register({
beforeDraw: function (chart, easing) {
if (chart.config.options.chartArea && chart.config.options.chartArea.backgroundColor) {
var helpers = Chart.helpers;
var ctx = chart.chart.ctx;
var chartArea = chart.chartArea;
ctx.save();
ctx.fillStyle = chart.config.options.chartArea.backgroundColor;
ctx.fillRect(chartArea.left, chartArea.top, chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);
ctx.restore();
}
}
});
and then
...
options: {
chartArea: {
backgroundColor: 'rgba(251, 85, 85, 0.4)'
}
}
...
Fiddle - http://jsfiddle.net/rrcd60y0/
I'm not sure what you mean by "the background color of the main area of the graph that isn't occupied with the line chart", but you can set the background-color of the canvas via CSS:
#myChart {
background-color: #666;
}
Look at this fiddle to see how it affects the chart.
This will set the background for the whole canvas, if you only want to set it for the inner part, check out potatopeelings solution.
Just to help others who are thinking how to add multiple background colors:
I modified a little bit #potatopeelings answer. First I checked how many columns there are
var columnCount = chart.data.datasets[0].data.length;
var width = chartArea.right - chartArea.left;
var columnWidth = width/columnCount;
and then fill every other of them with background color
while (startPoint < chartArea.right) {
ctx.fillRect(startPoint, chartArea.top, columnWidth, height);
startPoint += columnWidth * 2;
}
For my chart this works better but for this the July column is for some reason only part of it. Doesn't know how to fix that but hopefully you can get idea from here.
http://jsfiddle.net/e7oy6yk6/2
In my chart, I show the user pictures for their comment date, so the users can read the comments in a tooltip using these icons. It seems like soundcloud charts. I did it using flags type and I set the shape variables as user picture url for each data item.
But I want to add also colorized border for each icons. I know, there is lineWidth and lineColor config in flags type but it doesn't work with images, it works only with default shapes flag, circlepin or squarepin.
I tried to use shape as flag and to add user images as background image, but It doesn't work.
In SVG you can not set border for the images, you need to create rect around the image: http://jsfiddle.net/xuL76rkL/1/
For example you can use load and redraw events to manage those rects, code:
var H = Highcharts;
function drawBorder() {
var chart = this;
H.each(chart.series[1].points, function(p) {
var bbox,
rect,
fontSize = 13, // it's used as default font size offet, even for the images
dim = 32; //width and height for the image
if(p.graphic) {
if(p.rectangle) {
p.rectangle.destroy();
}
bbox = p.graphic.getBBox();
rect = chart.renderer.rect(p.plotX - dim/2, p.plotY - dim/2 - fontSize, dim, dim).attr({
"stroke": "black",
"stroke-width": 2,
"fill": "transparent"
}).add(chart.series[1].markerGroup);
p.rectangle = rect;
}
});
}
$('#container').highcharts('StockChart', {
chart: {
events: {
load: drawBorder,
redraw: drawBorder
}
},
...
});
You can set an image with the shape option:
Example: shape: "url(/assets/my_image.svg)"
Documentation available here: https://api.highcharts.com/highstock/series.flags.shape
What I have:
Text along a path made out of circle. It uses Raphael.js and a function called textOnPath (found here: Raphael JS Text Along path ):
var pathTest = r.path(getCircletoPath(286, 322, radius)).attr({stroke:"#b9b9b9"});
textOnPath(message, pathTest, fontSize, fontSpacing, kerning, kerning, point, textFill, fontNormal, fontFamily);
JSFiddle: http://jsfiddle.net/zorza/62hDH/1/
What I need:
The text to be centered on top of the circle.
My approach:
Try to calculate where the text should start depending on the arc size and text width. I tried to calculate the text width by creating it's invisible clone with text() function and get it's BBox width.
It doesn't quite work and the results vary depending on the web browser, font used and number of letters and spaces:
var length = r.text(100,400,message)
.attr({"font-size":fontSize,'opacity': 0, 'font-family': fontFamily})
.getBBox()
.width;
var point = (Math.PI*radius - length*fontSpacing)/2;
JSFiddle: http://jsfiddle.net/zorza/k8vBy/3/
Could anyone point me in the right direction?
The easiest way, IMHO, is to create additional helper path that is raised by half of text size. http://jsfiddle.net/p84VQ/
Also, I find it a bit more convenient to define a circle and then get points at specified angle:
var Circle = function(cx, cy, r) {
return function (a) {
return {
x: cx + r*Math.sin(Math.PI*-a/180),
y: cy - r*Math.cos(Math.PI*-a/180)
}
}
};