I am trying to create a line chart inside a PDF file using Chart.js, Node, Pug and Headless chrome (html-pdf-chrome) and it is not working.
The rendered HTML works directly in browser, but the generated PDF is blank. Adding a timeout makes no difference with completionTrigger.
I am wondering if it is even possible to do this, and if so, where did I go wrong?
Node file:
const pug = require('pug');
const htmlPdf = require('html-pdf-chrome');
async function createPDF() {
const html = pug.renderFile('template.pug', {})
const options = {
port: 9222,
completionTrigger: new htmlPdf.CompletionTrigger.Timer(5000),
};
htmlPdf.create(html, options).then((pdf) => pdf.toFile('output.pdf'));
}
createPDF();
Pug template:
doctype html
html
head
meta(charset="utf-8")
title test
script(type="text/javascript", src='chart.js')//chart.js lib
script(type="text/javascript", src='scripts.js')
body
canvas#myChart(width='200' height='100' style='border:1px solid #000000;')
scripts file:
window.onload = function () {
const ctx = document.getElementById('myChart').getContext('2d');
const chart = new Chart(ctx, {
type: 'line',
data: {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
label: 'My First dataset',
backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgb(255, 99, 132)',
data: [0, 10, 5, 2, 20, 30, 45]
}]
},
options: {}
});
};
Related
I have been working on a broadband management website.I want to show the user how much data he/she has used.For example if the total data they have in their name is 300GB.If they have used 150GB the remaining is 150GB right?.How to do i visualize this using a doughnut chart,Using ChartJS.
I have some code going but im not sure how to accomplish this please help me out
var ctx = document.getElementById('myChart').getContext('2d');
var constdata=document.getElementById("constantdata").textContent;
var data=document.getElementById("data").textContent;
console.log(data);
var chart = new Chart(ctx, {
// The type of chart we want to create
type: 'doughnut',
// The data for our dataset
data: {
datasets: [{
label: 'My First dataset',
backgroundColor: ['red','green'],
borderColor: 'rgb(255, 99, 132)',
data: [300,150] //300 being the total data,150 being the data used
}]
},
// Configuration options go here
options: {}
But the above code isnt working out.Assume a doughnut chart,If the used data is 150GB(out of 300).The doughnut
chart must be like image1(please refer image 1)
But im getting image2(please refer image 2)
https://i.stack.imgur.com/nFTym.png //image 1
https://i.stack.imgur.com/MG99s.png //image 2
Assuming that the used data should appear in red, data should be defined as follows:
data: [used, total - used]
Please have a look at your amended code sample below.
const total = 300;
const used = 100;
var chart = new Chart(document.getElementById('myChart'), {
type: 'doughnut',
data: {
datasets: [{
label: 'My First dataset',
backgroundColor: ['red', 'green'],
borderColor: 'rgb(255, 99, 132)',
data: [used, total - used]
}]
},
options: {}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<canvas id="myChart" height="90"></canvas>
We're trying to give colleagues the ability to share ChartJS graphs with each other. Most of our current graphs are dynamic and users can apply filters (dates, add/remove data etc).
The plan is to have a button that, on click, will get the data and properties (labels, line colours, borderWidth, chart type etc) and pass this data via a url. The user can then send that link to someone else. They can open it up to view that chart captured as it was seen by the original user, like a screenshot, but with all the interactive features enabled.
E.g.
stackoverflow.com/shared_chart.php?conf=%7B%22responsive%22:true,%22responsiveA
When a chart is created by myChart = new Chart(ctx, config); ChartJs adds a lot of new properties to the chart object (e.g $plugin, _meta) that I don't need.
And, when I JSON.stringify(myChart.config) I get an error "Uncaught TypeError: Converting circular structure to JSON".
I've added the code needed to create a sample bar chart below:
// HTML needs a canvas element
<-- <canvas id="myChart"></canvas> -->
const ctx = $('#myChart');
let config;
let myChart;
// config would look something like this
config = {
type: 'bar',
data: {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
label: 'Dataset 1',
backgroundColor: 'rgba(92,184,92,0.5)',
borderColor: 'rgba(92,184,92,1.000)',
borderWidth: 2,
data: [
1,2,3,4,3,2,1
]
}, {
label: 'Dataset 2',
backgroundColor: 'rgba(66,139,202,0.5)',
borderColor: 'rgba(66,139,202,1)',
borderWidth: 2,
data: [
7,2,3,1,5,2,1
]
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
legend: {
position: 'top',
},
title: {
display: true,
text: 'Chart.js Bar Chart'
}
}
}
myChart = new Chart(ctx,config);
On the page they are directed to, I'd like to grab the GET data and construct a new Chart.
You can exclude the extra properties that Chart.js adds. E.g.:
JSON.stringify(myChart.config, function(key, value) {
if (key === '_meta') return undefined;
else return value;
}
I have few charts ready in chart.js. I am trying to put the data that I have fetched through JSON file. How do I change the chart data automatically in a chart? I am getting json data from URL.
chartData1:{
labels: ["01 Jan","02 Jan","03 Jan","04 Jan","05 Jan","06
Jan","07 Jan"],
datasets: [{
label: "s1",
data:
[100,0,1,0,0,1,0,0,0,1,2,3,0,0,0,0,1,1,1,0,0,0,2,1,1,0,1,3,2,1,0],
fill:false,
borderColor: 'Orange',
lineTension:0,
borderWidth:2,
radius:2
},
{
label: "s2",
data:
[2,3,4,1,4,5,3,2,0,1,0,3,5,6,3,7,2,0,5,3,1,2,3,1,0,5,4,5,8,6,2],
fill:false,
borderColor: 'Violet',
lineTension:0,
borderWidth:2,
radius:2
}
]
},
"line-chart" is the id of the <canvas> where you want to display chart.
Try with this.
var chart1 = document.getElementById("line-chart").getContext("2d");
window.myLine = new Chart(chart1).Line(chartData1, {
responsive: true,
scaleLineColor: "rgba(0,0,0,.2)",
scaleGridLineColor: "rgba(0,0,0,.05)",
scaleFontColor: "#c5c7cc"
});
Using chart.js v2, is it possible to mark a dataset in a line chart as being disabled on initial load?
Didn't find an option for it in the documentation.
Yes, there is a "hidden" flag in ChartJS.
eg.
data:
{
datasets: [
{
data: [1,2,3],
label: 'My First Dataset',
hidden: true,
},
],
}
See this issue on GitHub: https://github.com/chartjs/Chart.js/issues/689
The accepted solution has the downside, that hiding/unhiding signals might sometimes fail after initializing the chart like that.
It might be a better idea to change it in the current metadata of the dataSet, which holds the actual data that is used by the chart:
chart.data.datasets.forEach((dataSet, i) => {
var meta = chart.getDatasetMeta(i);
meta.hidden = (<your-condition-here>);
});
this.chart.update();
If you are using angular-chartjs, then you can add the properties of the dataset in the chart-dataset-override property:
For example:
HTML:
<div class="container" ng-app="app" ng-controller="ChartCtrl">
<canvas id="bar" class="chart chart-bar" chart-data="data" chart-labels="labels" chart-series="series" chart-dataset-override="datasetOverride">
</canvas>
</div>
Javascript:
Chart.defaults.global.legend.display = true;
angular.module("app", ["chart.js"])
.controller("ChartCtrl", function($scope) {
$scope.labels = ['2006', '2007', '2008', '2009', '2010', '2011', '2012'];
$scope.series = ['Series A', 'Series B'];
$scope.data = [
[65, 59, 80, 81, 56, 55, 40],
[28, 48, 40, 19, 86, 27, 90]
];
$scope.datasetOverride = [{}, {
hidden: true,
}];
});
Alright, so I am trying to create a ChartJS instance via VueJS so that I could easily update its data via AJAX requests inside the component.
Basically it is working, the ChartJS instance gets created but it is empty and has a height and width of 0 and when I resize it via console it is still empty.
So what would be the best way of creating a "ChartJS Component" with VueJS or where is the fault in my code below?
The very basic way I want to load chart is like this.
<chart :resource="'https://httpbin.org/get'"></chart>
This is the basic component
var Vue = require('vue');
Vue.component('chart', {
template: require('./template.html'),
props: ['resource'],
data: function() {
return {
startingData: {},
latestLabel: {},
}
},
ready: function() {
// here I would load the js data and set the startingData
},
});
This is the directive which I use to pass down the data from the component. I do it this way to get this.el so that I can get the Context of it
Vue.directive('loadData', function(value) {
var startingData = {
labels: [1, 2, 3, 4, 5, 6, 7],
datasets: [{
fillColor: "rgba(151,187,205,0.2)",
strokeColor: "rgba(151,187,205,1)",
pointColor: "rgba(151,187,205,1)",
pointStrokeColor: "#fff",
data: [28, 48, 40, 19, 86, 27, 90]
}]
},
latestLabel = startingData.labels[6];
var liveChart = new Chart(this.el.getContext('2d')).Bar(startingData);
setInterval(function() {
liveChart.addData([Math.random() * 100], ++latestLabel);
liveChart.removeData();
}, 1000);
});
This is the template of the component
<canvas width="960" height="300" v-load-data="startingData"></canvas>
You are concerned by this issue. Your graph does not render because, as you pointed out, the graph has a height and width of 0.
I had this problem while working with tabsets, and I solved it by redrawing the graph with a directive like this :
app.directive('graphCanvasRefresh', ['$compile', function($compile) {
function link(scope, elem, attrs) {
function refreshDOM() {
var markup = '<canvas class="chart chart-pie" id="graph" data="entityGraph.data" labels="entityGraph.labels" legend="true" colours="graphColours" ></canvas>';
var el = angular.element(markup);
compiled = $compile(el);
elem.html('');
elem.append(el);
compiled(scope);
};
// Refresh the DOM when the attribute value is changed
scope.$watch(attrs.graphCanvasRefresh, function(value) {
refreshDOM();
});
// Clean the DOM on destroy
scope.$on('$destroy', function() {
elem.html('');
});
};
return {
link: link
};
}]);
Hope this can help you