How to add labels to the bubbles in Bubble Graph of react-chartjs-2 package? [duplicate] - reactjs

I'm creating a bubble chart using chartjs. I am able to create tooltips that describe each of the bubbles, but users of my chart may not be able to hover over it to see the tooltip. The BubbleData object format doesn't include a label element (I put one in anyway - no luck), I've tried the "labels" element for the Chart Data object (even though the docs say this is for Category labels - you never know!), and everything I can think of to put label on the bubble.
Is there a tooltip configuration that makes all the tooltips visible at all times? This would work for me as well.
Thanks;
Glenn

I was looking for the same thing and figured out how to do it.
add in the datasets the title:"dataTitle3" you want to show.
use the data labeling plugin.
simple code manipulation achieves what you want using
dataset.title
I have made a sample but I think you could find out how and represent the data you want if you play with: external link
new Chart(document.getElementById("bubble-chart"), {
type: 'bubble',
data: {
labels: "Africa",
datasets: [{
label: ["China"],
backgroundColor: "rgba(255,221,50,0.2)",
borderColor: "rgba(255,221,50,1)",
title: "dataTitle1", //adding the title you want to show
data: [{
x: 21269017,
y: 5.245,
r: 15
}]
}, {
label: ["Denmark"],
backgroundColor: "rgba(60,186,159,0.2)",
borderColor: "rgba(60,186,159,1)",
title: "dataTitle2",
data: [{
x: 258702,
y: 7.526,
r: 10
}]
}, {
label: ["Germany"],
backgroundColor: "rgba(0,0,0,0.2)",
borderColor: "#000",
title: "dataTitle3", //adding the title you want to show
data: [{
x: 3979083,
y: 6.994,
r: 15
}]
}, {
label: ["Japan"],
backgroundColor: "rgba(193,46,12,0.2)",
borderColor: "rgba(193,46,12,1)",
title: "dataTitle4", //adding the title you want to show
data: [{
x: 4931877,
y: 5.921,
r: 15
}]
}]
},
options: {
title: {
display: true,
text: 'Predicted world population (millions) in 2050'
},
scales: {
yAxes: [{
scaleLabel: {
display: true,
labelString: "Happiness"
}
}],
xAxes: [{
scaleLabel: {
display: true,
labelString: "GDP (PPP)"
}
}]
}
}
});
Chart.plugins.register({
afterDatasetsDraw: function(chart, easing) {
var ctx = chart.ctx;
chart.data.datasets.forEach(function(dataset, i) {
var meta = chart.getDatasetMeta(i);
if (meta.type == "bubble") { //exclude scatter
meta.data.forEach(function(element, index) {
// Draw the text in black, with the specified font
ctx.fillStyle = 'rgb(0, 0, 0)';
var fontSize = 13;
var fontStyle = 'normal';
var fontFamily = 'Helvetica Neue';
ctx.font = Chart.helpers.fontString(fontSize, fontStyle, fontFamily);
// Just naively convert to string for now
var dataString = dataset.data[index].toString();
// Make sure alignment settings are correct
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
var padding = 15;
var position = element.tooltipPosition();
ctx.fillText(dataset.title, position.x, position.y - (fontSize / 2) - padding);
});
} //if
});
}
});
<canvas id="bubble-chart" width="800" height="800"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js" integrity="sha512-ElRFoEQdI5Ht6kZvyzXhYG9NqjtkmlkfYk0wr6wHxU9JEHakS7UJZNeml5ALk+8IKlU6jDgMabC3vkumRokgJA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

ChartJs has a plugin now for this.
https://github.com/chartjs/chartjs-plugin-datalabels
Just install it using nuget or bower and add the reference of it. It wil automatically set z as label

The sytax has changed with chart.js V3 in a few places so I thought I'd share my variation on the chosen answer.
Chart.register({
id: 'permanentLabel',
afterDatasetsDraw: function (chart, args, options) {
var ctx = chart.ctx
chart.data.datasets.forEach(function (dataset, i) {
var meta = chart.getDatasetMeta(i)
if (meta.type == 'bubble') {
meta.data.forEach(function (element, index) {
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
var position = element.tooltipPosition()
ctx.fillText(dataset.data[index].label.toString(), position.x, position.y - dataset.data[index].r - Chart.defaults.font.size)
})
}
})
},
})

I have an some extra code, to avoid overlapping of labels.
var labelPlugin = {
myTimeout: null,
getNewYPostion:function(item, alreadyUsed, fontSize){
for(let i of alreadyUsed){
if((item.y_from >= i.y_from && item.y_from <= i.y_to) || (item.y_to>= i.y_from && item.y_to <= i.y_to)){
if((item.x_from >= i.x_from && item.x_from <= i.x_to) || (item.x_to>= i.x_from && item.x_to <= i.x_to)){
item.y_from=i.y_to+(fontSize*0.1);
item.y_to=item.y_from+fontSize;
return this.getNewYPostion(item, alreadyUsed, fontSize);
}
}
}
return item;
},
afterDatasetsDraw: function (chart, args, options) {
var ctx = chart.ctx;
var that=this;
clearTimeout(this.myTimeout);
this.myTimeout = setTimeout(function () {
var alreadyUsed = [];
chart.data.datasets.forEach(function (dataset, i) {
var txt = dataset.label;
var txtSize = ctx.measureText(txt).width;
var meta = chart.getDatasetMeta(i);
if (meta.type === "bubble") { //exclude scatter
var fontSize = 10;
var fontStyle = 'normal';
var fontFamily = 'Helvetica Neue';
ctx.font = Chart.helpers.fontString(fontSize, fontStyle, fontFamily);
ctx.fillStyle = 'rgb(0, 0, 0)';
ctx.textAlign = 'left';
ctx.textBaseline = 'middle';
var padding, position, x_from, x_to, y, y_from, y_to;
meta.data.forEach(function (element, index) {
padding = element.options.radius;
position = element.tooltipPosition();
x_from = position.x + padding + 5; // left
x_to = x_from + txtSize; // left
y = position.y; // top
y_from = y - (fontSize * 0.5);
y_to = y + (fontSize * 0.5);
var item={
'y_from': y_from,
'y_to': y_to,
'x_from': x_from,
'x_to': x_to,
};
item=that.getNewYPostion(item, alreadyUsed, fontSize);
alreadyUsed.push(item);
ctx.fillText(txt, item.x_from, item.y_from+(0.5*fontSize));
});
}
});
}, 500);
}
};

In 2022 the current version is 3.9.1 here is a working snippet:
const $canvas = document.getElementById('chart')
const popData = {
datasets: [{
label: ['Deer Population'],
data: [{
x: 100,
y: 0,
r: 25,
label: 'Russia',
}, {
x: 60,
y: 30,
r: 20,
label: 'China',
}, {
x: 40,
y: 60,
r: 25,
label: 'Canada',
}, {
x: 80,
y: 80,
r: 40,
label: 'US',
}, {
x: 20,
y: 30,
r: 25,
label: 'Africa',
}, {
x: 0,
y: 100,
r: 5,
label: 'Europe',
}],
backgroundColor: "#FF9966"
}]
};
const bubbleChart = new Chart($canvas, {
type: 'bubble',
data: popData
});
const fontSize = Chart.defaults.font.size
Chart.register({
id: 'permanentLabel',
afterDatasetsDraw: (chart, args, options) => {
const ctx = chart.ctx
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
chart.data.datasets.forEach((dataset, i) => {
const meta = chart.getDatasetMeta(i)
if (meta.type !== 'bubble') return
meta.data.forEach((element, index) => {
const item = dataset.data[index]
const position = element.tooltipPosition()
ctx.fillText(item.label.toString(), position.x, position.y - item.r - fontSize)
})
})
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>
<canvas id="chart" width="600" height="180"></canvas>

Related

How can I generate a custom legend in chart.js in React [duplicate]

I need the value of chart show after name of data for example ([colour of data] Car 50, [colour of data] Motorcycle 200). I've tried change the value of legend title but it doesn't work at all
Here is it my code:
var ctx = document.getElementById('top-five').getContext('2d');
var myChartpie = new Chart(ctx, {
type: 'pie',
data: {
labels: {!! $top->pluck('name') !!},
datasets: [{
label: 'Statistics',
data: {!! $top->pluck('m_count') !!},
backgroundColor: {!! $top->pluck('colour') !!},
borderColor: {!! $top->pluck('colour') !!},
}]
},
options: {
plugins: {
legend: {
display: true,
title: {
text: function(context) {//I've tried to override this but doesn't work
var value = context.dataset.data[context.dataIndex];
var label = context.label[context.dataIndex];
return label + ' ' + value;
},
}
},
},
responsive: true,
}
});
You can use a custom generateLabels function for this:
var options = {
type: 'doughnut',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
}]
},
options: {
plugins: {
legend: {
labels: {
generateLabels: (chart) => {
const datasets = chart.data.datasets;
return datasets[0].data.map((data, i) => ({
text: `${chart.data.labels[i]} ${data}`,
fillStyle: datasets[0].backgroundColor[i],
index: i
}))
}
}
}
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.js"></script>
</body>
The below is a direct over ride of the default label generation found in the controller here. I have made one change on the text property within the generateLabels function in order to append the data value. It preserves the data toggling and strikethrough styling when a label is toggled.
plugins: {
legend: {
labels: {
generateLabels(chart) {
const data = chart.data;
if (data.labels.length && data.datasets.length) {
const {labels: {pointStyle}} = chart.legend.options;
return data.labels.map((label, i) => {
const meta = chart.getDatasetMeta(0);
const style = meta.controller.getStyle(i);
return {
text: `${label}: ${data['datasets'][0].data[i]}`,
fillStyle: style.backgroundColor,
strokeStyle: style.borderColor,
lineWidth: style.borderWidth,
pointStyle: pointStyle,
hidden: !chart.getDataVisibility(i),
// Extra data used for toggling the correct item
index: i
};
});
}
return [];
}
},
onClick(e, legendItem, legend) {
legend.chart.toggleDataVisibility(legendItem.index);
legend.chart.update();
}
}
//...
}
[1]: https://github.com/chartjs/Chart.js/blob/master/docs/samples/legend/html.md
You can also use the base implementation to reduce the amount of copied code. Note that some chart types (like donut) already overrides the default label generation.
plugins: {
legend: {
labels: {
generateLabels: function (chart) {
return Chart.defaults.plugins.legend.labels.generateLabels(chart).map(function (label) {
var dataset = chart.data.datasets[label.datasetIndex];
var total = 0;
for (var j = 0; j < dataset.data.length; j++)
total += dataset.data[j].y;
label.text = dataset.label + ': ' + total;
return label;
});
}
}
}
}

Set Tooltip over line Chartjs

I wanna show tooltips over the line not only on data points.
I also tried the chartjs-plugin-crosshair but it doesn't work in V3 of chartjs.
You can write a custom implementation for V3 for it:
// Options for the indicators
const indicatorOptions = {
radius: 4,
borderWidth: 1,
borderColor: 'red',
backgroundColor: 'transparent'
};
// Override getLabelAndValue to return the interpolated value
const getLabelAndValue = Chart.controllers.line.prototype.getLabelAndValue;
Chart.controllers.line.prototype.getLabelAndValue = function(index) {
if (index === -1) {
const meta = this.getMeta();
const pt = meta._pt;
const vScale = meta.vScale;
return {
label: 'interpolated',
value: vScale.getValueForPixel(pt.y)
};
}
return getLabelAndValue.call(this, index);
}
// The interaction mode
Chart.Interaction.modes.interpolate = function(chart, e, option) {
const x = e.x;
const items = [];
const metas = chart.getSortedVisibleDatasetMetas();
for (let i = 0; i < metas.length; i++) {
const meta = metas[i];
const pt = meta.dataset.interpolate({
x
}, "x");
if (pt) {
const element = new Chart.elements.PointElement({ ...pt,
options: { ...indicatorOptions
}
});
meta._pt = element;
items.push({
element,
index: -1,
datasetIndex: meta.index
});
} else {
meta._pt = null;
}
}
return items;
};
// Plugin to draw the indicators
Chart.register({
id: 'indicators',
afterDraw(chart) {
const metas = chart.getSortedVisibleDatasetMetas();
for (let i = 0; i < metas.length; i++) {
const meta = metas[i];
if (meta._pt) {
meta._pt.draw(chart.ctx);
}
}
},
afterEvent(chart, args) {
if (args.event.type === 'mouseout') {
const metas = chart.getSortedVisibleDatasetMetas();
for (let i = 0; i < metas.length; i++) {
metas[i]._pt = null;
}
args.changed = true;
}
}
})
var ctx = document.getElementById("myChart").getContext("2d");
var chart = new Chart(ctx, {
type: "line",
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
fill: true,
label: "My First dataset",
backgroundColor: "rgba(132, 0, 0, 1)",
borderColor: "rgb(255, 99, 132)",
data: [0, 10, 5, 2, 20, 30, 45]
},
{
data: [30, 40, 50],
label: 'My Second Dataset',
fill: true,
backgroundColor: "lightgreen",
borderColor: "green"
}
]
},
options: {
interaction: {
mode: "interpolate",
intersect: false,
axis: "x"
},
plugins: {
tooltip: {
displayColors: false,
}
}
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.js"></script>
<h1>Interpolating line values</h1>
<div class="myChartDiv">
<canvas id="myChart" width="600" height="400"></canvas>
</div>
The following combination of chartjs-plugin-crosshair and chart.js seems to be working fine for me.
"chart.js": "^3.4.0",
"chartjs-plugin-crosshair": "^1.2.0"
I am initiating the Chart object like below:
Chart.register(CrosshairPlugin);
Which can be used properly in an useEffect block:
useEffect(() =>
Chart.register(CrosshairPlugin);
return () => {
Chart.unregister(CrosshairPlugin);
};
}, []);
And then you can pass the options of the chart like below:
{
...,
options: {
plugins: {
crosshair: {
line: {
color: "#d1d1d1",
width: 1,
},
sync: {
enabled: true,
group: 1,
suppressTooltips: false,
},
zoom: {
enabled: false,
},
}
}
}
}
Note that the configurations above, will keep the crosshair pointer synced over all your charts rendered on the same component. You may need to change the behavior here.
you can use chartjs-plugin-crosshair
function generateDataset(shift, label, color) {
var data = [];
var x = 0;
while (x < 30) {
data.push({
x: x,
y: Math.sin(shift + x / 3)
});
x += Math.random();
}
var dataset = {
backgroundColor: color,
borderColor: color,
showLine: true,
fill: false,
pointRadius: 2,
label: label,
data: data,
lineTension: 0,
interpolate: true
};
return dataset;
}
var chart1 = new Chart(document.getElementById("chart").getContext("2d"), {
type: "scatter",
options: {
plugins: {
crosshair: {
sync: {
enabled: false
},
},
tooltip: {
animation: false,
mode: "interpolate",
intersect: false,
callbacks: {
title: function(a, d) {
return a[0].element.x.toFixed(2);
},
label: function(d) {
return (
d.chart.data.datasets[d.datasetIndex].label + ": " + d.element.y.toFixed(2)
);
}
}
}
},
scales: {
x: {
min: 2,
max: 28
}
}
},
data: {
datasets: [
generateDataset(0, "A", "red")
]
}
});
<script src="https://cdn.jsdelivr.net/npm/moment#2.27.0/moment.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.4.0/dist/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment#0.1.1"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-crosshair#1.2.0/dist/chartjs-plugin-crosshair.min.js"></script>
<canvas id="chart" height="100"></canvas>
https://jsfiddle.net/Lb0k2sqx/1/

Is There any way to show image on top of the stacked bar, Am getting image on every color Instead of that i need only on top of each bar

Am returning Image inside labels, Its rendering image on every color , But i need only on top of the bar and image should be dynamically change.
this.options = {
legend: {
display:false,
},
plugins: {
datalabels: {
display: false,
},
labels: {
render: (args) => {
return { src: "https://i.stack.imgur.com/9EMtU.png", width: 16, height: 16 };
}
}
},
You could get rid of chartjs-plugin-labels and directly use the Plugin Core API. It offers a range of hooks that can be used for performing custom code. You can for example use the afterDraw hook to draw the images through CanvasRenderingContext2D.drawImage().
afterDraw: chart => {
let ctx = chart.chart.ctx;
let xAxis = chart.scales['x-axis-0'];
let yAxis = chart.scales['y-axis-0'];
xAxis.ticks.forEach((value, index) => {
let sum = chart.chart.data.datasets.filter(ds => !ds._meta[0].hidden).reduce((sum, ds) => sum + ds.data[index], 0);
let x = xAxis.getPixelForTick(index);
let y = yAxis.getPixelForValue(sum);
let image = new Image();
image.src = images[index];
ctx.drawImage(image, x - 12, y - 25);
});
}
To make sure that the top located image does not overlap the legend, the following code should be invoked prior to create the chart.
Chart.Legend.prototype.afterFit = function() {
this.height = this.height + 25;
};
Please take a look at below runnable code and see how it works.
const images = ['https://i.stack.imgur.com/2RAv2.png', 'https://i.stack.imgur.com/Tq5DA.png', 'https://i.stack.imgur.com/3KRtW.png', 'https://i.stack.imgur.com/iLyVi.png'];
Chart.Legend.prototype.afterFit = function() {
this.height = this.height + 25;
};
new Chart("canvas", {
type: 'bar',
plugins: [{
afterDraw: chart => {
let ctx = chart.chart.ctx;
let xAxis = chart.scales['x-axis-0'];
let yAxis = chart.scales['y-axis-0'];
xAxis.ticks.forEach((value, index) => {
let sum = chart.chart.data.datasets.filter(ds => !ds._meta[0].hidden).reduce((sum, ds) => sum + ds.data[index], 0);
let x = xAxis.getPixelForTick(index);
let y = yAxis.getPixelForValue(sum);
let image = new Image();
image.src = images[index];
ctx.drawImage(image, x - 12, y - 25);
});
}
}],
data: {
labels: ["A", "B", "C", "D"],
datasets: [{
label: 'X',
backgroundColor: "rgba(220,220,220,0.5)",
data: [50, 40, 23, 45]
}, {
label: 'Y',
backgroundColor: "rgba(151,187,205,0.5)",
data: [50, 40, 78, 23]
}, {
label: 'Z',
backgroundColor: "rgba(82,154,190,0.5)",
data: [50, 67, 78, 23]
}]
},
options: {
responsive: true,
scales: {
xAxes: [{
stacked: true
}],
yAxes: [{
stacked: true
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="canvas" height="100"></canvas>

how to set zoom in react-native-charts-wrapper?

i'm doing my first React Native app,
i'm using react-native-charts-wrapper to show graphs.
i have a listener for buttons (see code below comment // CHANGE ZOOM HERE) in my screen to set a predefined zoom in the graph that i'm showing.
How would i do that ?
Does anyone has any experience using that library ?
here is my screen:
import React, {Component} from 'react';
import {View, Text, StyleSheet, processColor} from 'react-native';
import { Button} from "native-base";
import {CombinedChart} from 'react-native-charts-wrapper';
import moment from 'moment';
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'stretch',
backgroundColor: 'transparent',
paddingTop:20
}
});
var InsulinShort = [];
var InsulinLong = [];
var glocuseTests = [];
const injectionsCount = 1000;
for (var i = 1; i < injectionsCount; i++) {
var random = Math.random();
if (random <= 0.7) {
var gloguseValue = Math.floor(Math.random() * 40) + 75;
var gloguseposition =Math.random();
glocuseTests.push({x:i+gloguseposition,y: gloguseValue, marker: "level: "+gloguseValue});
}
}
for (var i = 1; i < injectionsCount; i++) {
var random = Math.random();
if (random <= 0.15) {
var shortvalue = Math.floor(Math.random() * 16) + 1 ;
var shortPosition = Math.round(Math.random() * 100) / 100;
InsulinShort.push({x:i+shortPosition,y: shortvalue*20, marker: shortvalue+ " units of short insulin"});
}else if (random <= 0.3) {
var longePosition = Math.round(Math.random() * 10) / 10;
var longvalue = Math.floor(Math.random() * 16) + 1;
InsulinLong.push({x:i+longePosition,y: longvalue*20, marker: longvalue+ " units of long insulin"});
}else{
}
}
export default class LogGraph extends Component {
constructor() {
super();
// var valueFormatter = new Array(3515599953920);
this.state = {
loading: true,
days:1000,
legend: {
enabled: true,
textSize: 18,
form: 'SQUARE',
formSize: 18,
xEntrySpace: 10,
yEntrySpace: 5,
formToTextSpace: 5,
wordWrapEnabled: true,
maxSizePercent: 0.5
},
xAxis: {
valueFormatter: [
'01/04/18',
'02/04/18',
'03/04/18',
'04/04/18',
'05/04/18',
'06/04/18',
'07/04/18',
'08/04/18',
'09/04/18',
'10/04/18',
'11/04/18',
'12/04/18',
'13/04/18',
'14/04/18',
'15/04/18',
'16/04/18',
'17/04/18',
'18/04/18',
'19/04/18',
'20/04/18',
],
// valueFormatterPattern:'ssss',
// limitLines:100,
// drawLimitLinesBehindData:false,
// avoidFirstLastClipping: false,
textColor: processColor('#000'),
gridColor: processColor('#000'),
axisLineColor: processColor('#000'),
drawGridLines:true,
drawAxisLine:false,
drawLabels:true,
granularityEnabled: true,
// granularity:1515599953920,
granularity: 1,
// granularity: 131096 ,
position:'TOP',
textSize: 10,
labelRotationAngle:45,
gridLineWidth: 1,
axisLineWidth: 2,
gridDashedLine: {
lineLength: 10,
spaceLength: 10
},
centerAxisLabels:false,
},
yAxis: {
left: {
axisMinimum: 0,
axisMaximum: 400,
labelCount: 6,
labelCountForce: true,
granularityEnabled: true,
granularity: 5,
},
right: {
axisMinimum: 0,
axisMaximum: 20,
labelCount: 6, // 0 5 10 15 20 25 30
labelCountForce: true,
granularityEnabled: true,
granularity: 5,
}
},
marker: {
enabled: true,
markerColor: processColor('#F0C0FF8C'),
textColor: processColor('white'),
markerFontSize: 18,
},
data: {
barData: {
config: {
barWidth: 1 / 24 ,
},
dataSets: [{
values:InsulinLong,
label: 'Long Insulin',
config: {
drawValues: false,
colors: [processColor('#a2a4b2')],
}
},{
values:InsulinShort,
label: 'Short Insulin',
config: {
barShadowColor: processColor('red'),
highlightAlpha: 200,
drawValues: false,
colors: [processColor('#d0d5de')],
}
}]
},
lineData: {
dataSets: [{
values: glocuseTests,
label: 'Glucose Level',
config: {
drawValues: false,
colors: [processColor('#81d0fa')],
// mode: "CUBIC_BEZIER",
drawCircles: true,
lineWidth: 3,
}
}],
},
}
};
}
creatList(logs){
// var startTime = moment().millisecond();
var list = [];
var time = false;
if (logs) {
// console.log('firstLogDay',moment(firstLogDay).format('L'));
let gloguseItems = [];
let shortItems = [];
let longItems = [];
let firstValidFlag = false;
let firstLogTime;
let lastLogTime;
let days;
let firstLogDate;
let firstLogDayTime;
lastLogTime = logs[0].time;
for (var i = logs.length-1; i >= 0; i--) {
let item = logs[i];
if ( !firstValidFlag && ['glucose', 'long', 'short'].indexOf(item.type) >= 0 ) {
// debugger;
firstValidFlag = true;
firstLogTime = logs[i].time;
days = Math.round((lastLogTime-firstLogTime)/(1000*60*60*24));
firstLogDate = moment(firstLogTime).format('YYYY-MM-DD');
// console.log('firstLogDate',firstLogDate);
firstLogDayTime = new Date(firstLogDate);
firstLogDayTime = firstLogDayTime.getTime() - (2*60*60*1000);
// console.log('firstLogDayTime',firstLogDayTime);
}
if (firstValidFlag) {
let logX = ( item.time - firstLogDayTime ) / 1000 / 60 / 60 /24;
// logX = Math.round(logX * 10) / 10
if (logX) {
// logX = item.time;
// console.log(logX);
let logY = item.amount;
if (item.type !== 'glucose') {
if (item.type === 'short') {
shortItems.push({
x: logX,
y: logY*20,
marker: logY+ " units of short insulin" + moment(item.time).format('LLL')
})
}
if (item.type === 'long') {
longItems.push({
x: logX,
y: logY*20,
marker: logY+ " units of long insulin" + moment(item.time).format('LLL')
})
}
}else{
if(item.type === 'glucose'){
gloguseItems.push({
x: logX,
y: parseInt(logY),
marker: "level: "+ logY + moment(item.time).format('LLL')
})
}
}
}
}
}
let oldData = this.state.data;
oldData.lineData.dataSets[0].values = gloguseItems;
oldData.barData.dataSets[1].values = shortItems;
oldData.barData.dataSets[0].values = longItems;
let DayFlag = firstLogDate;
let valueFormatter = [];
valueFormatter.push(moment(DayFlag).format('DD/MM/YYYY'));
for (let i = 0; i < days; i++) {
DayFlag = moment(DayFlag).add(1, 'days');
valueFormatter.push(DayFlag.format('DD/MM/YYYY'));
}
let xAxis = this.state.xAxis;
xAxis.valueFormatter = valueFormatter;
this.setState({
data:oldData,
days:days,
xAxis:xAxis,
loading:false
});
}else{
this.setState({loading:false});
}
}
componentDidMount() {
this.creatList(this.props.logs);
}
zoomTwentyPressed() {
console.log ("pressed 25");
}
zoomFiftyPressed() {
console.log ("pressed 50");
}
zoomHundredPressed() {
console.log ("pressed 100");
// CHANGE ZOOM HERE
}
static displayName = 'Combined';
handleSelect(event) {
let entry = event.nativeEvent
if (entry == null) {
this.setState({...this.state, selectedEntry: null})
} else {
this.setState({...this.state, selectedEntry: JSON.stringify(entry)})
}
// console.log(event.nativeEvent)
}
render() {
return (
<View style={styles.container}>
{
(this.state.loading) ? <Text>Loading</Text>:
<CombinedChart
data={this.state.data}
xAxis={this.state.xAxis}
yAxis={this.state.yAxis}
legend={this.state.legend}
onSelect={this.handleSelect.bind(this)}
onChange={(event) => console.log(event.nativeEvent)}
marker={this.state.marker}
animation={{durationY: 1000,durationX: 1000}}
maxVisibleValueCount={16}
autoScaleMinMaxEnabled={true}
zoom={{scaleX: Math.floor(this.state.days/12), scaleY: 1, xValue: 4, yValue: 4, axisDependency: 'LEFT'}}
style={styles.container}/>
}
<View style={styles.buttonWrap}>
<Button block light onPress={this.zoomTwentyPressed()} style={(this.state.view === 'graph')?styles.buttonStyleCurrent:styles.buttonStyle}>
<Text>x100</Text>
</Button>
<Button block light onPress={this.zoomFiftyPressed()} style={(this.state.view === 'graph')?styles.buttonStyleCurrent:styles.buttonStyle}>
<Text>x50</Text>
</Button>
<Button block light onPress={this.zoomHundredPressed()} style={(this.state.view === 'graph')?styles.buttonStyleCurrent:styles.buttonStyle}>
<Text>x25</Text>
</Button>
</View>
</View>
);
}
}
I just put in the json format of options the prop dataZoom look this is my example
{
grafica: true,
option: {
title: {
text: ''
},
width: WIDTH - 100,
tooltip: {
trigger: 'axis'
},
xAxis: {
data: energiaV2.map(function (item) {
console.log(item.date, moment(item.date).format('hh:mm:ss'))
return moment(item.date).utc().calendar()//moment(item.date).utc().format('LL');//moment(item.date).utc().format('hh:mm:ss a');
}),
name: "dias",
nameLocation: 'middle',
nameGap: 30,
splitLine: {
show: false
}
},
yAxis: {
splitLine: {
show: false
},
name: "kWh",
nameLocation: 'middle',
},
/* toolbox: {
left: 'center',
feature: {
dataZoom: {
yAxisIndex: 'none'
},
restore: {},
}
}, */
dataZoom: [{
type: 'inside',
}, {
start: 5,
end: 10,
handleIcon: 'M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z',
handleSize: '80%',
handleWidth:30,
handleStyle: {
color: '#fff',
shadowBlur: 3,
shadowColor: 'rgba(0, 0, 0, 0.6)',
shadowOffsetX: 2,
shadowOffsetY: 2,
}
}],
series: [{
name: 'Activa kWh',
type: 'line',
data: energiaV2.map(function (item) {
return Math.floor(item.value * 100) / 100;
}),
},
{
name: 'Inductiva kVAr',
type: 'line',
data: energiaV2reactive.map(function (item) {
return Math.floor(item.value * 100) / 100;
}),
},
{
name: 'Capacitiva kVArhR',
type: 'line',
data: energiaV2inductive.map(function (item) {
return Math.floor(item.value * 100) / 100;
}),
},
],
color: ['rgb(253, 180, 59)', 'rgb(240, 94, 54)', 'rgb(0, 128, 35)']
},
grafica: true,
})

Jointjs and angular : ng click doesn't work

I am creating an element with joint js and putting it inside a paper. The element has an ng-click directive in a pencil. However when I click on the element
The element
joint.shapes.flowie.Rect = joint.shapes.basic.Generic.extend(_.extend({}, joint.shapes.basic.PortsModelInterface, {
markup: '<g class="rotatable" ><g class="scalable"><rect class="body"/></g><text class="label"/><text region="" transform="translate(40,10)" ng-init="alert()" ng-click="loadStep(workflow.steps[this.stepName])" class="fa edit fa-pencil"></text><g class="inPorts"/><g class="outPorts"/></g>',
portMarkup: '<g class="port port<%= id %>"><circle class="port-body"/><text class="port-label"/></g>',
defaults: joint.util.deepSupplement({
type: 'devs.Model',
size: { width: 1, height: 1 },
inPorts: [],
outPorts: [],
attrs: {
'.': { magnet: false },
'.body': {
width: 150, height: 350,
stroke: '#000000'
},
'.port-body': {
r: 8,
magnet: true,
stroke: '#000000'
},
text: {
// 'pointer-events': 'none'
},
'.label': { text: 'Model', 'ref-x': .5, 'ref-y': 10, ref: '.body', 'text-anchor': 'middle', fill: '#000000' },
'.inPorts .port-label': { x:-15, dy: 4, 'text-anchor': 'end', fill: '#000000'},
".inPorts circle": {type:"input", magnet:"passive" },
'.outPorts .port-label':{ x: 15, dy: 4, fill: '#000000',type:"output" }
}
}, joint.shapes.basic.Generic.prototype.defaults),
getPortAttrs: function(portName, index, total, selector, type) {
var attrs = {};
var portClass = 'port' + index;
var portSelector = selector + '>.' + portClass;
var portLabelSelector = portSelector + '>.port-label';
var portBodySelector = portSelector + '>.port-body';
attrs[portLabelSelector] = { text: portName };
attrs[portBodySelector] = { port: { id: portName || _.uniqueId(type) , type: type } };
attrs[portSelector] = { ref: '.body', 'ref-y': (index + 0.5) * (1 / total) };
if (selector === '.outPorts') { attrs[portSelector]['ref-dx'] = 0; }
return attrs;
}
}));
There is a saveStep function triggered by saving a form. The form contains some metadata for each element
I then do the following to add the step to the graph
shape = new joint.shapes.flowie.Start({
position: { x: 10, y: 10 },
size: { width: 100, height: 30 },
attrs: { rect: { fill: 'blue' }, '.label': { text: step.stepName, fill: 'white' } },
stepName:name
});
shape.set('inPorts', []);
shape.set('outPorts', ['OUT']);
graph.addCells([shape])
I have heard of the compile directive but can't figure out a way to use it.

Resources