i have the following bar chart and tooltip showing info value
var chartData = {
labels: ["Chevrolet", "Volkswagen", "Fiat", "Ford", "Renault", "Toyota"],
datasets: [
{
fillColor: "#FFB6C1",
strokeColor: "#FF1493",
data: [87, 80, 56, 50, 18, 78]
}
]
};
var ctx = document.getElementById("myChart").getContext("2d");
var myBar = new Chart(ctx).Bar(chartData, {
});
Fiddle
I would like to print this graphic but the tooltip values will not print. So how can I show the values at the top of the bar chart ?
You can loop through the bars onAnimationComplete function and display the values
showTooltips: false,
onAnimationComplete: function () {
var ctx = this.chart.ctx;
ctx.font = this.scale.font;
ctx.fillStyle = this.scale.textColor
ctx.textAlign = "center";
ctx.textBaseline = "bottom";
this.datasets.forEach(function (dataset) {
dataset.bars.forEach(function (bar) {
ctx.fillText(bar.value, bar.x, bar.y - 5);
});
})
}
look in my full Fiddle
Related
I have this code:
animation: {
duration: 500,
onComplete: function() {
var ctx = this.chart.ctx;
var chart = this;
ctx.textAlign = "center";
ctx.textBaseline = "middle";
var datasets = this.config.data.datasets;
ctx.font = "15px QuickSand";
datasets.forEach(function (dataset, i) {
switch ( chart.getDatasetMeta(i).type ) {
case "bar":
ctx.fillStyle = "#303030";
chart.getDatasetMeta(i).data.forEach(function (p, j)
{
ctx.fillText(datasets[i].data[j], p._model.x, p._model.y - 10);
});
break;
}
});
}
}
And these datasets:
datasets: [
{
backgroundColor: '#f87979',
data: [6500, 5500]},
{
backgroundColor: '#f8f8ee',
data: [4800, 5600]
}
]
The dataset is set to be stacked using.
scales: {
xAxes: [{
barThickness: 25,
stacked: true,
ticks: {
beginAtZero: true,
padding: 0,
fontSize: 13
}
}],
yAxes: [{
stacked: true,
display: false
}]
},
What the above code does is placing the values over the bars. My problem is that i want to show the highest value from each dataset at above each bar.
And not all the values from each point.
Can you guys help me with this? I have been trying to do this for like a 1 day now.
To clearify instead of this:
Image with all values
I want this:
Image with wanted values
check out this jsfiddle: https://jsfiddle.net/umsbywLg/2/
essentially I calculated the max value and then drew that on top on the stacked bars:
onComplete: function() {
var ctx = this.chart.ctx;
var chart = this;
ctx.textAlign = "center";
ctx.textBaseline = "middle";
var datasets = this.config.data.datasets;
ctx.font = "15px QuickSand";
ctx.fillStyle = "#303030";
datasets.forEach(function (dataset, i) {
var maxValue = 0;
chart.getDatasetMeta(i).data.forEach(function (p, j) {
if(maxValue < datasets[j].data[i]) {
maxValue = datasets[j].data[i];
}
});
ctx.fillText(maxValue, datasets[i]._meta[0].data[i]._view.x, 20);
});
}
hey guys thanks for reading, and helping...
i have chart bar using chart.js, i found similar on js fiddle
here is the link http://jsfiddle.net/uh9vw0ao/
var chartData = {
labels: ["January", "February", "March", "April", "May", "June"],
datasets: [
{
fillColor: "#79D1CF",
strokeColor: "#79D1CF",
data: [60, 80, 81, 56, 55, 40]
}
]
};
var ctx = document.getElementById("myChart1").getContext("2d");
var myLine = new Chart(ctx).Line(chartData, {
showTooltips: false,
onAnimationComplete: function () {
var ctx = this.chart.ctx;
ctx.font = this.scale.font;
ctx.fillStyle = this.scale.textColor
ctx.textAlign = "center";
ctx.textBaseline = "bottom";
this.datasets.forEach(function (dataset) {
dataset.points.forEach(function (points) {
ctx.fillText(points.value, points.x, points.y - 10);
});
})
}
});
var ctx = document.getElementById("myChart2").getContext("2d");
var myBar = new Chart(ctx).Bar(chartData, {
showTooltips: false,
onAnimationComplete: function () {
var ctx = this.chart.ctx;
ctx.font = this.scale.font;
ctx.fillStyle = this.scale.textColor
ctx.textAlign = "center";
ctx.textBaseline = "bottom";
this.datasets.forEach(function (dataset) {
dataset.bars.forEach(function (bar) {
ctx.fillText(bar.value, bar.x, bar.y - 5);
});
})
}
});
question is how can i add value beside existing data, example :
example please click..
Thankyou very much!
A very quick and dirty method would be to use a paired array that has the values you want to disaply for each data point at the same index point
i.e. var supportingData = [12, 14, 15, 16, 17, 26];
then in the onAnimation complete use the index of the current data set to draw out the data form this array at the same time
dataset.bars.forEach(function(bar, index) {
//keep a refence of the fillstyle to change back to later
var ctxColour = ctx.fillStyle;
ctx.fillText(bar.value, bar.x, bar.y - 5);
ctx.fillStyle = "#FF0000";
ctx.fillText("$" + supportingData[index], bar.x + (ctx.measureText(bar.value).width)+10, bar.y - 5);
//reset the fill style
ctx.fillStyle = ctxColour;
});
because this is chartjs 1.x I do not think extra data you give to the chart is passed to the actual chart so if you wanted something a bit nicer you would need to extend your own chart and allow it to take this extra supporting data, but the method for displaying would be the same
var chartData = {
labels: ["January", "February", "March", "April", "May", "June"],
datasets: [{
fillColor: "#79D1CF",
strokeColor: "#79D1CF",
data: [60, 80, 81, 56, 55, 40]
}]
};
//add an array to have your paird data in
var supportingData = [12, 14, 15, 16, 17, 26];
var ctx = document.getElementById("myChart2").getContext("2d");
var myBar = new Chart(ctx).Bar(chartData, {
showTooltips: false,
onAnimationComplete: function() {
var ctx = this.chart.ctx;
ctx.font = this.scale.font;
ctx.fillStyle = this.scale.textColor
ctx.textAlign = "center";
ctx.textBaseline = "bottom";
this.datasets.forEach(function(dataset) {
dataset.bars.forEach(function(bar, index) {
//keep a refence of the fillstyle to change back to later
var ctxColour = ctx.fillStyle;
ctx.fillText(bar.value, bar.x, bar.y - 5);
ctx.fillStyle = "#FF0000";
ctx.fillText("$" + supportingData[index], bar.x + (ctx.measureText(bar.value).width)+10, bar.y - 5);
//reset the fill sty;e
ctx.fillStyle = ctxColour;
});
})
}
});
<script src="https://rawgit.com/nnnick/Chart.js/v1.0.2/Chart.min.js"></script>
<canvas id="myChart2" height="300" width="500"></canvas>
In the javascript graphing library, is there a way I can change the line segment color of the line between two adjacent points?
Thanks
You can extend the chart to redraw the segment of your choice with the different color.
Preview
Script
Chart.types.Line.extend({
name: "LineAlt",
draw: function () {
Chart.types.Line.prototype.draw.apply(this, arguments);
var index = 1;
var datasetIndex = 0;
var hasValue = function(item){
return item.value !== null;
},
previousPoint = function (point, collection, index) {
return Chart.helpers.findPreviousWhere(collection, hasValue, index) || point;
};
var ctx = this.chart.ctx;
var dataset = this.datasets[datasetIndex];
var pointsWithValues = Chart.helpers.where(dataset.points, hasValue);
ctx.strokeStyle = 'red';
ctx.lineWidth = 3;
ctx.beginPath();
var point = dataset.points[index];
ctx.moveTo(point.x, point.y);
point = dataset.points[index + 1];
var previous = previousPoint(point, pointsWithValues, index + 1);
ctx.bezierCurveTo(
previous.controlPoints.outer.x,
previous.controlPoints.outer.y,
point.controlPoints.inner.x,
point.controlPoints.inner.y,
point.x,
point.y
);
ctx.stroke();
}
});
and
...
new Chart(ctx).LineAlt(data);
Fiddle - http://jsfiddle.net/021xvuhd/10/
Here's a working example to do this in Charts.js 2
https://jsfiddle.net/egamegadrive16/zjdwr4fh/
var ctx = document.getElementById('myChart').getContext('2d');
//adding custom chart type
Chart.defaults.multicolorLine = Chart.defaults.line;
Chart.controllers.multicolorLine = Chart.controllers.line.extend({
draw: function(ease) {
var
startIndex = 0,
meta = this.getMeta(),
points = meta.data || [],
colors = this.getDataset().colors,
area = this.chart.chartArea,
originalDatasets = meta.dataset._children
.filter(function(data) {
return !isNaN(data._view.y);
});
function _setColor(newColor, meta) {
meta.dataset._view.borderColor = newColor;
}
if (!colors) {
Chart.controllers.line.prototype.draw.call(this, ease);
return;
}
for (var i = 2; i <= colors.length; i++) {
if (colors[i-1] !== colors[i]) {
_setColor(colors[i-1], meta);
meta.dataset._children = originalDatasets.slice(startIndex, i);
meta.dataset.draw();
startIndex = i - 1;
}
}
meta.dataset._children = originalDatasets.slice(startIndex);
meta.dataset.draw();
meta.dataset._children = originalDatasets;
points.forEach(function(point) {
point.draw(area);
});
}
});
var chart = new Chart(ctx, {
// The type of chart we want to create
type: 'multicolorLine',
// The data for our dataset
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: "My First dataset",
borderColor: 'rgb(255, 99, 132)',
data: [0, 10, 5, 2, 20, 30, 45],
//first color is not important
colors: ['', 'red', 'green', 'blue']
}]
},
// Configuration options go here
options: {}
});
source: https://github.com/chartjs/Chart.js/issues/4895#issuecomment-342747042
It's now built into CHart.js 3:
https://www.chartjs.org/docs/latest/samples/line/segments.html
I am trying to get Chart.js 2.0 to display point values in a line chart using the animation onComplete function. I found a post making it work using 1.02, how to display data values on Chart.js, but I am unable to make it work in v2.
My failing fiddle is at Line Chart v2. Any help would be appreciated.
var chartData = {
labels: ["January", "February", "March", "April", "May", "June"],
datasets: [{
label: "Buttons",
strokeColor: "#79D1CF",
tension: 0,
fill: false,
data: [60, 80, 81, 56, 55, 40]
}, {
label: "Zipppers",
strokeColor: "rgba(255,255,0,1)",
tension: 0,
fill: false,
data: [50, 75, 42, 33, 80, 21]
}]
};
var options = {
animation: {
onComplete: function() {
var ctx = this.chart.ctx;
ctx.font = this.scale.font;
//alert(ctx.font);
ctx.fillStyle = this.scale.textColor
ctx.textAlign = "center";
ctx.textBaseline = "bottom";
var datasetName = chartData.data.datasets[0].label;
alert(chartData.data.datasets[0].label)
myLine.data.datasets.forEach(function(dataset) {
ctx.fillStyle = dataset.strokeColor;
dataset.points.forEach(function(points) {
ctx.fillText(points.value, points.x, points.y - 10);
});
})
}
}
};
Chart.defaults.global.responsive = true;
Chart.defaults.global.maintainAspectRatio = true;
Chart.defaults.global.title.display = true;
Chart.defaults.global.title.text = "My Chart";
Chart.defaults.global.title.fontSize = 30;
Chart.defaults.global.legend.position = "bottom";
Chart.defaults.global.hover.mode = "label";
Chart.defaults.global.tooltips.enabled = true;
var ctx = document.getElementById("myChart1").getContext("2d");
var myLine = new Chart(ctx, {
type: 'line',
data: chartData,
options: options
});
onComplete: function(animation) {
let ctx: any = this.chart.ctx;
let chart: any = this;
ctx.fillStyle = 'rgb(133, 157, 189)';
ctx.textAlign = "center";
ctx.textBaseline = "bottom";
let datasets = this.config.data.datasets;
datasets.forEach(function (dataset, i) {
chart.getDatasetMeta(i).data.forEach(function (p, j) {
ctx.fillText(datasets[i].data[j], p._model.x, p._model.y - 0);
});
});
}
I use the Version 2.5
I can only assume there is a better way, but for now try this:
var options = {
animation: {
onComplete: function() {
var ctx = this.chart.ctx;
ctx.textAlign = "center";
ctx.textBaseline = "bottom";
this.chart.config.data.datasets.forEach(function(dataset) {
ctx.fillStyle = dataset.strokeColor;
dataset.metaDataset._points.forEach(function(p) {
ctx.fillText(p._chart.config.data.datasets[p._datasetIndex].data[p._index], p._model.x, p._model.y - 10);
});
})
}
}};
for version 2.5 I noticed there is no metaDataset too.
I used this (assuming 'yourdata' contains the data array of your chart).
dataset._meta['1'].dataset._children.forEach((point, index) => {
ctx.fillText(yourdata[index], point._view.x, point._view.y - 15);
});
Hope this helps!
I'm new to Famo.us and I am trying to expand on the Timbre sample app by adding a scrollview to the PageView where the image would be (in the _createBody function). In other words, I'm trying to add a feed similar to Facebook or Tango, etc. I found two pieces of code online that's been working with (links below). I get no errors on the console log, yet the scrollview won't display, so I'm not sure what I am missing. Your guidance is much appreciated (would also love to know if there is a better way). Finally, this is my first post ever on StackOverflow, so please let me know if I can expose my issue in a better fashion.
Links I have been using for guidance:
StackOverflowFamo.us swipe on scrollview
JSFiddle
/*** AppView.js ***/
define(function(require, exports, module) {
var View = require('famous/core/View');
var Surface = require('famous/core/Surface');
var Modifier = require('famous/core/Modifier');
var Transform = require('famous/core/Transform');
var StateModifier = require('famous/modifiers/StateModifier');
var Easing = require('famous/transitions/Easing');
var Transitionable = require('famous/transitions/Transitionable');
var GenericSync = require('famous/inputs/GenericSync');
var MouseSync = require('famous/inputs/MouseSync');
var TouchSync = require('famous/inputs/TouchSync');
GenericSync.register({'mouse': MouseSync, 'touch': TouchSync});
var PageView = require('views/PageView');
var MenuView = require('views/MenuView');
var StripData = require('data/StripData');
function AppView() {
View.apply(this, arguments);
this.menuToggle = false;
this.pageViewPos = new Transitionable(0);
_createPageView.call(this);
_createMenuView.call(this);
_setListeners.call(this);
_handleSwipe.call(this);
}
AppView.prototype = Object.create(View.prototype);
AppView.prototype.constructor = AppView;
AppView.DEFAULT_OPTIONS = {
openPosition: 276,
transition: {
duration: 300,
curve: 'easeOut'
},
posThreshold: 138,
velThreshold: 0.75
};
function _createPageView() {
this.pageView = new PageView();
this.pageModifier = new Modifier({
transform: function() {
return Transform.translate(this.pageViewPos.get(), 0, 0);
}.bind(this)
});
this._add(this.pageModifier).add(this.pageView);
}
function _createMenuView() {
this.menuView = new MenuView({ stripData: StripData });
var menuModifier = new StateModifier({
transform: Transform.behind
});
this.add(menuModifier).add(this.menuView);
}
function _setListeners() {
this.pageView.on('menuToggle', this.toggleMenu.bind(this));
}
function _handleSwipe() {
var sync = new GenericSync(
['mouse', 'touch'],
{direction : GenericSync.DIRECTION_X}
);
this.pageView.pipe(sync);
sync.on('update', function(data) {
var currentPosition = this.pageViewPos.get();
if(currentPosition === 0 && data.velocity > 0) {
this.menuView.animateStrips();
}
this.pageViewPos.set(Math.max(0, currentPosition + data.delta));
}.bind(this));
sync.on('end', (function(data) {
var velocity = data.velocity;
var position = this.pageViewPos.get();
if(this.pageViewPos.get() > this.options.posThreshold) {
if(velocity < -this.options.velThreshold) {
this.slideLeft();
} else {
this.slideRight();
}
} else {
if(velocity > this.options.velThreshold) {
this.slideRight();
} else {
this.slideLeft();
}
}
}).bind(this));
}
AppView.prototype.toggleMenu = function() {
if(this.menuToggle) {
this.slideLeft();
} else {
this.slideRight();
this.menuView.animateStrips();
}
};
AppView.prototype.slideLeft = function() {
this.pageViewPos.set(0, this.options.transition, function() {
this.menuToggle = false;
}.bind(this));
};
AppView.prototype.slideRight = function() {
this.pageViewPos.set(this.options.openPosition, this.options.transition, function() {
this.menuToggle = true;
}.bind(this));
};
module.exports = AppView;
});
/*** PageView.js ***/
define(function(require, exports, module) {
var View = require('famous/core/View');
var Surface = require('famous/core/Surface');
var Transform = require('famous/core/Transform');
var StateModifier = require('famous/modifiers/StateModifier');
var HeaderFooter = require('famous/views/HeaderFooterLayout');
var ImageSurface = require('famous/surfaces/ImageSurface');
var Scrollview = require('famous/views/Scrollview');
function PageView() {
View.apply(this, arguments);
_createBacking.call(this);
_createLayout.call(this);
_createHeader.call(this);
_createBody.call(this);
_setListeners.call(this);
}
PageView.prototype = Object.create(View.prototype);
PageView.prototype.constructor = PageView;
PageView.DEFAULT_OPTIONS = {
headerSize: 44
};
function _createBacking() {
var backing = new Surface({
properties: {
backgroundColor: 'black',
boxShadow: '0 0 20px rgba(0,0,0,0.5)'
}
});
this.add(backing);
}
function _createLayout() {
this.layout = new HeaderFooter({
headerSize: this.options.headerSize
});
var layoutModifier = new StateModifier({
transform: Transform.translate(0, 0, 0.1)
});
this.add(layoutModifier).add(this.layout);
}
function _createHeader() {
var backgroundSurface = new Surface({
properties: {
backgroundColor: 'black'
}
});
this.hamburgerSurface = new ImageSurface({
size: [44, 44],
content : 'img/hamburger.png'
});
var searchSurface = new ImageSurface({
size: [232, 44],
content : 'img/search.png'
});
var iconSurface = new ImageSurface({
size: [44, 44],
content : 'img/icon.png'
});
var backgroundModifier = new StateModifier({
transform : Transform.behind
});
var hamburgerModifier = new StateModifier({
origin: [0, 0.5],
align : [0, 0.5]
});
var searchModifier = new StateModifier({
origin: [0.5, 0.5],
align : [0.5, 0.5]
});
var iconModifier = new StateModifier({
origin: [1, 0.5],
align : [1, 0.5]
});
this.layout.header.add(backgroundModifier).add(backgroundSurface);
this.layout.header.add(hamburgerModifier).add(this.hamburgerSurface);
this.layout.header.add(searchModifier).add(searchSurface);
this.layout.header.add(iconModifier).add(iconSurface);
}
function _createBody() {
var surfaces = [];
this.scrollview = new Scrollview();
var temp;
for (var i = 0; i < 30; i++) {
temp = new Surface({
size: [undefined, 80],
content: 'Surface: ' + (i + 1),
properties: {
textAlign: 'left',
lineHeight: '80px',
borderTop: '1px solid #000',
borderBottom: '1px solid #fff',
backgroundColor: '#ffff00',
fontFamily: 'Arial',
backfaceVisibility: 'visible',
paddingLeft: '10px'
}
});
temp.pipe(this.scrollview);
surfaces.push(temp);
}
this.scrollview.sequenceFrom(surfaces);
this.bodyContent = new Surface({
size: [undefined, undefined],
properties: {
backgroundColor: '#f4f4f4'
}
});
this.layout.content.add(this.bodyContent);
}
function _setListeners() {
this.hamburgerSurface.on('click', function() {
this._eventOutput.emit('menuToggle');
}.bind(this));
//this.bodyContent.pipe(this._eventOutput);
this.scrollview.pipe(this._eventOutput);
}
module.exports = PageView;
});
You need to add this.scrollview to your layout.content element on the page. Put this in place of this.bodyContent. layout.content is the node for the content of the page.
//this.layout.content.add(this.bodyContent);
this.layout.content.add(this.scrollview);