Am creating custom visualization and am using echarts for the visualization.
I have a source and everything but i am unable to make it work. Can anyone help in this how to achieve the below fiddle in looker custom visualization
import * as echarts from 'echarts';
var ROOT_PATH = 'https://echarts.apache.org/examples';
var chartDom = document.getElementById('main');
var myChart = echarts.init(chartDom);
var option;
myChart.showLoading();
$.getJSON(ROOT_PATH + '/data/asset/data/les-miserables.json', function (graph) {
myChart.hideLoading();
graph.nodes.forEach(function (node) {
node.label = {
show: node.symbolSize > 30
};
});
option = {
title: {
text: 'Les Miserables',
subtext: 'Default layout',
top: 'bottom',
left: 'right'
},
tooltip: {},
legend: [{
// selectedMode: 'single',
data: graph.categories.map(function (a) {
return a.name;
})
}],
animationDuration: 1500,
animationEasingUpdate: 'quinticInOut',
series: [
{
name: 'Les Miserables',
type: 'graph',
layout: 'none',
data: graph.nodes,
links: graph.links,
categories: graph.categories,
roam: true,
label: {
position: 'right',
formatter: '{b}'
},
lineStyle: {
color: 'source',
curveness: 0.3
},
emphasis: {
focus: 'adjacency',
lineStyle: {
width: 10
}
}
}
]
};
myChart.setOption(option);
});
option && myChart.setOption(option);
demo url
in the above snippet, they are passing json but in my requirement i need to fetch from selected dimensions or measures and I need to convert into looker custom viz
looker.plugins.visualizations.add({
});
Please do let me know any suggestions on this
Inside the object you pass to looker.plugins.visualizations.add, the updateAsync method ( that you will use to generate the echart options and series ) is async, and it passes you a done callback to be called when you are ready.
So you can call your json, process the data and then done()
Related
As the title says, i want to switch the tooltip header with the tootlip body text.
for me it makes no sense why the standard config is this way around...
i know i can create a custom tootlip but thats not my favorite way to do it.
the code im using currently
var options = {
series: [{
name: 'Series',
data: [v0, v1, v2, v3, v4]
}],
colors: ['#3979bd', '#c1a748', '#69b761', '#69b761', '#d54c4c'],
chart: {
type: 'bar',
height: 200
},
plotOptions: {
bar: {
distributed: true,
borderRadius: 0,
horizontal: true,
}
},
tooltip: {
enabled: true,
},
dataLabels: {
enabled: true,
},
xaxis: {
categories: ['open', 'planned', 'done', 'done cloud', 'stopped'],
}
};
var chart = new ApexCharts(document.querySelector("#overview_apex_sc4stats"), options);
chart.render();
and heres a image what i want
i have a big data set to display ( around 150 category) with a library named vue-apexchart my problem is that i cant find a way to make the graph scrollable on xaxis without having a broken display the following image will explain my problem better
as you can see having too many categories leads to an unreadable chart
can you please help me
i have tried to make a scrollable div, the probleme still remains ( unreadable xaxis )
here's my chartOptions object :
chartOptions: {
chart: {
type: "bar",
height: 350,
},
plotOptions: {
bar: {
horizontal: false,
columnWidth: "55%",
endingShape: "rounded",
},
},
dataLabels: {
enabled: false,
},
stroke: {
show: true,
width: 2,
colors: ["transparent"],
},
xaxis: {
categories: [],
},
fill: {
opacity: 1,
},
},
I think there are two strategies that you could adopt here. In my opinion, the second one is better.
1. Horizontal bar chart
If you do not have strict constraints in terms of UX/UI, a possible solution might be to switch both axes...
plotOptions: {
bar: {
horizontal: true
}
},
... and give your chart much more height:
chart: {
type: 'bar',
height: 2500,
},
Doing that would allow you to use the natural vertical scrolling of your browser.
let data = [];
for (let i = 1; i <= 150; i++) {
data.push({x: `Category ${i}`, y: i});
}
let options = {
series: [{
name: 'Series',
data
}],
chart: {
type: 'bar',
height: 2500
},
yaxis: {
labels: {
style: {
fontSize: '10px'
},
offsetY: 3
}
},
plotOptions: {
bar: {
horizontal: true
}
},
dataLabels: {
enabled: false
}
};
let chart = new ApexCharts(document.querySelector('#chart'), options);
chart.render();
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<div id="chart"></div>
All categories are visible. This is not very handy, though.
2. Zoom, pan and tick settings
Zooming and panning are useful features. They are available by default in the toolbar, but this toolbar does not appear immediately when your xaxis has categories. To enable the toolbar in this case, you have to change xaxis.tickPlacement from 'between' to 'on' (see Zoom on Category Bar Charts – ApexCharts.js).
Since you have a lot of categories, it is also a good idea to limit the number of visible labels with xaxis.tickAmount.
xaxis: {
tickPlacement: 'on',
tickAmount: 25
},
Thanks to the zoomX() method, you can decide to display your chart with only a subset of your data. The rest is still accessible via zooming and/or panning.
let data = [];
for (let i = 1; i <= 150; i++) {
data.push({x: `Category ${i}`, y: i});
}
let options = {
series: [{
name: 'Series',
data
}],
chart: {
type: 'bar',
height: 350
},
xaxis: {
tickPlacement: 'on',
tickAmount: 25
},
dataLabels: {
enabled: false
}
};
let chart = new ApexCharts(document.querySelector('#chart'), options);
chart.render();
chart.zoomX(37, 71);
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<div id="chart"></div>
I am trying to make a function which will be building Highcharts charts dynamically based on parameters passed. I do it the following way:
function makeChart(name, title, series)
{
var options = {
chart: {
type: 'areaspline',
renderTo: name
},
credits: { enabled: false },
legend: { enabled: true },
title: {
text: title
},
xAxis: {
type: 'datetime'
},
yAxis: {
gridLineDashStyle: 'dot',
title: {
text: 'Quantity'
}
},
plotOptions: {
areaspline: {
animation: false,
stacking: '',
lineWidth: 1,
marker: { enabled: false }
}
},
series: [] //chart does not display except title. It will draw if I paste the data here manually
};
this.chart = new Highcharts.Chart(options);
for (index = 0; index < series.length; ++index) {
options.series[index] = {'name':series[index][0], 'data':series[index][1], 'color':series[index][2], 'fillOpacity': .3};
}
}
makeChart('container2', 'second chart', [['thisisname1', [20,21,22,23,24,25,26,27,28], '#d8d8d8']]);//calling function with test parameters
But everything I can see is the charts title. I guess the problem is in adding data to series array. I tried to add it with several ways but it did not work, although I see that the data has been added if I console.log(options.series). Any ideas how to fix that? Thank you.
Place this.chart = new Highcharts.Chart(options); after the for loop.
You're adding the data after the chart has been initialized, for it to work this way you need to tell HighCharts to redraw itself, easier option is to init after the loop. :)
New to highcharts and as the title said I am trying to pull json from a webservice and place it into the chart (bar chart) but I am getting some weird behavior. after I pull the data down through $http.get() I try and set the series to that string of json like series: '$scope.jsondata'. It will fill some legends (more than expected) so it is getting the data. but the bars on the chart wont show.
On the other hand when I go to the url where I am getting the json and just copy and paste all of the json into the series field, it works perfectly.
I have a plunker here I have been working on that shows what I am talking about. You can just paste:
[
{
"name":"Kaia",
"data":[19]
},
{
"name":"Deborah",
"data":[86]
},
{
"name":"Phoebe",
"data":[77]
},
{
"name":"Rory",
"data":[17]
},
{
"name":"Savannah",
"data":[15]
}
]
...into the series field and everything works.
EDIT I havent yet, but I am planning to use $interval to update the data every x seconds. Something like :
$http.get(fullUrl).success(function(data2) {
$scope.records = [];
data2.forEach(function(r) {
$scope.records.push(r);
});
});
mainInterval = $interval(function() {
$http.get(fullUrl).success(function(data2) {
$scope.records = [];
data2.forEach(function(r) {
$scope.records.push(r);
});
});
}, 5000);
So like one of the answers suggested I put the chart creation in the callback of the $http.get() but I think that'd hinder the $interval
You can move the creation of the Chart into the callback of the get call to simplify things. http://plnkr.co/edit/utQG34xOQmtbOukTK71e?p=preview
Note I also updated series: '$scope.jsondata' to series: $scope.jsondata.
$http.get('https://api.myjson.com/bins/38qm9').success(function(ret) {
$scope.jsondata = ret;
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'bar'
},
title: {
text: 'Active Users'
},
xAxis: {
categories: ['user']
},
yAxis: {
min: 0,
title: {
text: 'Total Score',
align: 'high'
},
labels: {
overflow: 'justify'
}
},
plotOptions: {
bar: {
dataLabels: {
enabled: true
}
}
},
legend: {
layout: 'horizontal',
align: 'center',
verticalAlign: 'top',
x: -40,
y: 100,
floating: false,
backgroundColor: ((Highcharts.theme && Highcharts.theme.legendBackgroundColor) || '#FFFFFF'),
shadow: false
},
credits: {
enabled: false
},
series: $scope.jsondata
});
console.debug($scope.jsondata);
});
I have a basic pie chart in ExtJS 5. The issue I am having is that the chart renders with a static JsonStore but won't render properly with a remote data.store?
Here is my code:
View (Chart)
Ext.define('APP.view.core.graphs.Countytotals', {
extend: 'Ext.Panel',
alias: 'widget.countytotalchart',
id: 'countyTotalsGraph',
width: 650,
initComponent: function() {
var me = this;
// Doesn't work?
var countyStore = Ext.create('APP.store.Countytotalsgraph');
// Works
var store = Ext.create('Ext.data.JsonStore', {
fields: ['COUNTY', 'AMOUNT'],
data: [{
'COUNTY': 'London',
'AMOUNT': 10.92
}, {
'COUNTY': 'Lancashire',
'AMOUNT': 6.61
}, {
'COUNTY': 'Kent',
'AMOUNT': 5.26
}, {
'COUNTY': 'West Yorkshire',
'AMOUNT': 4.52
}, {
'COUNTY': 'Nottinghamshire',
'AMOUNT': 4.01
}, {
'COUNTY': 'Other',
'AMOUNT': 68.68
}]
});
var chart = new Ext.chart.PolarChart({
width: '100%',
height: 500,
insetPadding: 50,
innerPadding: 20,
legend: {
docked: 'bottom'
},
listeners: {
afterrender: function (chart) {
if (chart.isVisible()) {
countyStore.load();
chart.redraw();
}
}
},
interactions: ['itemhighlight'],
store: countyStore,
series: [{
type: 'pie',
angleField: 'AMOUNT',
label: {
field: 'COUNTY',
display: 'outside',
calloutLine: {
length: 60,
width: 3
// specifying 'color' is also possible here
}
},
highlight: true,
tooltip: {
trackMouse: true,
renderer: function(storeItem, item) {
this.setHtml(storeItem.get('COUNTY') + ': ' + storeItem.get('AMOUNT') + '%');
}
}
}]
});
me.items = [chart];
this.callParent();
}
});
Store
Ext.define('APP.store.Countytotalsgraph', {
extend: 'Ext.data.Store',
model: 'APP.model.Countytotalsgraph',
autoLoad: false,
storeId: 'countyTotalsGraphStore',
proxy: {
type: 'ajax',
url : '/dashboard/countytotals',
method : 'POST',
reader: {
type: 'json',
rootProperty: 'data'
}
},
listeners: {
beforeload: function(store, eOpts) {
//if ( this.data.items.length ) {
//Ext.getCmp('optionsGrid').getView().refresh();
//}
store.proxy.extraParams = {
percentage: 'true'
}
}
}
});
Model
Ext.define('APP.model.Countytotalsgraph', {
extend: 'Ext.data.Model',
fields: ['COUNTY', 'AMOUNT']
});
This is how is renders with the static store:
This is how it renders with the remote store:
I am on the latest version of the GPL although the charts were built using Sencha CMD and the "sencha ant build" command in the sencha-charts directory.
Why does the static store display it (well still there is still an issue regarding the legend at the bottom) but the remote json not?
Iv'e tried to load the store after it the chart is rendered and is visible as I have seen a previous post regarding holding off on loading the store to give the chart time to render but this did not work:
listeners: {
afterrender: function (chart) {
if (chart.isVisible()) {
countyStore.load();
chart.redraw();
}
}
},
Thanks in advance :)
Nathan
Probably a bug in Ext.
The chart colors are set in Ext.chart.AbstractChart#updateColors. This is a "config" method, that is called automatically when setColors is called, and also from the constructor, when the config is initialized.
In your case, it is only called at construction time, before the remote store has been loaded; and it happens that polar series need to know the number of records in the store in order to know how many colors it must used (unlike other kind of charts that rely on number of axis or so).
Here's the code of that method:
updateColors: function (newColors) {
var me = this,
colors = newColors || (me.themeAttrs && me.themeAttrs.colors),
colorIndex = 0, colorCount = colors.length, i,
series = me.getSeries(),
seriesCount = series && series.length,
seriesItem, seriesColors, seriesColorCount;
if (colorCount) {
for (i = 0; i < seriesCount; i++) {
seriesItem = series[i];
// Ext.chart.series.Polar#themeColorCount uses store.getCount()
// so seriesColorCount will be 0
seriesColorCount = seriesItem.themeColorCount();
// ... hence seriesColor will be an empty array
seriesColors = me.circularCopyArray(colors, colorIndex, seriesColorCount);
colorIndex += seriesColorCount;
seriesItem.updateChartColors(seriesColors);
}
}
me.refreshLegendStore();
}
You could probably get it working by creating the chart after the load event of the store, but that's kind of kinky given your usage is as intended, and the bug will probably get smashed in a coming release.
For now, a possible fix is to override the onRefresh of the chart, that is called, well, when the store is refreshed, and force colors to be updated at this time:
Ext.define(null, {
override: 'Ext.chart.PolarChart'
,onRefresh: function() {
this.callParent(arguments);
var colors = this.getColors();
if (colors) {
this.updateColors(colors);
}
}
});