I am trying to draw a very basic line chart using c3.js in react. But the the chart output appears with dark areas around the lines, which I assume is not a feature of the graph, because I used another graph library and the dark areas persisted. Anyone knows what the source of error can be?
Here is a picture of how the chart looks like:
Here is the code:
import React from "react";
import * as c3 from 'c3'
class Hello extends React.Component {
drawGraph = () =>
{
var chart = c3.generate({
bindto: this.refs.chart,
data: {
xs: {
'data1': 'x1',
'data2': 'x2',
},
columns: [
['x1', 10, 30, 45, 50, 70, 100],
['x2', 30, 50, 75, 100, 120],
['data1', 30, 200, 100, 400, 150, 250],
['data2', 20, 180, 240, 100, 190]
]
}
});
}
render() {
return (
<div>
<br/>
<div id='chart' ref={'chart'} style={{width: '100%', height: '100%'}}><button onClick={this.drawGraph}>draw</button></div>
</div>
);
}
}
export default Hello;
If the package was installed using npm (i.e. npm install c3 or yarn add c3), it's necessary import the styles from .css files: Inside the main component, add the line
import "c3/c3.min.css";
Apparently the problem can be solved just by adding a single line of code in the beginning:
import "../../node_modules/c3/c3.css";
If you come across here as I did from top results of google search, you will be probably surprised why both of other solutions don't work.
In Vue 3 Cli there is issue with .css file loader not working properly, but you can circumvent this if you add to your main.js file, following line:
require('c3/c3.css');// C3 chart styles
This will enable you to use c3 in rest of your project, with importing c3 in components like so:
<template>
<div id="testChart"></div>
</template>
<script>
var c3 = require('c3');
export default {
async mounted() {
c3.generate({
bindto: "#testChart",
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25]
]
}
});
}
};
</script>
Related
I'm trying to switch from a ResponsiveLine to a ResponsiveLineCanvas using Javascript library Nivo version 0.80.0 and React 18.2.0, but markers are just not shown.
Not sure what I am missing, so I created an example to reproduce the issue
https://codesandbox.io/embed/fast-leftpad-q6ypqr?fontsize=14&hidenavigation=1&theme=dark
It is sufficient to switch from ResponsiveLineCanvas to ResponsiveLine and the marker get shown.
From the docs I cannot guess if the feature is unsupported in ResponsiveLineCanvas. So, am I missing any configuration?
import React, { useEffect, useState } from "react";
import { ResponsiveLineCanvas } from "#nivo/line";
import { ResponsiveLine } from "#nivo/line";
const commonProperties = {
width: 900,
height: 400,
margin: { top: 20, right: 20, bottom: 60, left: 80 },
animate: true,
enableSlices: "x"
};
const App = () => (
<div style={{ height: 600 }}>
<ResponsiveLineCanvas
{...commonProperties}
data={[
{
id: "Id of serie",
data: [
{ x: 0, y: 0.2 },
{ x: 1, y: 0.3 },
{ x: 2, y: 0.5 },
{ x: 3, y: 0.4 },
{ x: 4, y: 0.3 },
{ x: 5, y: 0.5 },
{ x: 6, y: 0.3 },
{ x: 7, y: 0.1 }
]
}
]}
markers={[
{
axis: "x",
value: 2,
lineStyle: { stroke: "#6aa84f", strokeWidth: 3, opacity: 0.95 },
legend: "Budget line"
}
]}
layers={[
"grid",
"axes",
"areas",
"lines",
"points",
"slices",
"mesh",
"legends",
"markers"
]}
enableGridX={false}
colors={["rgb(97, 205, 187)", "rgb(244, 117, 96)"]}
xScale={{
type: "linear"
}}
yScale={{
type: "linear",
stacked: false,
min: 0,
max: 1
}}
enableArea={true}
areaOpacity={1}
enableSlices={false}
useMesh={true}
crosshairType="cross"
/>
</div>
);
export default App;
Looking at the source code, it's clear that support for markers has not been implemented in the LineCanvas and ResponsiveLineCanvas components. There is no mention of markers anywhere in the component source. The markers prop is not included in the destructuring assignment so that prop will be ignored and have no effect.
As for the layers prop, this Canvas version goes through a bunch of if statements to check for known layer types. "marker" is not one of these types. There is no else statement that lets you know if a provided layer was invalid, it just doesn't do anything.
The supported values of the layers prop, per the source code, are:
"grid"
"axes"
"areas"
"lines"
"points"
"mesh"
"legends"
custom functions
On the other hand, the SVG-based Line and ResponsiveLine components do use the markers prop and support layers=["markers"]. You can see here how the markers prop is passed off to a CartesianMarkers component from the #nivo/core package and the resulting element is stored in the layerById dictionary.
I am using the same example line chart shown here. However, I have black fill under the lines on my chart. How do I remove the black fill from under the lines. In the documentation under LineChartOptions there it only shows two configurable options, HidePoints and LinePoint. Here is my example. The same thing happens to my time series chart. Thank you.
var lineChart = bb.generate({
data: {
columns: [
["data1", 30, 200, 100, 400, 150, 250],
["data2", 50, 20, 10, 40, 15, 25]
],
type: "line", // for ESM specify as: line()
},
bindto: "#lineChart"
});
Adding fill: none to the bb-chart-lines class should do the trick.
Add this to your CSS:
.bb-chart-lines {
fill: none;
}
Link to Codepen
I am using Angular and Higcharts to visualize some data. I have gotten many of the other Highchart components working, now I want to use the gauges. I went to the Highcharts website and used the example at their demo section. Unfortunately this is not working.
For some reason the gauge is blank but the other parts of my component shows up. Example below:
My code looks like this:
TS file
import { Component, OnInit } from '#angular/core';
import * as Highcharts from 'highcharts';
#Component({
selector: 'app-speedo',
templateUrl: './speedo.component.html',
styleUrls: ['./speedo.component.scss']
})
export class SpeedoComponent implements OnInit {
chartOptions: any;
Highcharts: typeof Highcharts = Highcharts;
chartRef: Highcharts.Chart;
updateFromInput = false;
constructor() { }
ngOnInit(): void {
this.myChart();
}
chartCallback: Highcharts.ChartCallbackFunction = (chart) => {
this.chartRef = chart;
};
myChart(){
this.chartOptions = {
chart: {
type: 'solidgauge'
},
title: null,
pane: {
center: ['50%', '85%'],
size: '140%',
startAngle: -90,
endAngle: 90,
background: {
backgroundColor:
Highcharts.defaultOptions.legend.backgroundColor || '#EEE',
innerRadius: '60%',
outerRadius: '100%',
shape: 'arc'
}
},
exporting: {
enabled: false
},
tooltip: {
enabled: false
},
// the value axis
yAxis: {
stops: [
[0.1, '#55BF3B'], // green
[0.5, '#DDDF0D'], // yellow
[0.9, '#DF5353'] // red
],
lineWidth: 0,
tickWidth: 0,
minorTickInterval: null,
tickAmount: 2,
title: {
y: -70
},
labels: {
y: 16
}
},
plotOptions: {
solidgauge: {
dataLabels: {
y: 5,
borderWidth: 0,
useHTML: true
}
}
}
}
setTimeout(() => {
window.dispatchEvent(
new Event('resize')
);
}, 300);
}
}
HTML file
<p>speedo works!</p>
<highcharts-chart
[Highcharts]="Highcharts"
[options]="chartOptions"
style="width: 100%; height: 400px; display: block;"
[(update)]="updateFromInput"
[callbackFunction]="chartCallback">
</highcharts-chart>
Does anyone know what is wrong with this code. How can I fix it so that the gauge actually shows up?
If anyone can recommend any other package I can use to show real time data on a gauge I would appreciate it. This package should be easy to use, or at least have more resources than Highcharts where one can find tutorials an so on.
Thanks in advance!
There are a few glitches:
The highcharts-more module is missing. Import it at the begging
import HC_more from "highcharts/highcharts-more";
HC_more(Highcharts);
Your demo was not working simply because there was nothing to show.
All you have to do to fix this is to set the data in the series object.
Remember to always add the series type for each series.
series: [
{
type: "gauge",
data: [80]
}
]
Also, I highly recommend Highhcarts official documentation where you might find more examples and descriptions.
API:
https://api.highcharts.com/highcharts/series.gauge
https://github.com/highcharts/highcharts-angular
Demo:
https://stackblitz.com/edit/highcharts-angular-gauge
I'm trying to write a custom bar chart directive in angular js using ES6. I have installed the c3 library using bower install c3 --save. when I run gulp serve I'm getting the error "c3" is not defined no-undef. Below is my code -
export class MyDirective {
constructor($interval) {
'ngInject';
this.template = '<div id=chart></div>';
this.restrict = 'E';
this.scope = {}
this.$interval = $interval;
}
compile(tElement) {
tElement.css('position', 'absolute');
}
link(scope, element) {
this.$interval(() => this.chart(), 1000);
}
chart() {
c3.generate({
bindto: '#chart',
data:{
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 130, 100, 140, 200, 150, 50]
],
type: 'bar'
},
bar: {
width: {
ratio: 0.5 // this makes bar width 50% of length between ticks
}
// or
//width: 100 // this makes bar width 100px
}
});
}
}
If you install c3 directly, it will not be "angular friendly". I use c3 in my project with es2015 (and a babel transpire) and I choose to use c3-angular
To install it:
bower install c3-angular --save
And to import it as a dependency :
import 'c3-angular';
let barChartModule = angular.module('barChart', ['gridshore.c3js.chart']);
If you do this, you can define charts in your view this it is explained in the examples here
I'm creating a AngularJS directive that is supposed to have a C3.js-based chart in it. Problem is that the C3 library does not see the DOM element it's supposed to attach to. The directive's link function looks something like this:
link: function(scope, element, attrs) {
scope.someid = 'id';
scope.chart = c3.generate({
bindto: "#somechart"+scope.someid,
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25]
]
}
});
console.log($("#somechart"+scope.someid).size()); // this is a test, outputs 0
}
The template for the directive has this in it:
<div id="#somechart{{ scope.someid }}">...</div>
The problem is that the c3.generate()'s bindto does not see the #somechartid. The console.log() I've put in outputs 0 which means the element is not present in the DOM at the moment when the link function is called.
If I call the same chart-generating code from the browser's console or even from some ng-click the chart gets rendered.
Is there a way to overcome this problem without using a solution like $timeout?
UPDATE 2014-07-15 15:33 Changed the code sample and added relevant line from directive's template.
Use $timeout function in your link function if you want to manipulate dom, which is not yet generated. See this
Have you tried something like this
link: function(scope, element, attrs) {
scope.chart = c3.generate({
bindto: element[0],
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25]
]
}
});
}
Maybe usage of element.find('#id') will help:
link: function(scope, element, attrs) {
var item = element.find('#somechartid');
scope.chart = c3.generate({
bindto: item,
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25]
]
}
});
}