I am trying to load geojson data, which I hard coded as variable called sample. Now I want to display a chart after clicking on each feature. Below is my code. But it gives the ErrorMessage: feature is undefined.
var map = L.map('map').setView([55, 3], 5);
L.tileLayer( 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap',
subdomains: ['a','b','c']
}).addTo( map );
var trees = L.geoJson(Sample).addTo(map);
trees.on('click', function ( evt) {
feature = evt.layer.feature;
$("#chart").empty();
var chart = c3.generate({
data: {
names: {
data1: 'a',
data2: 'b',
data3: 'c',
data4: 'd',
data5: 'e'
},
// just taken some RANDOM fields to demonstrate
// how to draw the chart
columns: [
['data1',
feature.properties.a],
['data2',
feature.properties.b],
['data3',
feature.properties.c],
['data4',
feature.properties.d],
['data5',
feature.properties.e]
],
types: {
data1: 'bar',
data2: 'bar',
data3: 'bar',
data4: 'bar',
data5: 'bar'
}
},
axis: {
rotated: false,
x: {
label: {
text: 'Your Topics',
position: 'outer-middle'
}
},
y: {
label: {
text: 'Your_Values',
position: 'outer-center'
}
}
}
});
});
The event layer in the trees click handler doesn't have features. You should add the click handler to each layer:
var trees = L.geoJson(Sample, {
onEachFeature: function onEachFeature(feature, layer) {
layer.on('clicked feature', function(evt) {
console.log('feature=', feature);
$("#chart").empty();
// generate chart here using feature
// var chart = c3.generate({...});
});
}
}).addTo(map);
Related
the end goal is being able to zoom into an e-chart on the chart itself, without the 'datazoom' mini chart
(and/or being able to extract the datazoom mini chart and use that on it's own as a line chart would be amazing!)
meanwhile, i want to click on the chart (not just on the line) and get the x-coordinate.
I can get the Y-coordinate; but not the x.
even just how to convert the offsetX into which data point is nearest would be wonderful.
the triggerEvent on the axes means that if i click on the axis itself, it gets the data; but not on the grid :(
var dom = document.getElementById('chart-container');
var myChart = echarts.init(dom, null, {
renderer: 'canvas',
useDirtyRect: false
});
var app = {};
var option;
option = {
xAxis: {
type: 'category',
data: [0, 5, 10, 12, 15, 16, 20],
triggerEvent: true,
},
yAxis: {
type: 'value',
triggerEvent: true,
},
series: [
{
data: [820, 932, 901, 934, 1290, 1330, 1320],
type: 'line',
smooth: true
}
]
};
if (option && typeof option === 'object') {
myChart.setOption(option);
}
myChart.on('click', 'xAxis.category', function (params) {
console.log('x axis....got params....', params)
});
myChart.on('click', 'yAxis', function(params){
console.log('Y axis', params);
})
myChart.on('click', function(params){
console.log('i clicked on the actual line: ', params);
)
var zr = myChart.getZr();
// listens for clicking on the grid:
// (blank area where the grid is, but no line is drawn)
zr.on('click', function (params) {
var pointInPixel = [params.offsetX, params.offsetY];
var pointInGrid = myChart.convertFromPixel('grid', pointInPixel);
console.log('clicked on:', pointInGrid);
// this is not the graph/data that i want :(
// how to get this to the x data value? (ie, 5, or 10, or 12?)
});
window.addEventListener('resize', myChart.resize);
pen here:
https://codepen.io/jrenee42/pen/ExENXOq
I'm attempting to integrate ZingChart as a custom component type in GrapesJs. I've followed some examples and have implemented the following plugin.
blocks.js
import { lineChartRef, chartType } from './consts';
export default (editor, opt = {}) => {
const c = opt;
const bm = editor.BlockManager;
if (c.blocks.indexOf(lineChartRef) >= 0) {
bm.add(lineChartRef, {
label: c.labelLineChart,
content: `
<div data-gjs-type="${chartType}" id="myChart"></div>
`
});
}
};
components.js
import { chartType } from './consts';
export default (editor, opt = {}) => {
const domc = editor.DomComponents;
const defaultType = domc.getType('default');
const defaultModel = defaultType.model;
domc.addType(chartType, {
model: defaultModel.extend(
{
defaults: {
...defaultModel.prototype.defaults,
script: function() {
if (typeof zingchart == 'undefined') {
var script = document.createElement('script');
script.src =
'https://cdn.zingchart.com/zingchart.min.js';
document.body.appendChild(script);
}
}
}
},
{
isComponent: el => {
if (
el.getAttribute &&
el.getAttribute('data-gjs-type') === chartType
) {
return {
type: chartType
};
}
}
}
),
view: {
onRender() {
renderZingChart.bind(this)();
}
}
});
function renderZingChart() {
const data = {
type: 'bar',
title: {
text: 'Data Basics',
fontSize: 24
},
legend: {
draggable: true
},
scaleX: {
// Set scale label
label: { text: 'Days' },
// Convert text on scale indices
labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
scaleY: {
label: { text: 'Temperature (°F)' }
},
plot: {
animation: {
effect: 'ANIMATION_EXPAND_BOTTOM',
method: 'ANIMATION_STRONG_EASE_OUT',
sequence: 'ANIMATION_BY_NODE',
speed: 275
}
},
series: [
{
// plot 1 values, linear data
values: [23, 20, 27, 29, 25, 17, 15],
text: 'Week 1'
},
{
// plot 2 values, linear data
values: [35, 42, 33, 49, 35, 47, 35],
text: 'Week 2'
},
{
// plot 2 values, linear data
values: [15, 22, 13, 33, 44, 27, 31],
text: 'Week 3'
}
]
};
const chart = {
id: 'myChart',
data
};
zingchart.render(chart);
}
};
index.js
import grapesjs from 'grapesjs';
import loadBlocks from './blocks';
import loadComponents from './components';
import { lineChartRef } from './consts';
export default grapesjs.plugins.add('fndy-charts', (editor, opts = {}) => {
let c = opts;
let defaults = {
blocks: [lineChartRef],
defaultStyle: 1,
labelLineChart: 'Line Chart'
};
// Load defaults
for (let name in defaults) {
if (!(name in c)) c[name] = defaults[name];
}
loadBlocks(editor, c);
loadComponents(editor, c);
});
consts.js
export const lineChartRef = 'line-chart';
export const chartType = 'chart';
When I add the block to the canvas, it renders, but the ZingChart inside does not. Some things I've tried already:
Verify that the ZingChart render function is being called.
Try moving the renderZingChart function call to different component hooks. Specifically, component:mount, view.init(), and view.onRender().
Move the renderZingChart function call to the script function as a script.onload callback. A similar example can be found here: https://grapesjs.com/docs/modules/Components-js.html#basic-scripts. This does render the ZingChart correctly but doesn't feel correct, and does not allow me to pass in parameters since the script function runs outside the scope of GrapesJs.
I'm running out of ideas so any guidance would be great! Thanks!
I'm making a chart component library with echarts, and the approach for rendering the chart would be similar. The only missing thing I see is element's id. It is an attribute that zing uses to render the chart.
I've made a small example which is obviously not production ready because the id of the block is static. This solves specifically the render problem to make the id dynamic you can do it listening to component:add event and add model id as attribute.
const plugin = editor => {
const {
BlockManager: bm
} = editor;
bm.add("mychart", {
label: "Chart",
content: {
tagName: "div",
attributes: {
id: 'myChart'
},
style: {
width: "300px",
height: "300px"
},
script: function() {
const init = () => {
const data = {
type: "bar",
title: {
text: "Data Basics",
fontSize: 24
},
legend: {
draggable: true
},
scaleX: {
// Set scale label
label: {
text: "Days"
},
// Convert text on scale indices
labels: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
},
scaleY: {
label: {
text: "Temperature (°F)"
}
},
plot: {
animation: {
effect: "ANIMATION_EXPAND_BOTTOM",
method: "ANIMATION_STRONG_EASE_OUT",
sequence: "ANIMATION_BY_NODE",
speed: 275
}
},
series: [{
// plot 1 values, linear data
values: [23, 20, 27, 29, 25, 17, 15],
text: "Week 1"
},
{
// plot 2 values, linear data
values: [35, 42, 33, 49, 35, 47, 35],
text: "Week 2"
},
{
// plot 2 values, linear data
values: [15, 22, 13, 33, 44, 27, 31],
text: "Week 3"
}
]
};
const chart = {
id: this.id,
data
};
zingchart.render(chart);
};
if (typeof zingchart == "undefined") {
var script = document.createElement("script");
script.onload = init;
script.src = "https://cdn.zingchart.com/zingchart.min.js";
document.body.appendChild(script);
} else {
init();
}
}
}
});
};
const editor = grapesjs.init({
container: "#gjs",
fromElement: true,
height: "100vh",
width: "auto",
storageManager: false,
panels: {
defaults: []
},
plugins: ["gjs-preset-webpage", plugin]
});
You can give a check here the chart is rendering.
Codepen
Hope that's enough, cheers!
I don't think you need to write very complicated code for using Zing charts.I will add a small sample code for making a chart block element , So when you drag and drop the block element then it will make the chart a part of the gjs div of grapesjs .I am using Highcharts.
editor.BlockManager.add('Blockhighcharts', {
label: 'Highchart',
category: 'CHART',
attributes: { class:'gjs-fonts gjs-f-b1' },
content: {
script: function () {
var container = "container"+Math.floor(Math.random() * 100);
$(this).attr("id",container);
$('#gridly_div').append($(this));
var myChart = Highcharts.chart(container, {
chart: {
type: 'bar',
},
title: {
text: 'Fruit Consumption'
},
xAxis: {
categories: ['Apples', 'Bananas', 'Oranges']
},
yAxis: {
title: {
text: 'Fruit eaten'
}
},
series: [{
name: 'Jane',
data: [1, 0, 4]
}, {
name: 'John',
data: [5, 7, 3]
}]
});
The HTML code where the chart will be displayed is as follows.
<div id="gjs" style="height:0px; overflow:hidden;">
<style>
#gjs{
height: 100%;
width: 100%;
margin: 0;
}
</style>
<div id='gridly_div' class="gridly">
</div>
For example:
var chart = c3.generate({
data: {
x : 'x',
columns: [
['x', 'www.site1.com11111111111111111111111111111111111111111111111111111', 'www.site2.com11111111111111111111111111111111111111111111111111111111', 'www.site3.com11111111111111111111111111111111111111111111111111111111111111', 'www.site4.com11111111111111111111111111111111111111111111111111111111111111111111111111'],
['download', 30, 200, 100, 400],
['loading', 90, 100, 140, 200],
],
groups: [
['download', 'loading']
],
type: 'bar'
},
axis: {
x: {
type: 'category', // this needed to load string x value
tick: {
rotate: 25
}
}
}
})
;
and it looks like
How can I hide the long title while keeping the ability for the user to see the full name (maybe when hovering the mouse). Or maybe better way?
You can change the text with the tick.format configuration, but actually getting the value of the text because these are category values is a bit of a PITA, see the solution below:
the tick.format function shortens the axes label text (and this is carried over into the bar chart tooltip too)
the .onrendered function adds title elements to the axes labels that show the full axes label as a basic tooltip when you mouseover them
var chart = c3.generate({
data: {
x : 'x',
columns: [
['x', 'www.site1.com11111111111111111111111111111111111111111111111111111', 'www.site2.com11111111111111111111111111111111111111111111111111111111', 'www.site3.com11111111111111111111111111111111111111111111111111111111111111', 'www.site4.com11111111111111111111111111111111111111111111111111111111111111111111111111'],
['download', 30, 200, 100, 400],
['loading', 90, 100, 140, 200],
],
groups: [
['download', 'loading']
],
type: 'bar'
},
axis: {
x: {
type: 'category', // this needed to load string x value
tick: {
rotate: 25,
format: function (d) {
var catName = this.api.categories()[d];
if (catName.length > 20) {
catName = catName.slice(0,20)+"…";
}
return catName;
}
},
}
},
onrendered: function () {
var self = this;
d3.select(this.config.bindto)
.selectAll(".c3-axis-x .tick text")
.each(function (d) {
var title = d3.select(this).select("title");
if (title.empty()) {
title = d3.select(this).append("title");
}
title.text (self.api.categories()[d]);
})
;
}
});
http://jsfiddle.net/ajh0q2e7/
I was under the assumption the "Play with this data!" link was supposed the show up by default. Any ideas on why it may not appear? I am just working with a basic scatter plot.
Note that this code below is not standalone as is, it is just the excerpt that does the plotly work.
var xData = [];
var yData = [];
var h = results;
for(var k in h) {
var localdate = k;
var plotdate = moment(localdate).format('YYYY-MM-DD HH:mm:ss');
xData.push(plotdate);
if (currentPort === "t") {
yData.push(CtoF(h[k]));
} else {
yData.push(h[k]);
};
}
var plotdata = [
{
x: xData,
y: yData,
type: 'scatter',
mode: 'markers+lines',
line: {
'color': HELIUM_BLUE
},
marker: {
'symbol': 'circle',
'color': HELIUM_PINK,
'maxdisplayed': 50
}
}
];
var layout = {
title: currentData,
xaxis: {
'title': 'Date / Time'
},
yaxis: {
'title': title
}
};
Plotly.newPlot(plotHolder, plotdata, layout);
You would need to add {showLink: true} as the fourth argument (after layout). I guess the default value changed from true to false.
If you want to change the caption of the button, use {showLink: true, "linkText": "Play with this data"}
var xData = [1, 2, 3, 4, 5];
var yData = [10, 1, 25, 12, 9];
var plotdata = [
{
x: xData,
y: yData,
type: 'scatter',
mode: 'markers+lines',
}
];
var layout = {
title: 'Edit me',
xaxis: {
'title': 'x'
},
yaxis: {
'title': 'y'
}
};
Plotly.newPlot(plotHolder, plotdata, layout, {showLink: true, "linkText": "Play with this data"});
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id='plotHolder'>
</div>
I want to create a combination chart (line and bar) for same json data so that the line touches the all the bars since datapoints are same.
Here is the code
var graphdata=[
{ 'indicator': 'X', 'total': 100 },
{ 'indicator': 'Y', 'total': 200 },
{ 'indicator': 'Z', 'total': 300 }
];
var g1=[
{ 'indicator': 'X', 'total': 150 },
{ 'indicator': 'Y', 'total': 220 },
{ 'indicator': 'Z', 'total': 330 }
];
setTimeout(function () {
chart.load({
data: {
type: 'line',
json: g1,
keys: {
x: 'indicator',
value: ['total']
},
},
axis: {
x: {
type: 'category'
}
},
});
}, 1000);
var chart = c3.generate({
data: {
type: 'bar',
json: graphdata,
keys: {
x: 'indicator',
value: ['total']
},
},
axis: {
x: {
type: 'category'
}
},
bar: {
width: {
ratio: 0.5
}
}
});
The output of this is only bar chart,the line chart is not loading.
try this code
var data = [
{ 'date': '2015-01-01', 'Dept': null, 'SMV': 3},
{ 'date': '2015-01-02', 'Dept': 1, 'SMV': 4}
];
Example You separated all the date, the Dept and the SMV data into separate arrays. The way to go here is the following: The data should contain one array of several arrays. The first argument is defined as the key of the dataset. An example dataset looks then like this:
var data = [
['date', '2015-01-01', 2015-01-02'],
['Dept', null, 1],
['SMV', 3, 4]
];
Try the simple code below, you can use a simple JSON file as shown below.
var graphdata={data1:[100,200,300],data2:[150,220,330]};
var chart = c3.generate({
data: {
types: {data1:'spline',
data2:'bar'
},
json: graphdata,
},
bar: {
width: {
ratio: 0.5
}
}
});
For more details you can try http://c3js.org/samples/chart_combination.html .