Error "Tried calling: call()" while loading page with Linechart - firebase

In my application I am trying to use the following code to display a Linechart with a a selector below for the displayed data.
class _SearchResultState extends State<SearchResult> {
dynamic data_snap;
bool _loading = false;
Future<dynamic> getData() async{
final DocumentReference document = FirebaseFirestore.instance.collection("Animals").doc(widget.data);
_loading = true;
await document.get().then<dynamic>(( DocumentSnapshot snapshot) async{
setState(() {
data_snap =snapshot.data;
_loading = false;
});
});
}
Map<int, LineChartData> selection;
int _selected = 2;
bool showAvg = false;
#override
void initState(){
selection = {0: oneWeek(), 1: oneMonth(), 2: oneYear()};
super.initState();
getData();
}
#override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
SizeConfig().init(context);
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
iconTheme: IconThemeData(color: Colors.lightGreen),
backgroundColor: Colors.grey[100],
title: const Text('Details', style:
TextStyle(color: Colors.lightGreen)),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [ _loading ? CircularProgressIndicator():
Container(
height: SizeConfig.safeBlockHorizontal * 150,
child: Card(
color: Theme.of(context).cardColor,
child: Padding(
padding: const EdgeInsets.only(
top: 5.0,
bottom: 5.0,
left: 5.0,
right: 5.0
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Row(
children: _loading ? CircularProgressIndicator(): [
Text(data_snap()['Name'],
style: new TextStyle(
fontSize: SizeConfig.blockSizeHorizontal * 5,
fontWeight: FontWeight.bold))
],
),
Row(
children: [ _loading ? CircularProgressIndicator():
new Container(
width: SizeConfig.safeBlockHorizontal * 90,
height: SizeConfig.safeBlockHorizontal * 38,
alignment: Alignment.center,
child: LineChart(
selection[_selected],
),
),],),
Row(
children: [ _loading ? CircularProgressIndicator():
new Container(
width: SizeConfig.safeBlockHorizontal * 90,
height: SizeConfig.safeBlockHorizontal * 38,
alignment: Alignment.center,
child:
SizedBox(
width: 300,
height: 34,
child: Row(
children: [
FlatButton(
onPressed: () {
setState(() {
_selected = 2;
});
},
child: Text('Week',
style: TextStyle(
fontSize: 12,
color: _selected == 0
? Colors.white.withOpacity(0.5)
: Colors.white))),
FlatButton(
onPressed: () {
setState(() {
_selected = 1;
});
},
child: Text('Month',
style: TextStyle(
fontSize: 12,
color: _selected == 1
? Colors.white.withOpacity(0.5)
: Colors.white))),
FlatButton(
onPressed: () {
setState(() {
_selected = 2;
});
},
child: Text('Year',
style: TextStyle(
fontSize: 12,
color: _selected == 2
? Colors.white.withOpacity(0.5)
: Colors.white))),
],
))
)],),
],
),
),
),
)
]
)
),
);
}
LineChartData oneWeek() {
List<double> listMax2 = List.from(data_snap()['Historie_Inhalt']);
final listMax2reversed = List.from(listMax2.reversed);
final list_one_week2 = listMax2reversed.take(
data_snap()['Historie_Zeitangabe']['1w']);
final list_one_week_list2 = List.from(list_one_week2);
final list_one_week_list_rev2 = List.from(list_one_week_list2.reversed);
List<FlSpot> spots_one_week2 =
list_one_week_list_rev2
.asMap()
.entries
.map((e) {
return FlSpot(e.key.toDouble(), e.value);
}).toList();
return LineChartData(
lineTouchData: LineTouchData(enabled: true),
gridData: FlGridData(
show: false,
drawHorizontalLine: false,
drawVerticalLine: false,
getDrawingVerticalLine: (value) {
return FlLine(
color: Colors.black,
strokeWidth: 1,
);
},
getDrawingHorizontalLine: (value) {
return FlLine(
color: const Color(0xff37434d),
strokeWidth: 1,
);
},
),
lineBarsData: [
LineChartBarData(
spots: spots_one_week2,
isCurved: true,
barWidth: 1,
colors: [
Colors.black87,
],
belowBarData: BarAreaData(
show: true
),
aboveBarData: BarAreaData(
show: true,
colors: [Colors.grey.withOpacity(0.3)]
),
dotData: FlDotData(
show: false,
getDotPainter: (spot, percent, barData, index) =>
FlDotCirclePainter(
radius: 10,
color: Colors.deepOrange.withOpacity(0.5)),
),
),
],
titlesData: FlTitlesData(
bottomTitles: SideTitles(
showTitles: false,
reservedSize: 3,
getTitles: (value) {
switch (value.toInt()) {
case 0:
return '2019';
case 1:
return '2020';
case 2:
return '2021';
case 3:
return '2022';
default:
return '';
}
}),
leftTitles: SideTitles(showTitles: true, margin: 3,
reservedSize: SizeConfig.safeBlockHorizontal * 11
),
rightTitles: SideTitles(showTitles: false),
topTitles: SideTitles(showTitles: false),
));
}
LineChartData oneMonth() {
List<double> listMax2 = List.from(data_snap()['Historie_Inhalt']);
final listMax2reversed = List.from(listMax2.reversed);
final list_one_month2 = listMax2reversed.take(data_snap()['Historie_Zeitangabe']['1m']);
final list_one_month_list2 = List.from(list_one_month2);
final list_one_month_list_rev2 = List.from(list_one_month_list2.reversed);
List<FlSpot> spots_one_month2 =
list_one_month_list_rev2
.asMap()
.entries
.map((e) {
return FlSpot(e.key.toDouble(), e.value);
}).toList();
return LineChartData(
lineTouchData: LineTouchData(enabled: true),
gridData: FlGridData(
show: false,
drawHorizontalLine: false,
drawVerticalLine: false,
getDrawingVerticalLine: (value) {
return FlLine(
color: Colors.black,
strokeWidth: 1,
);
},
getDrawingHorizontalLine: (value) {
return FlLine(
color: const Color(0xff37434d),
strokeWidth: 1,
);
},
),
lineBarsData: [
LineChartBarData(
spots: spots_one_month2,
isCurved: true,
barWidth: 1,
colors: [
Colors.black87,
],
belowBarData: BarAreaData(
show: true
),
aboveBarData: BarAreaData(
show: true,
colors: [Colors.grey.withOpacity(0.3)]
),
dotData: FlDotData(
show: false,
getDotPainter: (spot, percent, barData, index) =>
FlDotCirclePainter(
radius: 10,
color: Colors.deepOrange.withOpacity(0.5)),
),
),
],
titlesData: FlTitlesData(
bottomTitles: SideTitles(
showTitles: false,
reservedSize: 3,
getTitles: (value) {
switch (value.toInt()) {
case 0:
return '2019';
case 1:
return '2020';
case 2:
return '2021';
case 3:
return '2022';
default:
return '';
}
}),
leftTitles: SideTitles(showTitles: true, margin: 3,
reservedSize: SizeConfig.safeBlockHorizontal * 11
),
rightTitles: SideTitles(showTitles: false),
topTitles: SideTitles(showTitles: false),
));
}
LineChartData oneYear() {
List<double> listMax2 = List.from(data_snap()['Historie_Inhalt']);
final listMax2reversed = List.from(listMax2.reversed);
final list_one_year2 = listMax2reversed.take(data_snap()['Historie_Zeitangabe']['1y']);
final list_one_year_list2 = List.from(list_one_year2);
final list_one_year_list_rev2 = List.from(list_one_year_list2.reversed);
List<FlSpot> spots_one_year2 =
list_one_year_list_rev2
.asMap()
.entries
.map((e) {
return FlSpot(e.key.toDouble(), e.value);
}).toList();
return LineChartData(
lineTouchData: LineTouchData(enabled: true),
gridData: FlGridData(
show: false,
drawHorizontalLine: false,
drawVerticalLine: false,
getDrawingVerticalLine: (value) {
return FlLine(
color: Colors.black,
strokeWidth: 1,
);
},
getDrawingHorizontalLine: (value) {
return FlLine(
color: const Color(0xff37434d),
strokeWidth: 1,
);
},
),
lineBarsData: [
LineChartBarData(
spots: spots_one_year2,
isCurved: true,
barWidth: 1,
colors: [
Colors.black87,
],
belowBarData: BarAreaData(
show: true
),
aboveBarData: BarAreaData(
show: true,
colors: [Colors.grey.withOpacity(0.3)]
),
dotData: FlDotData(
show: false,
getDotPainter: (spot, percent, barData, index) =>
FlDotCirclePainter(
radius: 10,
color: Colors.deepOrange.withOpacity(0.5)),
),
),
],
titlesData: FlTitlesData(
bottomTitles: SideTitles(
showTitles: false,
reservedSize: 3,
getTitles: (value) {
switch (value.toInt()) {
case 0:
return '2019';
case 1:
return '2020';
case 2:
return '2021';
case 3:
return '2022';
default:
return '';
}
}),
leftTitles: SideTitles(showTitles: true, margin: 3,
reservedSize: SizeConfig.safeBlockHorizontal * 11
),
rightTitles: SideTitles(showTitles: false),
topTitles: SideTitles(showTitles: false),
));
}
}
I already tried to use a FutureBuilder, but it doesn't work with the selection in initState().
I get the following error in the line "List listMax2 = List.from(data_snap()['Historie_Inhalt']);" of the function LineChartData oneWeek().
The method 'call' was called on null.
Receiver: null
Tried calling: call()
How can I solve this problem?

Try doing this instead:
Map<int, LineChartData> selection = {};
#override
void initState(){
super.initState();
getData().then((_) { //or use whenComplete
setState(() => selection = {0: oneWeek(), 1:oneMonth(), 2: oneYear()});
}
}
And change your Row like this:
Row(
children: [
_loading
? CircularProgressIndicator()
: Container(
width: SizeConfig.safeBlockHorizontal * 90,
height: SizeConfig.safeBlockHorizontal * 38,
alignment: Alignment.center,
child: selection.isNotEmpty && selection.containsKey(_selected)
? LineChart(selection[_selected])
: Container() ,
),],),

Related

How to edit rows in detailslist fluent react UI

I am working with Fluent react UI. I want to edit rows in the table. Is there any option?
https://developer.microsoft.com/en-us/fluentui#/controls/web/detailslist
I recommend FluentUI Editable DetailsList. The following example/library has excellent customization to edit on grid/table. It also have other features like column-based filter, bulk edit, bulk delete, and so on.
GitHub Repo: https://github.com/microsoft/FluentUIEditableDetailsList
Working Example: https://editabledetailslist.azurewebsites.net/
The examples are right forward and easy to use. I am currently using it in my SPFx Webpart project with react. You can install using the npm and use the example on the repository to play around.
Install Package on your project
npm i fluentui-editable-grid
Usage
import { DetailsListLayoutMode, mergeStyles, mergeStyleSets, SelectionMode, TextField } from '#fluentui/react';
import { EditableGrid, EditControlType, IColumnConfig, EventEmitter, EventType, NumberAndDateOperators } from 'fluentui-editable-grid';
import { Fabric } from 'office-ui-fabric-react';
import * as React from 'react';
import { useState } from 'react';
const Consumer = () => {
const classNames = mergeStyleSets({
controlWrapper: {
display: 'flex',
flexWrap: 'wrap',
}
});
const [items, setItems] = useState<any[]>([]);
const columns: IColumnConfig[] = [
{
key: 'id',
name: 'ID',
text: 'ID',
editable: false,
dataType: 'number',
minWidth: 100,
maxWidth: 100,
isResizable: true,
includeColumnInExport: true,
includeColumnInSearch: true,
applyColumnFilter: true,
disableSort: true
},
{
key: 'customerhovercol',
name: 'Custom Hover Column',
text: 'Custom Hover Column',
editable: true,
dataType: 'string',
minWidth: 100,
maxWidth: 100,
isResizable: true,
includeColumnInExport: false,
includeColumnInSearch: false,
applyColumnFilter: false,
disableSort: true,
hoverComponentOptions: { enable:true, hoverChildComponent: <CellHover customProps={{ someProp: '' }} /> }
},
{
key: 'name',
name: 'Name',
text: 'Name',
editable: true,
dataType: 'string',
minWidth: 100,
maxWidth: 100,
isResizable: true,
includeColumnInExport: true,
includeColumnInSearch: true,
applyColumnFilter: true
},
{
key: 'age',
name: 'Age',
text: 'Age',
editable: true,
dataType: 'number',
minWidth: 100,
maxWidth: 100,
isResizable: true,
includeColumnInExport: true,
includeColumnInSearch: true,
applyColumnFilter: true
},
{
key: 'designation',
name: 'Designation',
text: 'Designation',
editable: true,
dataType: 'string',
minWidth: 100,
maxWidth: 100,
isResizable: true,
includeColumnInExport: true,
includeColumnInSearch: true,
inputType: EditControlType.MultilineTextField,
applyColumnFilter: true
},
{
key: 'salary',
name: 'Salary',
text: 'Salary',
editable: true,
dataType: 'number',
minWidth: 100,
maxWidth: 100,
isResizable: true,
includeColumnInExport: false,
includeColumnInSearch: true,
maxLength:5,
applyColumnFilter: true,
cellStyleRule: {
enable: true,
rule: {
operator : NumberAndDateOperators.LESSTHAN,
value: 50000
},
whenTrue: { textColor: '#EF5350', fontWeight: 'bold' },
whenFalse: { textColor: '#9CCC65' }
}
},
{
key: 'dateofjoining',
name: 'Date of Joining',
text: 'Date of Joining',
editable: true,
dataType: 'date',
minWidth: 150,
maxWidth: 150,
isResizable: true,
includeColumnInExport: true,
includeColumnInSearch: true,
inputType: EditControlType.Date
},
{
key: 'payrolltype',
name: 'Payroll Type',
text: 'Payroll Type',
editable: true,
dataType: 'string',
minWidth: 150,
maxWidth: 150,
isResizable: true,
includeColumnInExport: true,
includeColumnInSearch: true,
inputType: EditControlType.DropDown,
dropdownValues: [
{ key: 'weekly', text: 'Weekly' },
{ key: 'biweekly', text: 'Bi-Weekly' },
{ key: 'monthly', text: 'Monthly' }
]
},
{
key: 'employmenttype',
name: 'Employment Type',
text: 'Employment Type',
editable: true,
dataType: 'string',
minWidth: 200,
maxWidth: 200,
isResizable: true,
includeColumnInExport: true,
includeColumnInSearch: true,
inputType: EditControlType.Picker,
pickerOptions: {
pickerTags: ['Employment Type1', 'Employment Type2', 'Employment Type3', 'Employment Type4', 'Employment Type5', 'Employment Type6', 'Employment Type7', 'Employment Type8', 'Employment Type9', 'Employment Type10', 'Employment Type11', 'Employment Type12'],
minCharLimitForSuggestions: 2,
tagsLimit: 1,
pickerDescriptionOptions: {
enabled: true,
values: [
{ key: 'Employment Type1', description: 'Employment Type1 Description'},
{ key: 'Employment Type2', description: 'Employment Type2 Description'},
{ key: 'Employment Type3', description: 'Employment Type3 Description'},
{ key: 'Employment Type4', description: 'Employment Type4 Description'},
{ key: 'Employment Type5', description: 'Employment Type5 Description'},
{ key: 'Employment Type6', description: 'Employment Type6 Description'},
{ key: 'Employment Type7', description: 'Employment Type7 Description'},
{ key: 'Employment Type8', description: 'Employment Type8 Description'},
{ key: 'Employment Type9', description: 'Employment Type9 Description'},
{ key: 'Employment Type10', description: 'Employment Type10 Description'},
{ key: 'Employment Type11', description: 'Employment Type11 Description'},
{ key: 'Employment Type12', description: 'Employment Type12 Description'},
] },
suggestionsRule: StringOperators.STARTSWITH
}
}
];
const SetDummyData = () : void => {
const dummyData = [
{
id: "1",
customerhovercol: 'Hover Me',
name: "Name1",
age:32,
designation:'Designation1',
salary:57000,
dateofjoining:'2010-04-01T14:57:10',
payrolltype: 'Weekly',
employmenttype: 'Employment Type11'
},
{
id: "2",
customerhovercol: 'Hover Me',
name: "Name2",
age:27,
designation:'Designation2',
salary:42000,
dateofjoining:'2014-06-09T14:57:10',
payrolltype: 'Monthly',
employmenttype: 'Employment Type4'
},
{
id: "3",
customerhovercol: 'Hover Me',
name: "Name3",
age:35,
designation:'Designation3',
salary:75000,
dateofjoining:'2005-07-02T14:57:10',
payrolltype: 'Weekly',
employmenttype: 'Employment Type7'
},
{
id: "4",
customerhovercol: 'Hover Me',
name: "Name4",
age:30,
designation:'Designation4',
salary:49000,
dateofjoining:'2019-04-01T14:57:10',
payrolltype: 'Bi-Weekly',
employmenttype: 'Employment Type2'
}
];
setItems(dummyData);
}
React.useEffect(() => {
SetDummyData();
}, []);
return (
<Fabric>
<div className={classNames.controlWrapper}>
<TextField placeholder='Search Grid' className={mergeStyles({ width: '60vh', paddingBottom:'10px' })} onChange={(event) => EventEmitter.dispatch(EventType.onSearch, event)}/>
</div>
<EditableGrid
id={1}
columns={columns}
items={items}
enableCellEdit={true}
enableExport={true}
enableTextFieldEditMode={true}
enableTextFieldEditModeCancel={true}
enableGridRowsDelete={true}
enableGridRowsAdd={true}
height={'70vh'}
width={'140vh'}
position={'relative'}
enableUnsavedEditIndicator={true}
//onGridSave={onGridSave}
enableGridReset={true}
enableColumnFilters={true}
enableColumnFilterRules={true}
enableRowAddWithValues={{enable : true, enableRowsCounterInPanel : true}}
layoutMode={DetailsListLayoutMode.justified}
selectionMode={SelectionMode.multiple}
enableRowEdit={true}
enableRowEditCancel={true}
enableBulkEdit={true}
enableColumnEdit={true}
enableSave={true}
/>
</Fabric>
);
};
export default Consumer;
}

FlChart to display different time series

I try to use the following code for my application to display the weight of animals in a chart. My goal is a variable time controlled via buttons (e.g. 1 month, 6 months, 1 year,...).
LineChart(
LineChartData(
lineTouchData: LineTouchData(enabled: true),
gridData: FlGridData(
show: false,
drawHorizontalLine: false,
drawVerticalLine: false,
getDrawingVerticalLine: (value) {
return FlLine(
color: Colors.black,
strokeWidth: 1,
);
},
getDrawingHorizontalLine: (value) {
return FlLine(
color: const Color(0xff37434d),
strokeWidth: 1,
);
},
),
lineBarsData: [
LineChartBarData(
spots: [
FlSpot(0, data_snap()['Historie_Inhalt']['0']),
FlSpot(1, data_snap()['Historie_Inhalt']['1']),
FlSpot(2, data_snap()['Historie_Inhalt']['2']),
FlSpot(3, data_snap()['Historie_Inhalt']['3']),
FlSpot(4, data_snap()['Historie_Inhalt']['4']),
FlSpot(6, data_snap()['Historie_Inhalt']['5'])],
isCurved: true,
barWidth: 1,
colors: [
Colors.black87,
],
belowBarData: BarAreaData(
show: true,
),
aboveBarData: BarAreaData(
show: true,
colors: [Colors.grey.withOpacity(0.3)]
),
dotData: FlDotData(
show: false,
getDotPainter: (spot, percent, barData, index) =>
FlDotCirclePainter(
radius: 10,
color: Colors.deepOrange.withOpacity(0.5)),
),
),
],
titlesData: FlTitlesData(
bottomTitles: SideTitles(
showTitles: false,
reservedSize: 10,
getTitles: (value) {
switch (value.toInt()) {
case 0:
return '2019';
case 1:
return '2020';
case 2:
return '2021';
case 3:
return '2022';
default:
return '';
}
}),
leftTitles: SideTitles(showTitles: true, margin: 3,
reservedSize: SizeConfig.safeBlockHorizontal * 11
),
rightTitles: SideTitles(showTitles: false),
topTitles: SideTitles(showTitles: false),
),
),
swapAnimationDuration: Duration(milliseconds: 1500),
)
I get the following error directly for the first FlSpot:
type 'String' is not a subtype of type 'int' of 'index'
So far I retrieved only six fixed values from Firebase and displayed them with the following code:
FlSpot(5, data_snap()['P_1W_W']),
'P_1W_W' is in the screenshot below on the same level as 'name'.
The database looks like this ('Historie_Inhalt' is defined as an Array):

How to exclude code from running inside requestAnimationFrame

Hi all, in a nextjs app Im using requestAnimationFrame and matter.js to animate shapes created using paper.js. The shapes are created with a javascript Class inside a forEach loop. Each shape (RegularPolygon) has a random number of sides. When I run the code, Matter.js takes care of the physics but the logic to create the random sides also animates creating a cool (but undesirable strobing effect) of continuously randomising the number of sides of the RegularPolygon. I'm looking for a way of creating the shapes with random sides, once, and then animating them. Thanks in advance.
link to netlify site
import { Engine, Render, World, Bodies } from 'matter-js';
import { useEffect, useRef } from 'react';
import { paper } from 'paper';
const random = (min, max) => {
return Math.random() * min + Math.random() * max + min;
};
function Canvas(props) {
const scene = useRef();
const engine = useRef(Engine.create());
const paperRef = useRef();
const raf = useRef();
console.log(random);
useEffect(() => {
const time = 0;
window.addEventListener('load', () => {
paper.setup(paperRef.current);
const cw = document.body.clientWidth;
const ch = document.body.clientHeight;
const render = Render.create({
element: scene.current,
engine: engine.current,
options: {
width: cw,
height: ch,
wireframes: false,
background: 'transparent',
},
});
World.add(engine.current.world, [
Bodies.rectangle(cw / 2, -10, cw, 20, {
isStatic: true,
}),
Bodies.rectangle(-10, ch / 2, 20, ch, {
isStatic: true,
fillStyle: '#F35e66',
}),
Bodies.rectangle(cw / 2, ch + 10, cw, 20, {
isStatic: true,
fillStyle: '#F35e66',
}),
Bodies.rectangle(cw + 10, ch / 2, 20, ch, {
isStatic: true,
fillStyle: '#F35e66',
}),
]);
Engine.run(engine.current);
Render.run(render);
const balls = [];
for (let i = 0; i < 40; i++) {
balls.push(
Bodies.circle(Math.random() * cw, 0, 80, {
density: Math.random(),
friction: 0.01,
frictionAir: 0.00001,
restitution: 0.8,
render: {
fillStyle: '#F35e66',
strokeStyle: 'black',
lineWidth: 1,
},
})
);
}
var ball = Bodies.circle(0, 0, 20, {
density: 0.04,
friction: 0.01,
frictionAir: 0.00001,
restitution: 0.8,
render: {
fillStyle: '#F35e66',
strokeStyle: 'black',
lineWidth: 1,
},
});
for (let i = 0; i < balls.length; i++) {
World.add(engine.current.world, [balls[i]]);
}
const shapes = [];
for (let i = 0; i < balls.length; i++) {
shapes.push(
new paper.Path.RegularPolygon({
position: new paper.Point([
balls[i].position.x,
balls[i].position.y,
]),
sides: Math.floor(random(0, 8)),
radius: 100,
fillColor: 'tomato',
})
);
}
class Shape {
constructor(x, y, angle) {
this.angle = angle;
this.x = x;
this.y = y;
this.draw();
this.shape = new paper.Path.RegularPolygon({
position: new paper.Point([this.x, this.y]),
sides: Math.floor(random(0, 8)),
radius: 100,
fillColor: 'tomato',
});
}
draw() {
// this.shape.rotate(this.angle);
}
}
console.log(ball);
const callback = () => {
// paper.view.update();
paper.project.clear();
balls.forEach((ball) => {
new Shape(ball.position.x, ball.position.y, ball.angle);
// let shape = new paper.Path.RegularPolygon({
// position: new paper.Point([
// ball.position.x,
// ball.position.y,
// ]),
// sides: Math.floor(Math.random() * 8),
// radius: 100,
// fillColor: 'tomato',
// });
// shape.rotate(ball.angle);
});
const shape = new paper.Path.RegularPolygon({
position: new paper.Point([
ball.position.x,
ball.position.y,
]),
sides: 5,
radius: 100,
fillColor: 'tomato',
});
shape.rotate(ball.angle);
raf.current = requestAnimationFrame(callback);
};
raf.current = requestAnimationFrame(callback);
return () => {
cancelAnimationFrame(raf.current);
Render.stop(render);
World.clear(engine.current.world);
Engine.clear(engine.current);
render.canvas.remove();
render.canvas = null;
render.context = null;
render.textures = {};
};
});
}, []);
return (
<div className=''>
<div className='paper'>
<canvas
resize='true'
ref={paperRef}
style={{
width: '100%',
height: '100%',
position: 'fixed',
top: 0,
left: 0,
}}
/>
</div>
<div
ref={scene}
style={{
display: 'none',
width: '100%',
height: '100%',
position: 'fixed',
top: 0,
left: 0,
}}
/>
</div>
);
}
export default Canvas;

How to show multi data Labels on group column highcharts

I have the data that I want to display on column like this:
I tried this code but it isn't working. How can I do this?
HTML:
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="http://code.highcharts.com/modules/exporting.js"></script>
<div id="container" style="min-width: 310px; height: 400px; margin: 0 auto"></div>
Javascript:
$(function () {
$('#container').highcharts({
chart: {
type: 'column'
},
title: {
text: 'Column chart'
},
xAxis: {
categories: ['Apples', 'Oranges', 'Pears']
},
yAxis: {
min: 0,
title: {
text: 'Total fruit consumption'
},
stackLabels: {
enabled: true,
style: {
fontWeight: 'bold',
color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
}
}
},
legend: {
align: 'right',
x: -70,
verticalAlign: 'top',
y: 20,
floating: true,
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || 'white',
borderColor: '#CCC',
borderWidth: 1,
shadow: false
},
tooltip: {
formatter: function() {
var allSeries = this.series.chart.series;
var totalAmount = 0;
for(var s in allSeries) { totalAmount += allSeries[s].points[this.point.x].Amount; }
return '<b>'+ this.x +'</b><br/>'+
this.series.name +': '+ this.y + ' (<b>$ ' + this.point.Amount +') <br/>'+
'Total: '+ this.point.stackTotal + ' (<b>$ ' + totalAmount +')';
}
},
plotOptions: {
column: {
dataLabels: {
enabled: true,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white',
style: {
textShadow: '0 0 3px black, 0 0 3px black'
},
formatter: function() {
return this.point.Amount + '%'
},
}
}
},
series: [{
name: 'John',
data: [{y: 5, Amount: 100}, {y: 3, Amount: 60}, {y: 4, Amount: 80}]
}, {
name: 'Joe',
data: [{y: 3, Amount: 60}, {y: 4, Amount: 80}, {y: 4, Amount: 80}]
}]
});
});
Check out this Fiddle
dataLabels: {
enabled: true,
useHTML: true,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white',
style: {
textShadow: '0 0 3px black, 0 0 3px black'
},
formatter: function() {
var pointHeight = this.point.shapeArgs.height + 20;
return '<div class="datalabel" style="position: relative; top: 0px">' + this.point.Amount + '%' + '</div><div class="datalabelInside" style="text-shadow:none;color:#000;position: absolute; top:' + pointHeight / 2 + 'px">' + this.y + '</div>';
}
}

highcharts solid gauge: bigger tick marks

I am making a solid gauge with highcharts. I am trying to make the ticks long enough to span both data series. The goal is for a white line to cut through the colored bands at 10, 6, 2.9, and 0%. Notice how at 2.9%, the tick doesn't go all the way through (even though the length is set to 100).
I have tried yAxis.tickLength to make the ticks longer, to no avail. I also tried yAxis.tickPosition: 'inside'. That doesn't solve it either. Here is my JSFiddle.
http://jsfiddle.net/ncernek/wy6bo63p/2/
Thank you for your help.
If you add dummy second pane and yAxis, then ticks will be both inside and outside - because in fact there will be 2 ticks looking like one.
Example: http://jsfiddle.net/Lcz6juea/
And if I get wrong index of ticks (over series) then you could use this code without zIndex set for axes: http://jsfiddle.net/Lcz6juea/1/
$(function() {
// Uncomment to style it like Apple Watch
/*
if (!Highcharts.theme) {
Highcharts.setOptions({
chart: {
backgroundColor: 'black'
},
colors: ['#F62366', '#9DFF02', '#0CCDD6'],
title: {
style: {
color: 'silver'
}
},
tooltip: {
style: {
color: 'silver'
}
}
});
}
// */
Highcharts.setOptions({
chart: {
backgroundColor: 'white'
},
colors: ['#FE670A', '#0277a0', 'white']
});
Highcharts.chart('container', {
chart: {
type: 'solidgauge',
marginTop: 50
},
title: {
text: 'Discepant Reads',
style: {
fontSize: '24px'
}
},
tooltip: {
borderWidth: 0,
backgroundColor: 'none',
shadow: false,
style: {
fontSize: '16px'
},
pointFormat: '{series.name}<br><span style="font-size:2em; color: {point.color}; font-weight: bold; text-align: center">{point.y}%</span>',
positioner: function(labelWidth, labelHeight) {
return {
x: 200 - labelWidth / 2,
y: 180
};
}
},
pane: [{
startAngle: -140,
endAngle: 140,
background: [{ // Track for Move
outerRadius: '112%',
innerRadius: '88%',
backgroundColor: Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0.3).get(),
borderWidth: 0,
shape: 'arc'
}, { // Track for Exercise
outerRadius: '87%',
innerRadius: '63%',
backgroundColor: Highcharts.Color(Highcharts.getOptions().colors[1]).setOpacity(0.3).get(),
borderWidth: 0,
shape: 'arc'
}, { // Track for Stand
outerRadius: '62%',
innerRadius: '38%',
backgroundColor: Highcharts.Color(Highcharts.getOptions().colors[2]).setOpacity(0.3).get(),
borderWidth: 0,
shape: 'arc'
}]
}, {
startAngle: -140,
endAngle: 140,
size: '95%',
background: []
}],
yAxis: [{
reversed: true,
min: 0,
max: 10,
lineWidth: 0,
tickLength: 100,
tickWidth: 4,
tickColor: 'white',
tickPosition: 'outside',
minorTickLength: 0,
tickPositions: [0, 2.9, 6, 10],
zIndex: 4,
labels: {
distance: 30,
enabled: true,
x: 0,
y: 0,
format: '{value} %',
style: {
fontSize: 16
}
}
}, {
pane: 1,
linkedTo: 0,
reversed: true,
min: 0,
max: 10,
lineWidth: 0,
tickLength: 100,
tickWidth: 4,
tickColor: 'white',
tickPosition: 'inside',
minorTickLength: 0,
tickPositions: [0, 2.9, 6, 10],
zIndex: 4,
labels: {
enabled: false
}
}],
plotOptions: {
solidgauge: {
borderWidth: '34px',
dataLabels: {
enabled: false
},
linecap: 'round',
stickyTracking: false
}
},
series: [{
name: 'Your Score',
borderColor: Highcharts.getOptions().colors[0],
data: [{
color: Highcharts.getOptions().colors[0],
radius: '100%',
innerRadius: '100%',
y: 4
}],
dataLabels: {
borderRadius: 0,
backgroundColor: "#fff",
borderWidth: 0,
borderColor: "#FFF",
style: {
fontSize: "50px"
},
color: "grey",
crop: true,
formatter: function() {
var s;
s = '<span style="font-size: 50px;">' + this.point.y + '</span>';
return s;
},
y: -30,
zIndex: 90
}
}, {
name: 'Department Average',
borderColor: Highcharts.getOptions().colors[1],
data: [{
color: Highcharts.getOptions().colors[1],
radius: '75%',
innerRadius: '75%',
y: 6
}]
}, {
name: '',
borderColor: Highcharts.getOptions().colors[2],
data: [{
color: Highcharts.getOptions().colors[2],
radius: '50%',
innerRadius: '50%',
y: 50
}]
}]
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/highcharts-more.js"></script>
<script src="https://code.highcharts.com/modules/solid-gauge.js"></script>
<div id="container" style="width: 400px; height: 400px; margin: 0 auto">
</div>
Using JavaScript
Highcharts.wrap(Highcharts.Tick.prototype, 'getMarkPath', function (prev, x, y, tickLength, tickWidth, horiz, renderer) {
return renderer.rect(x, y, 2, 80, 0)
.attr({
'stroke-width': 2,
stroke: 'white',
zIndex: 4,
style: 'transform: rotateZ(45deg) translateY(-290px)'
}).add();
});
You'd have to figure out a way to override each tick, but it's doable.
--
Using CSS
The (almost) pure CSS way is to target the exact SVG path and apply a transform to it. By no means is this way ideal, but it does provide a way to get the job done.
.highcharts-axis path:nth-child(2) {
transform: scale3d(1.6, 1, 1) rotateY(-59.7deg) translate(0, 25px);
stroke-width: 2;
}
.highcharts-axis path:nth-child(3) {
transform: scale3d(3.9, 1, 1) rotateY(-70deg) translate(0, 56px);
stroke-width: 2;
}
You would also have to adjust the zIndex attribute of the yAxis so that the redrawn ticks are on top of the other paths:
yAxis: {
...
zIndex: 4
}

Resources