I have created a Google Pie chart. I need to add a border around the Google pie chart can you guys help me to add this? I have added the code for the Google Chart and the image I want it to be done.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.3.js"></script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {
packages: ["corechart"]
});
google.setOnLoadCallback(drawChart);
var values = [];
$(document).ready(function() {
$.ajax({
type: "GET",
url: "ChartData.xml",
dataType: "xml",
success: function(xml) {
$(xml).find('Pie').each(function() {
var sTitle = $(this).find('Title').text();
var sValue = $(this).find('Value').text();
if (!isNaN(+sValue)) {
sValue = +sValue;
}
values.push([sTitle, sValue]);
});
drawChart(values);
},
error: function() {
alert("An error occurred while processing XML file.");
}
});
});
function drawChart(val) {
var data = google.visualization.arrayToDataTable(val);
var options = {'title':'Sample Charts', 'width':650, 'height':600, pieHole: 0.5, colors: ['#F6891F', '#A59B91', '#72C5EF', '#53585A', '#C8502B'], tooltip: {showColorCode: true}, is3D: false };
var chart = new google.visualization.PieChart(document.getElementById('piechart'));
chart.draw(data, options);
}
</script>
<title>My Read</title>
</head>
<body>
<div id="piechart"></div>
</body>
</html>
#piechart {
width:120px;
margin: 10px;
border:5px solid red;
border-radius: 100px;
-webkit-border-radius: 500px;
-moz-border-radius: 500px;
}
try giving this css style. It may Work. You can change dimensions accordingly.
I hope it works for you
Old question but maybe somebody could still use this:
function drawPieBorder(chart) {
var layout = chart.getChartLayoutInterface();
var chartArea = layout.getChartAreaBoundingBox();
var svg = chart.getContainer().getElementsByTagName('svg')[0];
var radius = chartArea.height/2;
var path = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
path.setAttribute('stroke', 'black');
path.setAttribute('stroke-width', 1);
path.setAttribute('fill', 'transparent');
path.setAttribute('cx', radius + chartArea.left);
path.setAttribute('cy', radius + chartArea.top);
path.setAttribute('r', radius);
svg.appendChild(path);
}
Related
I create a Google charts, in php page
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load("current", {packages:['corechart']});</script>
<script type="text/javascript">
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
["M", "COUNT",{ role: 'style' }],
var view = new google.visualization.DataView(data);
var options = {
width: 200,
height: 400,
bar: {groupWidth: "95%"},
legend: { position: "none" },
};
var chart1 = new google.visualization.ColumnChart(document.getElementById("columnchart_values1"));
chart1.draw(view, options);
document.getElementById("columnchart_values1").style.display = "block";
}
</script>
<div style="width:80%;"class="columnchart_values" id="columnchart_values1"> </div>
The graph is fine, but the page width varies - very large. Why?
enter image description here
I have a Google line chart which doesn't show up after loading the page. After the first resize everything works.
How can I get the chart show up after loading the page?
Data comes from locale text file on the server. This textfile holds the date/time and a sensor value. Textfile gets split and used as data for the chart.
google.load('visualization', '1.0', {'packages':['corechart']});
google.setOnLoadCallback(drawChart);
function drawChart () {
$.ajax({
url: 'Temp.ESP',
type: 'get',
success: function (txt) {
var dataArray = [['Name', 'Date']];
var txtArray = txt.split('\n');
for (var i = 0; i < txtArray.length; i++) {
var tmpData = txtArray[i].split(/\s+/);
dataArray.push([tmpData[0], parseInt(tmpData[1])]);
}
var data = google.visualization.arrayToDataTable(dataArray);
var chart = new google.visualization.LineChart(document.querySelector('#chart_div'));
var options = {width: '100%',
height: '40%',
legend: 'none',
colors: ['red'],
hAxis: {
textStyle:{color: 'white'}},
vAxis: {
textStyle:{color: 'white'}},
backgroundColor: { fill:'transparent' }};
$(window).resize(function(){
chart.draw(data,options);
});
}
});
}
google.load('visualization', '1', {packages:['corechart'], callback: drawChart});
setInterval(function(){
$.get( "mydata.php", function( data ) {
$( "#mydata" ).html( data ); // this will replace the html refreshing its content using ajax
});
}, 1000);
/* Chart */
#chart{
width: 100%;
}
<div id="chart">
<div id="chart_div"></div>
</div>
thank you!
Hard to know what's going on without being able to run your code, but it could just be a simple css fix. Try changing the parent to a flex container at 100vw and the child chart at flex:1
#chart{
width: 100vw;
display: flex;
// adjust the padding accordingly
}
#chart_div {
flex: 1;
}
I forgot to call the draw function.
First call was in the resize function.
function drawChart () {
$.ajax({
url: 'Temp.ESP',
type: 'get',
success: function (txt) {
var dataArray = [['Name', 'Date']];
var txtArray = txt.split('\n');
for (var i = 0; i < txtArray.length; i++) {
var tmpData = txtArray[i].split(/\s+/);
dataArray.push([tmpData[0], parseInt(tmpData[1])]);
}
var data = google.visualization.arrayToDataTable(dataArray);
var chart = new google.visualization.LineChart(document.querySelector('#chart_div'));
var options = {width: '100%',
height: '40%',
legend: 'none',
colors: ['red'],
hAxis: {
textStyle:{color: 'white'}},
vAxis: {
textStyle:{color: 'white'}},
backgroundColor: { fill:'transparent' }};
chart.draw(data,options); //forgot this call
$(window).resize(function(){
chart.draw(data,options);
});
}
});
Thanks for the inspiration!
I'm using Google Charts and I'm trying to add multiple charts to one json call.
The chart style is gauge.
The example below works for only one gauge "field1" I'm not that great with the charts but I did create a working example that updates.
What I want to add is two more gauges and the json array names would be Tlak,Vlhkost. So the json would look something like this {"created_at":"2017-04-19T17:05:54Z","entry_id":4381,"field1":"1.00\r\n\r\n","field2":"83"}
How would I go about adding one more gauges?
<html>
<head>
<title>Google Gauge - ThingSpeak</title>
</head>
<body>
<div id="container">
<div id="inner">
<div id="gauge_div"></div>
</div>
</div>
</body>
</html>
//css
<style type="text/css">
body { background-color: #FFFFFF; }
#container { height: 100%; width: 100%; }
#inner { }
#gauge_div { margin: 0 auto; }
</style>
<script type='text/javascript' src='https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js'></script>
<script type='text/javascript' src='https://www.google.com/jsapi'></script>
<script type='text/javascript'>
// set your channel id here
var channel_id = 248987;
// set your channel's read api key here if necessary
var api_key = '16UK5LLONGR9LCR2';
// maximum value for the gauge
var max_gauge_value = 1023;
// name of the gauge
var gauge_name = 'Tlak';
// global variables
var chart, charts, data;
// load the google gauge visualization
google.load('visualization', '1', {packages:['gauge']});
google.setOnLoadCallback(initChart);
// display the data
function displayData(point) {
data.setValue(0, 0, gauge_name);
data.setValue(0, 1, point);
chart.draw(data, options);
}
// load the data
function loadData() {
// variable for the data point
var p;
// get the data from thingspeak
$.getJSON('https://api.thingspeak.com/channels/' + channel_id + '/feed/last.json?api_key=' + api_key, function(data) {
// get the data point
p = data.field1;
// if there is a data point display it
if (p) {
// p = Math.round((p / max_gauge_value) * 100);
displayData(p);
}
});
}
// initialize the chart
function initChart() {
data = new google.visualization.DataTable();
data.addColumn('string', 'Label');
data.addColumn('number', 'Value');
data.addRows(1);
chart = new google.visualization.Gauge(document.getElementById('gauge_div'));
options = {
width: 160, height: 160, min: 955, max: 1065,
majorTicks: [950, 980, 1010, 1040, 1060], minorTicks: 10,
greenFrom: 955,
greenTo: 1000,
greenColor: "#00e600",
yellowFrom: 1000,
yellowTo: 1020,
yellowColor: "#ff751a",
redFrom: 1020,
redTo: 1065,
redColor: "#FF0000"};
loadData();
// load new data every 15 seconds
setInterval('loadData()', 15000);
}
</script>
first, recommend using loader.js vs. the older library jsapi
according to the release notes...
The version of Google Charts that remains available via the jsapi loader is no longer being updated consistently. Please use the new gstatic loader.js from now on.
this will only change the load statement, see following snippet...
next, start by loading the data, before building anything else
once the json data is received, use it to determine which charts to draw,
according the properties specified by field1, field2, etc...
see following working snippet...
// load the google gauge visualization
google.charts.load('current', {
callback: loadData,
packages:['gauge']
});
function loadData() {
// set your channel id here
var channel_id = 248987;
// set your channel's read api key here if necessary
var api_key = '16UK5LLONGR9LCR2';
// variable for the data point
var p;
// name of the gauge
var gauge_name;
// get the data from thingspeak
$.getJSON('https://api.thingspeak.com/channels/' + channel_id + '/feed/last.json?api_key=' + api_key, function(jsonData) {
for (var key in jsonData) {
if (jsonData.hasOwnProperty(key)) {
if (key.indexOf('field') > -1) {
p = jsonData[key];
switch (key) {
case 'field1':
gauge_name = 'Tlak';
break;
case 'field2':
gauge_name = 'Vlhkost';
break;
default:
gauge_name = key;
}
displayData(key, p, gauge_name);
}
}
}
});
setInterval(loadData, 15000);
}
// display the data
function displayData(div, point, name) {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Label');
data.addColumn('number', 'Value');
data.addRows(1);
data.setValue(0, 0, name);
data.setValue(0, 1, point);
var chartContainer = document.getElementById('gauge_div_' + div) || null;
if (chartContainer === null) {
chartContainer = document.getElementById('inner').appendChild(document.createElement('div'));
chartContainer.id = 'gauge_div_' + div;
chartContainer.className = 'gauge';
}
var chart = new google.visualization.Gauge(chartContainer);
var options = {
width: 160, height: 160, min: 955, max: 1065,
majorTicks: [950, 980, 1010, 1040, 1060], minorTicks: 10,
greenFrom: 955,
greenTo: 1000,
greenColor: "#00e600",
yellowFrom: 1000,
yellowTo: 1020,
yellowColor: "#ff751a",
redFrom: 1020,
redTo: 1065,
redColor: "#FF0000"
};
chart.draw(data, options);
}
body { background-color: #FFFFFF; }
#container { height: 100%; width: 100%; }
#inner { }
.gauge { margin: 0 auto; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="container">
<div id="inner"></div>
</div>
note: the chart container divs are added dynamically...
I am trying to show multiple diagrams/charts at the same time using chart.js.
For my setup, I have one chart.html file which displays the diagram and a split.html file which creates multiple iframes (2 so far) and loads the chart.html in them.
When opening the chart.html directly, the resizing works, but when loaded in iframe it doesn't.
I could only imagine the error at chart.js since the sizing itself is already weird. It orients on the next "higher" element (div with fixed 100% width and height in my case) and setting width or height directly on the canvas doesnt change anything, see code below.
chart.html:
<html>
<head>
<script src="./node_modules/chart.js/dist/Chart.bundle.js"></script>
<script src="./node_modules/jquery/dist/jquery.min.js"></script>
<script src="./js/diagram.js"></script>
</head>
<body>
<div id="container" style="width:100%; height:100%;">
<canvas id="diagram"></canvas>
</div>
</body>
split.html:
<html>
<head>
<link rel="stylesheet" href="./css/splitter.css" />
<script src="./node_modules/jquery/dist/jquery.min.js"></script>
<script src="./js/splitter.js"></script>
</head>
<body>
<div id="content">
</div>
</body>
diagram.js:
$(document).ready(function() {
var ctx = document.getElementById("diagram");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: /** excluded (unimportance) **/
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
// Resize chart
$(window).resize(function() {
console.log("resize works!");
if(myChart) myChart.update();
});
});
splitter.js:
$(document).ready(function () {
const splits = 2;
switch (splits) {
case 2:
$("#content").append(
$('<iframe />')
.attr("id", "frame1")
.attr("src", "./chart.html")
.addClass("width50 height100")
);
$("#content").append(
$('<iframe />')
.attr("id", "frame2")
.attr("src", "./chart.html")
.addClass("width50 height100 left50")
);
break;
}
});
splitter.css:
iframe {
position: fixed;
border: none;
margin: 0;
padding: 0;
}
.width100 {
width: 100%;
}
.height100 {
height: 100%;
}
.width50 {
width: 50%;
}
.height50 {
height: 50%;
}
.left50 {
left: 50%;
}
.top50 {
top: 50%;
}
Change iframes to divs with modifiing your splitter.js:
$(document).ready(function () {
const splits = 2;
for(var i = 0; i < splits;i++){
var chartContainer = $('<div id="frame' + (i + 1) + '"></div>').appendTo("#content");
var canvas = $('<canvas class="diagram">').appendTo(chartContainer);
if(i === 0)
chartContainer.addClass('width50 height100');
else
chartContainer.addClass('width50 height100 left50');
}
});
It will add two divs to the content element instead of iframes and also put the canvases into the divs.
Than change your diagram.js to foreach over the canvases and make them work as a chart:
$('canvas.diagram').each(function(){
var ctx = $(this);
var myChart = new Chart(ctx, {
//here comes the chart configuration...
});
});
Change your css to align the two div next to each other with
.width50 {
width: 50%;
display: inline-block;
}
So the charts are now inside block elements and because of they're set to be responsive if you resize the window they will be resized automatically based on their parent elements' width (so you can remove the resizing part from your script too)
I am using markerCluster for Leaflet with the showCoverageOnHover option set to true. However, in Firefox (v 46.0.1), the event showCoverageOnHover is not triggered correctly, meaning that the cluster area is shown not only when the mouse is hovered over the cluster, but also if the mouse is far away from that cluster.
Basically, I am using the standard procedure to create a markerClusterGroup, but with a customized icon creation function (Using d3 to draw a Pie chart). My code looks as follows:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style type="text/css">
#mapid {
height: 60vh;
}
</style>
<script src='https://api.mapbox.com/mapbox.js/v2.4.0/mapbox.js'></script>
<link href='https://api.mapbox.com/mapbox.js/v2.4.0/mapbox.css' rel='stylesheet' />
<script src='https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/0.5.0/leaflet.markercluster.js'></script>
<link href='https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/0.5.0/MarkerCluster.css' rel='stylesheet' />
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<title>WorldMap</title>
<script type="text/javascript">
function defineClusterIcon(cluster) {
var color = d3.scale.category20b();
//some dummy json
var myjson = '[{ "label":"Monday", "count": 15 },{ "label":"Tuesday", "count": 20 }]';
var dataset = JSON.parse( myjson );
var size = 40;
var radius= size / 2;
var svgres = document.createElementNS(d3.ns.prefix.svg, 'svg');
var svg = d3.select(svgres).append('svg')
.attr('width', size)
.attr('height', size)
.append('g')
.attr('transform','translate(' + (size / 2) + ',' + (size / 2) + ')'); //center g
var arc = d3.svg.arc().outerRadius(radius);
var pie = d3.layout.pie().value(function(d) {
return d.count;
});
//create final chart
svg.selectAll('path').data(pie(dataset)) //fill dataset into path
.enter() //create placeholder for data
.append('path') //fill placeholder with data in path
.attr('d', arc) //define an attribute d
.attr('fill', function(d, i) {
return color(d.data.label);
});
var html = serializeXmlNode(svgres);
var myIcon = new L.DivIcon({
html : html,
className : 'mycluster',
iconSize : new L.Point(size, size)
});
return myIcon;
}
function serializeXmlNode(xmlNode) {
if (typeof window.XMLSerializer != "undefined") {
return (new window.XMLSerializer()).serializeToString(xmlNode);
} else if (typeof xmlNode.xml != "undefined") {
return xmlNode.xml;
}
return "";
}
</script>
</head>
<body>
<div id="mapid"></div>
<script type="text/javascript">
var map = L.map('mapid', {
center: [40, 40],
maxZoom : 10,
zoom: 2
});
//create markercluster
var markers = new L.markerClusterGroup({
showCoverageOnHover: true,
iconCreateFunction: defineClusterIcon
});
//some example markers
var marker = new L.marker([40.0,10.0]);
markers.addLayer(marker);
var marker = new L.marker([42.0,-12.0]);
markers.addLayer(marker);
var marker = new L.marker([50.0,30.0]);
markers.addLayer(marker);
map.addLayer(markers);
</script>
</body>
</html>
Any ideas why the showCoverageOnHover event is not triggered correctly in Firefox?
Thanks!
Looks like the SVG element you created overflows the Leaflet icon.
Simply setting overflow: hidden CSS rule on your icon class seems to solve your issue.
.mycluster {
overflow: hidden;
}
Updated JSFiddle: https://jsfiddle.net/sqeypmrn/1/
Note: question also posted on Leaflet.markercluser GitHub page as issue #677.