Problem
There are very small numbers that appear atop a bar chart in Flot that I think are being drawn using canvas. As a result, I'm having difficulty trying to change it to match the styles of the labels on my x and y-axis.
scripts.js
<script type="text/JavaScript">
var d1 = [
[2013, {{ school.apr_2013 }}],
[2014, {{ school.apr_2014 }}],
[2015, {{ school.apr_2015 }}],
[2016, {{ school.apr_2016 }}]
];
$(document).ready(function() {
aprPlot = $.plot($("#apr-chart"), [d1], {
series: {
bars: {
show: true,
fill: true,
// Determines the color of the bar in the chart
fillColor: '#c62828',
barWidth: 0.5,
align: "center"
},
valueLabels: { show: true },
color: "#c62828"
},
xaxis: {
min: 2012.5,
max: 2016.5,
ticks:
[[2013, '2013'],
[2014, '2014'],
[2015, '2015'],
[2016, '2016']]},
yaxis: {
min: 0,
max: 105,
tickSize: 10
},
grid: {
borderWidth: 0.5,
borderColor: 'AAA',
color: '#AAA',
labelMargin: 10
}
});
// Add data value labels at top of bar
var ctx = aprPlot.getCanvas().getContext("2d");
var data = aprPlot.getData()[0].data;
var xaxis = aprPlot.getXAxes()[0];
var yaxis = aprPlot.getYAxes()[0];
var offset = aprPlot.getPlotOffset();
for (var i = 0; i < data.length; i++){
var text = data[i][1] + '';
var metrics = ctx.measureText(text);
var xPos = (xaxis.p2c(data[i][0])+offset.left) - metrics.width/2;
var yPos = yaxis.p2c(data[i][1]) + offset.top - 5;
ctx.fillText(text, xPos, yPos);
}
});
</script>
style.scss
.flot-text {
font-family: "Lato", sans-serif;
color: $color-black !important;
font-size: 12px !important;
}
You can set the font style for the canvas before you draw the text:
ctx.font = '12px Lato';
ctx.fillText(text, xPos, yPos);
Related
I am trying to draw a straight line on mouse click on plotlyjs with image loaded as background. I am able to get the co-ordinates but not able to draw lines on successive mouse clicks.
With the help of myPlot.on('plotly_click', function(data){ // some code }) I am able to get the co-ordinates but no idea to draw lines on mouse click. Any idea or reference will be helpful. Thanks in advance.
this is the output of the plotly graph with background image.
<script src='https://cdn.plot.ly/plotly-2.16.1.min.js'></script>
<div id='plotlyContainer'></div>
var d3 = Plotly.d3;
var imgWidth = 0;
var imgHeight = 0;
const imgs = new Image();
let plotCon = document.getElementById('plotlyContainer');
imgs.onload = function() {
imgWidth = this.width;
imgHeight = this.height;
loadImgGraph(imgWidth, imgHeight);
}
imgs.src = 'https://i.stack.imgur.com/cRbua.png';
function loadImgGraph(imgWidth, imgHeight) {
var data = [
{
x: [],
y: [],
type: 'scatter'
}
];
var layout = {
autosize: false,
width: imgWidth,
height: imgHeight,
xaxis: {range: [0, 100], dtick: 25, ticks: 'outside', tickwidth: 2, gridcolor: "black", gridwidth: 2, mirror: true, linecolor: 'black', linewidth: 1},
yaxis: {range: [140, 0], dtick: 20, ticks: 'outside', tickwidth: 2, gridcolor: "black", gridwidth: 2, mirror: true, linecolor: 'black', linewidth: 1},
margin: {
l: 32,
r: 20,
b: 30,
t: 30
},
images: [
{
source: 'https://i.stack.imgur.com/cRbua.png',
xref: 'paper',
yref: 'paper',
x: 0,
y: 1,
sizex: 1,
sizey: 1,
sizing: 'fill',
opacity: 1,
layer: 'below'
}
],
};
Plotly.newPlot('plotlyContainer', data, layout).then(clickEv);
function clickEv() {
var xaxis = plotCon._fullLayout.xaxis;
console.log('xaxis',xaxis);
var yaxis = plotCon._fullLayout.yaxis;
console.log('yaxis',yaxis);
var l = plotCon._fullLayout.margin.l;
console.log('l',l);
var t = plotCon._fullLayout.margin.t;
console.log('t',t);
plotCon.addEventListener('mousemove', function(evt) {
var xInDataCoord = xaxis.p2c(evt.x - l);
var yInDataCoord = yaxis.p2c(evt.y - t);
Plotly.relayout(plotCon, 'title', ['x: ' + xInDataCoord, 'y : ' + yInDataCoord].join('<br>'));
});
plotCon.on('plotly_click', function(){
alert('You clicked this Plotly chart!');
});
}
}
In you setting, one way to do it could be:
plotCon.addEventListener('click', function(evt){
data[0].x.push(xaxis.p2c(evt.x - l))
data[0].y.push(yaxis.p2c(evt.y - t))
Plotly.update(plotCon, data, layout);
});
Also, see Plotly.react for a more efficient way to update the plot.
I created a bubble chart with chart.JS 2.0 (risk matrix). I would now like to color the background with a green circle centered on the bottom left of the chart which would become red when expanding to the top right.
I managed to create the circle on the background which generates the following chart :
I would now like to have the circle centered on the bottom left but I am struggling to deal with the coordinates.
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;
// {left: 45.073828125, top: 34.4, right: 588, bottom: 538.2}
ctx.save();
var canevas = document.querySelector("canvas");
var contexte = canevas.getContext('2d');
X = chartArea.right;
Y = chartArea.bottom;
leftoffset = chartArea.left;
topoffset = chartArea.top;
// var gradient = ctx.createLinearGradient(0, 70, 70, 0);
var gradient = ctx.createRadialGradient(X / 1.34, Y / 1.412, X / 8, X / 4 * 3, Y / 2, X / 3);
gradient.addColorStop(0, "green");
gradient.addColorStop(0.5, "orange");
gradient.addColorStop(1, "red");
ctx.fillStyle = gradient;
ctx.fillRect(chartArea.left, chartArea.top, chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);
}
}
});
var myBubbleChart = new Chart(document.getElementById("bubble-chart"), {
type: 'bubble',
data: {
labels: "Africa",
datasets: [{
idu: 29,
label: ["Hurricane"],
backgroundColor: "#398B93",
data: [{
x: 4,
y: 1,
r: 15
}]
},
{
idu: 30,
label: ["Flooding"],
backgroundColor: "#398B93",
data: [{
x: 5,
y: 4,
r: 15
}]
},
{
idu: 31,
label: ["Cyber-attack"],
backgroundColor: "#398B93",
data: [{
x: 1,
y: 4,
r: 15
}]
},
]
},
options: {
chartArea: {
backgroundColor: 'linear-gradient(0.25turn, #3f87a6, #ebf8e1, #f69d3c)'
},
title: {
display: true,
text: 'Risk matrix'
},
scales: {
yAxes: [{
scaleLabel: {
display: true,
labelString: "Likelihood"
},
ticks: {
min: 0, // Controls where axis starts
max: 6, // Controls where axis finishes
stepSize: 1,
display: true,
callback: function(tick) {
return (tick !== 0) && (tick !== 6) ? tick : '';
}
},
gridLines: {
display: true,
drawBorder: false,
lineWidth: 1, // Width of line,
offsetGridLines: true,
color: '#EBEEEE',
}
}],
xAxes: [{
scaleLabel: {
display: true,
labelString: "Impact"
},
ticks: {
min: 0, // Controls where axis starts
max: 6, // Controls where axis finishes
stepSize: 1,
display: true,
callback: function(tick) {
return (tick !== 0) && (tick !== 6) ? tick : '';
}
},
gridLines: {
display: true,
drawBorder: false,
offsetGridLines: true,
color: '#ebeeee',
}
}]
},
legend: {
display: false,
labels: {
fontColor: 'rgb(255, 99, 132)'
}
},
jitter: true,
}
});
#bubble-chart {
max-width: 90%;
max-height: 90%;
}
<canvas id="bubble-chart" width="800" height="800"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.8.0"></script>
Thanks a lot
Problem: I am trying to plot a dumbel chart using highcharts. I want to conditionally check if the series is positive or negative and assign the color to the line series.
tried: to write a function to dynamically assign the colors but it does not work. But the same function is used to dynalically render circles and it work
https://jsfiddle.net/z4t2qg5o/
Highcharts.chart('container', {
chart: {
type: 'xrange'
},
plotOptions: {
columnrange: {
colorByPoint: true,
colors: ['red', 'blue', 'yellow']
}
},
title: {
text: 'Highcharts X-range'
},
xAxis: {
},
yAxis: {
title: {
text: ''
},
categories: ['Prototyping', 'Development', 'Testing'],
reversed: true
},
series: [{
// name: 'Project 3',
// pointPadding: 0,
// groupPadding: 0,
//borderColor: 'gray',
pointWidth: 5,
data: [{
x: 32,
x2: 33,
y: 0,
val: -1,
//color:'red'
// partialFill: 0.25
}, {
x: 21,
x2:25,
y: 1,
val: 1,
//color:'#BADA55'
}, {
x:31,
x2: 32,
y: 2,
val: -1,
//color:'red'
}],
dataLabels: {
align: 'left',
enabled: false
}
}]
}, function() {
var chart = this,
leftOffset = chart.plotLeft,
topOffset = chart.plotTop,
series = chart.series[0],
xAxis = series.xAxis,
x2Axis = series.x2Axis,
yAxis = series.yAxis,
points = series.points;
points.forEach(function(point) {
var x = xAxis.toPixels(point.x) - leftOffset,
x2 = xAxis.toPixels(point.x2) - leftOffset,
y = yAxis.toPixels(point.y - 0.005) - topOffset,
toCenter = x2-x;
val = point.val;
toCenter = toCenter > 0 ? toCenter : -toCenter;
if(val > 0 ){
//to set the color of the line to green
point.color = '#BADA55';
chart.renderer.circle(x, y, 6).attr({
fill: '#BADA55',
//'stroke-width': 1,
stroke: '#BADA55',
zIndex: 10
}).add(series.group);
chart.renderer.circle(x2, y, 6).attr({
fill: '#BADA55',
//'stroke-width': 1,
stroke: '#BADA55',
zIndex: 10
}).add(series.group);
// toCenter = toCenter > 0 ? toCenter : -toCenter;
chart.renderer.image('https://www.highcharts.com/samples/graphics/sun.png',x2 + 74,y +35,20,20).attr({
zIndex: 15
}).add();
}
else{
//to set the color of the line to green
point.color = '#BADA55';
chart.renderer.circle(x, y, 6).attr({
fill: '#ff0000',
'stroke-width': 1,
zIndex: 10
}).add(series.group);
chart.renderer.image('https://www.highcharts.com/samples/graphics/sun.png',x + 92,y +35,20,20).attr({
zIndex: 15
}).add();
// toCenter = toCenter > 0 ? toCenter : -toCenter;
chart.renderer.circle(x2, y , 6).attr({
fill: '#ff0000',
// 'stroke-width': 2,
zIndex: 10
}).add(series.group);
}
});
});
#container {
min-width: 300px;
max-width: 800px;
height: 300px;
margin: 1em auto;
}
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/xrange.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<div id="container"></div>
Expected: In the link shared, I want the line to be green when the 'val' is positive and the line to be red when the 'val' is negative
There might be a better way to achieve what you want. instead of writing your own function use Zones.
Look here.
You can use zones like this :
series:[{
data : [1,5,-8,9,12]//your data
zones : [{value:0,color:'red'},{color:'green'}]
}]
A live example of this is provided by HighCharts API refrence at this jsfiddle.
I don't know if this counts as an answer to your question but taking a look at this Zone thing might buy you some time.
I am using this version of ChartJS -> http://www.chartjs.org/samples/latest/charts/line/basic.html
And I'd like to ask you - is there a possibility to add value above the point ?
I think about something like:
^ an example :-)
Was trying to find something using google but unsuccessfully
Thanks in advance,
Yes, there is a possibility :-)
However, there's no built-in functionality for this in ChartJS as of now. You would rather have to create a chart plugin.
ᴘʟᴜɢɪɴ
plugins: [{
afterDatasetsDraw: function(chart) {
var ctx = chart.ctx;
chart.data.datasets.forEach(function(dataset, index) {
var datasetMeta = chart.getDatasetMeta(index);
if (datasetMeta.hidden) return;
datasetMeta.data.forEach(function(point, index) {
var value = dataset.data[index],
x = point.getCenterPoint().x,
y = point.getCenterPoint().y,
radius = point._model.radius,
fontSize = 14,
fontFamily = 'Verdana',
fontColor = 'black',
fontStyle = 'normal';
ctx.save();
ctx.textBaseline = 'middle';
ctx.textAlign = 'center';
ctx.font = fontStyle + ' ' + fontSize + 'px' + ' ' + fontFamily;
ctx.fillStyle = fontColor;
ctx.fillText(value, x, y - radius - fontSize);
ctx.restore();
});
});
}
}]
* add this followed by your chart options.
ᴡᴏʀᴋɪɴɢ ᴇxᴀᴍᴘʟᴇ ⧩
var chart = new Chart(ctx, {
type: 'line',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May'],
datasets: [{
label: 'LINE 1',
data: [3, 1, 4, 2, 5],
backgroundColor: 'rgba(0, 119, 290, 0.5)',
borderColor: 'rgba(0, 119, 290, 0.6)',
fill: false
}, {
label: 'LINE 2',
data: [2, 4, 1, 5, 3],
backgroundColor: 'rgba(233, 30, 99, 0.5)',
borderColor: 'rgba(233, 30, 99, 0.6)',
fill: false
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
max: 7
}
}]
}
},
plugins: [{
afterDatasetsDraw: function(chart) {
var ctx = chart.ctx;
chart.data.datasets.forEach(function(dataset, index) {
var datasetMeta = chart.getDatasetMeta(index);
if (datasetMeta.hidden) return;
datasetMeta.data.forEach(function(point, index) {
var value = dataset.data[index],
x = point.getCenterPoint().x,
y = point.getCenterPoint().y,
radius = point._model.radius,
fontSize = 14,
fontFamily = 'Verdana',
fontColor = 'black',
fontStyle = 'normal';
ctx.save();
ctx.textBaseline = 'middle';
ctx.textAlign = 'center';
ctx.font = fontStyle + ' ' + fontSize + 'px' + ' ' + fontFamily;
ctx.fillStyle = fontColor;
ctx.fillText(value, x, y - radius - fontSize);
ctx.restore();
});
});
}
}]
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<canvas id="ctx"></canvas>
I am using Flot interactive chart, the data being displayed is taken in from a datatable.
When the user hover's over a point the tooltip displays "Height(cm) on 6.00 = 168", basically the "168" represents the y value which is correct as it corresponds with the y-axis labels.
However the "6.00" should be a date, as is displayed on the chart along the x-axis, "6.00" is the sequence number , I need to get the label.....
any ideas ?
//Show ToolTip Part 2
function showTooltip(x, y, contents)
{
$('<div id="tooltip">' + contents + '</div>').css(
{
position: 'absolute',
display: 'none',
top: y + 5,
left: x + 15,
border: '1px solid #333',
padding: '4px',
color: '#fff',
'border-radius': '3px',
'background-color': '#333',
opacity: 0.7
}
).appendTo("body").fadeIn(400);
}
//Show ToolTip Part 1
var previousPoint = null;
$("#VitalsChart").bind("plothover", function (event, pos, item)
{
$("#x").text(pos.x.toFixed(2));
$("#y").text(pos.y.toFixed(2));
if (item)
{
if (previousPoint != item.dataIndex)
{
previousPoint = item.dataIndex;
$("#tooltip").remove();
var x = item.datapoint[0].toFixed(2),
y = item.datapoint[1].toFixed(2);
showTooltip(item.pageX, item.pageY, item.series.label + " on " + x + "=" + "<strong>" + y + "</strong>");
}
}
else
{
$("#tooltip").remove();
previousPoint = null;
}
});
//Plot Data
var plot = $.plot($("#VitalsChart"), [{ data: weight, label: "Weight (kg)" },
{ data: height, label: "Height (cm)" }],
{
series:
{
lines:
{
show: true,
lineWidth: 2,
fill: false,
fillColor: { colors: [{ opacity: 0.5 }, { opacity: 0.1 }] }
},
points: { show: true },
shadowSize: 7
},
grid:
{
hoverable: true,
clickable: false,
tickColor: "#ddd",
borderWidth: 1,
minBorderMargin: 10
},
colors: ["red", "blue"],
xaxis:
{
ticks: xLabels,
tickDecimals: 0
},
yaxis:
{
ticks: 11,
tickDecimals: 0
}
});
}
Try:
var x = xLabels[item.datapoint[0] - 1][1];
Your ticks (xLabels) is an array of 2 element arrays. You need just the second element, the label itself.