EDIT:
So now I have a chart with all my data pushed off to the right, BUT I have labels in different colors for the sets I want to show but no data?? Updated my code
Original post:
I have a working highchart here http://opensourcesurf.com/chart.html . The problem is when I try and change the color of an individual data set, they all change. How could I change these settings given my code? Thanks in advance!
code:
var options1 = {
chart: {
renderTo: 'container1',
type: 'area'
},
xAxis: {
type: 'datetime'
},
series: [{
name: 'Swell Period',
color: '#0066FF',
data: 'newSeriesData',
},
{ name: ' Maximum Breaking Wave Height',
color: '#ffffff',
data: 'newSeriesData',
},
{ name: 'Swell Height',
color: '#123456',
data: 'newSeriesData',
}],
};
var drawChart = function(data, name, color) {
var newSeriesData = {
name: name,
data: data
};
// Add the new data to the series array
options1.series.push(newSeriesData);
// If you want to remove old series data, you can do that here too
// Render the chart
var chart = new Highcharts.Chart(options1);
};
$.getJSON('decode.php', function(data){
drawChart(data, 'Swell Height');
});
$.getJSON('decode2.php', function(data){
drawChart(data, ' Maximum Breaking Wave Height');
});
$.getJSON('decode3.php', function(data){
drawChart(data, 'Swell Period');
});
Try this:
// 'series' is an array of objects with keys:
// - 'name' (string)
// - 'data' (array)
// - 'color' (HTML color code)
var newSeriesData = {
name: name,
data: data,
color: color
};
The way to specify a color for a specific series is to define it when you're defining the series. For example:
series: [{
name: 'John',
color: '#0066FF',
dashStyle: 'ShortDash',
data: [
[Date.UTC(2010, 0, 1), 29.9],
[Date.UTC(2010, 2, 1), 71.5],
[Date.UTC(2010, 3, 1), 106.4]
]
},
So essentially when you're creating your series in your drawchart function, do a check for the name, and appropriately assign a color:
var color;
if(name=="Swell Height"){
color="#0066FF";
}else if(name=="Maximum Breaking Wave Height"){
color="#0066EE";
}else if(name=="Swell Period"){
color="#0066HH";
}
var newSeriesData = {
name: name,
data: data,
color: color
};
It looks to me like you are not looping through the array of data and/or you only have one set of data in data.
Related
I am working with a echarts javascript chart and trying to get it to work with my data in Zoomdata. I have the data grouped by 20 different computers so I am looking to do a stacked line chart with 20 lines. I know how to hard code this but I would like to link the data in Zoomdata to the code to display in the chart. Right now it just plots all 20 computers on one line.
import echarts from 'echarts'; //
import styles from './index.css';
// create chart container
const chartContainer = document.createElement('div');
chartContainer.style.width = '100%';
chartContainer.style.height = '100%';
chartContainer.classList.add(styles.chartContainer);
controller.element.appendChild(chartContainer);
const groupAccessor = controller.dataAccessors['Group By'];
const metricAccessor = controller.dataAccessors.Size;
//Need help
//Part Im having trouble with linking data in zoomdata to this chart
const chart = echarts.init(chartContainer);
const option = {
xAxis: {
type: 'category',
data: []
},
yAxis: {
type: 'value'
},
series: [
{
name:'邮件营销',
type:'line',
stack: '总量',
data:[120, 132, 101, 134, 90, 230, 210]
},
{
name:'联盟广告',
type:'line',
stack: '总量',
data:[220, 182, 191, 234, 290, 330, 310]
},
{
name:'视频广告',
type:'line',
stack: '总量',
data:[150, 232, 201, 154, 190, 330, 410]
},
{
name:'直接访问',
type:'line',
stack: '总量',
data:[320, 332, 301, 334, 390, 330, 320]
},
{
name:'搜索引擎',
type:'line',
stack: '总量',
data:[820, 932, 901, 934, 1290, 1330, 1320]
}
]
};
//Rest of code
controller.update = data => {
// Called when new data arrives
option.series[0].data = reshapeData(data);
chart.setOption(option);
};
function reshapeData(data) {
return data.map(d => ({
name: groupAccessor.raw(d),
value: metricAccessor.raw(d),
datum: d,
itemStyle: { //tell the chart you would like to use the colors selected
color: groupAccessor.color(d),//tell the chart you would like to use the colors selected
}, //tell the chart you would like to use the colors selected
}));
}
chart.on('mousemove', param => {
controller.tooltip.show({
event: param.event.event,
data: () => param.data.datum,
});
});
chart.on('mouseout', param => {
controller.tooltip.hide();
});
chart.on('click', param => {
controller.menu.show({
event: param.event.event,
data: () => param.data.datum,
});
});
controller.createAxisLabel({
picks: 'Group By',
position: 'bottom',
orientation: 'horizontal',
});
controller.createAxisLabel({
picks: 'Size',
position: 'bottom',
orientation: 'horizontal',
});
The json looks like:
[
{
current: {
count: 1508,
metrics: null,
na: false
},
group: [
"Computer1"
]
},
{..},
{..}
]
Thanks for adding the json details. If I understood it good, the value you want to display on each line must be current.count, and the name of each series is given by the first item in the group array (I don't know why it's an array, though).
Here is the code I would write if I want to map your data on ECharts:
/*
* incremental update counter. This will be displayed
* on the xAxis by being pushed to options.xAxis.data array.
*/
let updateCount = 0,
// initialize series as empty
const options = {
xAxis: {
type: 'category',
data: []
},
yAxis: {
type: 'value'
},
series: []
}
controller.update = data => {
updateCount++
if (options.series.length > 0) {
// Called when new data arrives
options.xAxis.data.push('record ' + updateCount)
options.series = updateData(data)
} else {
// Called only once to initialize
options.xAxis.data.push('record ' + updateCount)
options.series = initData(data)
}
// you can remove the following line if your chart is already reactive.
chart.setOption(option)
}
// the init function.
const initData = data => {
// transform each item in the data array into a series entry.
data.map(item => {
return {
name: item.group[0],
type: 'line',
stack: 'defaultStack',
data: [item.current.count]
}
})
}
// the update function.
const updateData = newData => {
// push new data counts to its respective series data.
options.series.forEach((item, index) => {
item.data.push(newData[index].current.count)
}
}
It's a bit long but more secure way to parse your raw data into an ECharts option. Let me know if you have any issue with this, I haven't tested yet so it's only brain code.
I have the following array:
Where the arrays keys are the dates and the only element I want to plot, of each set, is the weight. Look:
I am putting the code as follows. Notice that I am already grouping in the date attribute the whole set belonging to each that key.
var ctx = document.getElementById("barChart").getContext("2d");
var data = {
labels: ['21/03/2018','01/04/2018','02/04/2018','04/04/2018','05/04/2018','06/04/2018'],
datasets: [
{
label: '21/03/2018',
data: [12, 0, 0]
},
{
label: '01/04/2018',
data: [15.00, 15.00,15.00]
},
{
label: '02/04/2018',
data: [25.00, 25.00, 25.00]
},
{
label: '04/04/2018',
data: [25.00, 25.00, 25.00]
},
{
label: '05/04/2018',
data: [-8.14,-7.93, -7.84]
},
{
label: '06/04/2018',
data: [-35.9 ,-38.1, -37.5]
},
]
};
var myBarChart = new Chart(ctx, {
type: 'bar',
data: data,
});
But in this way ChartJs does not understand that it only needs to plot the data set present in the "data" attribute and grouping them by the key. Plotting the graph in the wrong way.
How could I plot the data correctly knowing that they are already grouped?
You need to organize your data as such:
var ctx = document.getElementById("canvas").getContext("2d");
var data = {
labels: ['21/03/2018','01/04/2018','02/04/2018','04/04/2018','05/04/2018','06/04/2018'],
datasets: [
{
data: [12, 15.00, 25.00, 25.00, -8.14, -35.9]
},{
data: [0, 15.00, 25.00, 25.00, -7.93, -38.1]
},{
data: [0, 15.00, 25.00, 25.00, -7.84, -37.5]
}
]
};
var myBarChart = new Chart(ctx, {
type: 'bar',
data: data,
options:{
legend: 'none'
}
});
I took your legend out as it's useless in this case. To look at it in the coding persepective, whatever index the date in labels is at needs to correlate with the index of the information you want to display in that grouping. data[0] refers to labels[0] and so on.
I am creating a combination chart taking data from a database. I am able to import all the data and render it in single type i.e. Column. There is one series though which I want to render in spline type. The tutorial I am following only teaches about rendering in a single type, so I am kind of lost here.
This is my JavaScript
$(document).ready(function(){
var options = {
chart: {
renderTo: 'fetch-render',
type: 'column',
},
xAxis: {
title: {
text: 'Date'
},
categories: []
},
yAxis: {
title: {
text: 'Number'
},
series: []
}
$.getJSON("includes/fetch-data.php", function(json) {
options.xAxis.categories = json[0]['data'];
options.series[0] = json[1];
options.series[1] = json[2];
/*so on...... */
options.series[7] = json[8];
/* i want to draw this series in spline */
options.series[8] = json[9];
chart = new Highcharts.Chart(options);
});
})
I want to draw data from series 8 as a spline unlike others which are drawn in column type
Highcharts Demos have all kinds of demos of using Highcharts. One of them shows how to draw different types of series in the same chart: http://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/demo/combo/
Basically, instead of defining the type on the chart object like you did, you will set the type for each series on your series object:
series: [{
type: 'column',
name: 'Jane',
data: [3, 2, 1, 3, 4]
}, {
type: 'column',
name: 'John',
data: [2, 3, 5, 7, 6]
}, {
type: 'column',
name: 'Joe',
data: [4, 3, 3, 9, 0]
}, {
type: 'spline',
name: 'Average',
data: [3, 2.67, 3, 6.33, 3.33],
marker: {
lineWidth: 2,
lineColor: Highcharts.getOptions().colors[3],
fillColor: 'white'
}
}
Thanks for the heads up by #João Menighin . i adopted the method given in this demo. its neater, cleaner and can be used to add as many chart types as needed. here is the code for someone else who wants to make a combined chart taking data from the database.
$(document).ready(function(){
$.getJSON("includes/fetch-data.php", function(json){
Highcharts.chart('fetch-render', {
title: {
text: 'Fetched Data'
},
xAxis: {
categories: json[0]['data']
},
series: [{
type: json[1]['type'],
name: json[1]['name'],
data: json[1]['data']
}, {
type: json[2]['type'],
name: json[2]['name'],
data: json[2]['data']
}, {
type: json[3]['type'],
name: json[3]['name'],
data: json[3]['data']
},{
type: json[4]['type'],
name: json[4]['name'],
data: json[4]['data']
}, {
type: json[5]['type'],
name: json[5]['name'],
data: json[5]['data']
}, {
type: json[6]['type'],
name: json[6]['name'],
data: json[6]['data']
}, {
type: json[7]['type'],
name: json[7]['name'],
data: json[7]['data']
},{
type: json[8]['type'],
name: json[8]['name'],
data: json[8]['data']
},{
type: json[9]['type'],
name: json[9]['name'],
data: json[9]['data']
}],
});
})
})
And i have set the chart types in fetch-data.php like this
$date = array();
$date['name'] = 'Date';
$blank=array();
$blank['name'] = 'Blank';
$blank['type'] = 'column';
$direct=array();
$direct['name'] = 'Direct';
$direct['type'] = 'area';
$checked_in=array();
$checked_in['name'] = 'Checked In';
$checked_in['type'] = 'column';
$conf=array();
$conf['name'] = 'Conf';
$conf['type'] = 'column';
$gdf=array();
$gdf['name'] = 'GDF';
$gdf['type'] = 'column';
$gdp=array();
$gdp['name'] = 'GDP';
$gdp['type'] = 'column';
$gtn=array();
$gtn['name'] = 'GTN';
$gtn['type'] = 'column';
$prov=array();
$prov['name'] = 'PROV';
$prov['type'] = 'column';
$enquire=array();
$enquire['name'] = 'ENQUIRE';
$enquire['type'] = 'spline';
I am drawing graph on UI using ChartJS 2.0. And I am able to render a Pie Chart. But I want the mouse-hover to show the data along with a "%" sign. How can I append % So if on mouse hover I am getting Rented: 93 I would like to see Rented: 93 %. Kindly guide me.
Below is what I have now:
var sixthSubViewModel = Backbone.View.extend({
template: _.template($('#myChart6-template').html()),
render: function() {
$(this.el).html(this.template());
var ctx = this.$el.find('#pieChart')[0];
var data = {
datasets: [{
data: this.model.attributes.currMonthOccAvailVac,
backgroundColor: [
"#455C73",
"#BDC3C7",
"#26B99A",
],
label: 'My dataset' // for legend
}],
labels: [
"Rented",
"Vacant",
"Unavailable",
]
};
var pieChart = new Chart(ctx, {
type: 'pie',
data: data
});
},
initialize: function(){
this.render();
}
});
Understanding:
I understand that currently hover takes the label and adds a colon and then adds data to it. So if label = Rented, Data = 93 I will see something like Rented: 93 on mouse-hover. How can I change text of mouse-hover to display Rented: 93%. Below is the image of what I have till now on mouse-hover.
I understand that I need to add one "options" in the pie chart. But I am not sure how to do that. Please help me.
You can edit what is displayed in your tooltip with the callbacks.label method in your chart options, and then simply add a "%" to the default string using :
tooltipItems -- See documentation for more information (scroll up a bit to "Tooltip Item Interface")
data -- Where the datasets and labels are stored.
var ctx = document.getElementById("canvas");
var data = {
datasets: [{
data: [93, 4, 3],
backgroundColor: [
"#455C73",
"#BDC3C7",
"#26B99A",
],
label: 'My dataset' // for legend
}],
labels: [
"Rented",
"Vacant",
"Unavailable",
]
};
var pieChart = new Chart(ctx, {
type: 'pie',
data: data,
options: {
tooltips: {
callbacks: {
label: function(tooltipItems, data) {
return data.labels[tooltipItems.index] +
" : " +
data.datasets[tooltipItems.datasetIndex].data[tooltipItems.index] +
' %';
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.2.1/Chart.min.js"></script>
<canvas id="canvas" height="150"></canvas>
I'm attempting to combine a couple of different chart demos from Highcharts.
My examples are: Data classes and popup and Small US with data labels
I want the map from the first with the popup feature of the second. I need to connect the map to my own google spreadsheet but for now I'm just trying to get the data from the first example to work.
This is what I have so far but can't seem to get any data in the map. I thought I had a joinBy problem, and I may still, but when I set joinBy to null I thought "the map items are joined by their position in the array", yet nothing happened.
https://jsfiddle.net/9eq6mydv/
$(function () {
// Load the data from a Google Spreadsheet
// https://docs.google.com/a/highsoft.com/spreadsheet/pub?hl=en_GB&hl=en_GB&key=0AoIaUO7wH1HwdFJHaFI4eUJDYlVna3k5TlpuXzZubHc&output=html
Highcharts.data({
googleSpreadsheetKey: '0AoIaUO7wH1HwdDFXSlpjN2J4aGg5MkVHWVhsYmtyVWc',
googleSpreadsheetWorksheet: 1,
// custom handler for columns
parsed: function (columns) {
// Make the columns easier to read
var keys = columns[0],
names = columns[1],
percent = columns[10],
// Initiate the chart
options = {
chart : {
renderTo: 'container',
type: 'map',
borderWidth : 1
},
title : {
text : 'US presidential election 2008 result'
},
subtitle: {
text: 'Source: <a href="http://en.wikipedia.org/wiki/United_States_presidential_election,' +
'_2008#Election_results">Wikipedia</a>'
},
mapNavigation: {
enabled: true,
enableButtons: false
},
legend: {
align: 'right',
verticalAlign: 'top',
x: -100,
y: 70,
floating: true,
layout: 'vertical',
valueDecimals: 0,
backgroundColor: (Highcharts.theme && Highcharts.theme.legendBackgroundColor) || 'rgba(255, 255, 255, 0.85)'
},
colorAxis: {
dataClasses: [{
from: -100,
to: 0,
color: '#C40401',
name: 'McCain'
}, {
from: 0,
to: 100,
color: '#0200D0',
name: 'Obama'
}]
},
series : [{
data : data,
dataLabels: {
enabled: true,
color: '#FFFFFF',
format: '{point.code}',
style: {
textTransform: 'uppercase'
}
},
mapData: Highcharts.geojson(Highcharts.maps['countries/us/custom/us-small']),
joinBy: keys,
name: 'Democrats margin',
point: {
events: {
click: pointClick
}
},
tooltip: {
ySuffix: ' %'
},
cursor: 'pointer'
}, {
type: 'mapline',
data: Highcharts.geojson(Highcharts.maps['countries/us/custom/us-small'], 'mapline'),
color: 'silver'
}]
};
/**
* Event handler for clicking points. Use jQuery UI to pop up
* a pie chart showing the details for each state.
*/
function pointClick() {
var row = this.options.row,
$div = $('<div></div>')
.dialog({
title: this.name,
width: 400,
height: 300
});
window.chart = new Highcharts.Chart({
chart: {
renderTo: $div[0],
type: 'pie',
width: 370,
height: 240
},
title: {
text: null
},
series: [{
name: 'Votes',
data: [{
name: 'Obama',
color: '#0200D0',
y: parseInt(columns[3][row], 10)
}, {
name: 'McCain',
color: '#C40401',
y: parseInt(columns[4][row], 10)
}],
dataLabels: {
format: '<b>{point.name}</b> {point.percentage:.1f}%'
}
}]
});
}
// Read the columns into the data array
var data = [];
$.each(keys, function (i, key) {
data.push({
key: key,//.toUpperCase(),
value: parseFloat(percent[i]),
name: names,
row: i
});
});
// Initiate the chart
window.chart = new Highcharts.Map(options);
},
error: function () {
$('#container').html('<div class="loading">' +
'<i class="icon-frown icon-large"></i> ' +
'Error loading data from Google Spreadsheets' +
'</div>');
}
});
});
UPDATE:
I wanted to share with everyone my final solution. Although Ondkloss did a magnificent job answering my question the popup feature still didn't work and this is because I forgot to include the jQuery for the .dialog call. Once I included that I had an empty popup with a highchart error 17, this is because the highmaps.js code doesn't include the pie chart class. So I had to add the highcharts.js code and include map.js module afterward. You can see my final jsfiddle here.
Thanks again to Ondkloss for the excellent answer!
The problem here mostly comes down to the use of joinBy. Also to correct it there are some required changes to your data and mapData.
Currently your joinBy is an array of strings, like ["al", "ak", ...]. This is quite simply not an accepted format of the joinBy option. You can read up on the details in the API documentation, but the simplest approach is to have a attribute in common in data and mapData and then supply a string in joinBy which then joins those two arrays by that attribute. For example:
series : [{
data : data,
mapData: mapData,
joinBy: "hc-key",
]
Here the "hc-key" attribute must exist in both data and mapData.
Here's how I'd create the data variable in your code:
var data = [];
$.each(keys, function (i, key) {
if(i != 0)
data.push({
"hc-key": "us-"+key,
code: key.toUpperCase(),
value: parseFloat(percent[i]),
name: names[i],
row: i
});
});
This skips the first key, which is just "Key" (the title of the column). Here we make the "hc-key" fit the format of the "hc-key" in our map data. An example would be "us-al". The rest is just metadata that will be joined in. Note that you were referencing your data in the options prior to filling it with data, so this has to be moved prior to this.
This is how I'd create the mapData variable in your code:
var mapData = Highcharts.geojson(Highcharts.maps['countries/us/custom/us-small']);
// Process mapdata
$.each(mapData, function () {
var path = this.path,
copy = { path: path };
// This point has a square legend to the right
if (path[1] === 9727) {
// Identify the box
Highcharts.seriesTypes.map.prototype.getBox.call(0, [copy]);
// Place the center of the data label in the center of the point legend box
this.middleX = ((path[1] + path[4]) / 2 - copy._minX) / (copy._maxX - copy._minX);
this.middleY = ((path[2] + path[7]) / 2 - copy._minY) / (copy._maxY - copy._minY);
}
// Tag it for joining
this.ucName = this.name.toUpperCase();
});
The first part is your "standard map data". The rest is to correctly center the labels for the popout states, and gotten directly from the example.
And voila, see this JSFiddle demonstration to witness your map in action.
I suggest doing some console.log-ing to see how data and mapData have the hc-key in common and that leads to the joining of the data in the series.