Related
I have a plugin which should render a circle for each value in the dataset at the same height as each bar is. I can get the y position for a value with
chart.scales.y.getPixelForValue(index)
but that is not the position of the bars.
const data ={
labels:[
"Macht",
"Ehre",
"Besitz",
[
"Selbst-",
"verwirklichung"
],
"Wettbewerb",
"Dienen",
"Spiritualität"
],
"datasets": [
{
"label": "first",
"backgroundColor": "rgb(208,55,25)",
"data": [
4,
8,
5,
4,
1,
1,
3
]
},
{
"label": "second",
"backgroundColor": "rgb(240,223,89)",
"data": [
1,
4,
5,
2,
5,
3,
3
]
}
]
}
const circles = {
id: 'circles',
afterDraw(chart, args, options) {
const {ctx, scales:{x,y}} = chart;
options.data.forEach((dataset) => {
let even = true
dataset.data.forEach((value,index) => {
var xpos = x.getPixelForValue(value);
var ypos = chart.scales.y.getPixelForValue(index) //HERE I WANT THE Y POSITION OF EACH BAR
ctx.save();
ctx.fillStyle = dataset.backgroundColor;
ctx.beginPath();
ctx.arc(xpos, ypos, 10, 0, 2 * Math.PI);
ctx.fill();
ctx.stroke();
ctx.restore();
})
})
}
}
const chartOptions = {
maintainAspectRatio: false,
responsive:true,
indexAxis: 'y',
scales: {
x:{
min: 1,
max: 9,
},
y:{
ticks: {
stepSize: 1,
autoSkip: false,
},
min: 0,
max: 6,
position: 'left',
},
},
plugins: {
circles: {
data: [
{
"label": "Selbseinschätzung",
"backgroundColor": "rgb(208,55,25)",
"data": [
6,
4,
3,
7,
4,
4,
7
]
},
{
"label": "Selbseinschätzung",
"backgroundColor": "rgb(240,223,89)",
"data": [
7,
4,
4,
3,
6,
5,
2
]
}
]
}
}
}
const ctx = document.getElementById('mts').getContext('2d');
const myChart = new Chart(ctx, {
type: 'bar',
data: data,
options: chartOptions,
plugins: [circles]
});
[![enter image description here][1]][1]
How can I get the bars y position?
Now I have to give some more details, but I dont know how to explain the problem mor exactly. So I write this stuff.
I think you could use the dataset element for y.
const data ={
labels:["Macht", "Ehre", "Besitz", ["Selbst-", "verwirklichung"], "Wettbewerb", "Dienen", "Spiritualität"],
"datasets": [
{
"label": "first",
"backgroundColor": "rgb(208,55,25)",
"data": [4, 8, 5, 4, 1, 1, 3]
},
{
"label": "second",
"backgroundColor": "rgb(240,223,89)",
"data": [1, 4, 5, 2, 5, 3, 3]
}
]
}
const circles = {
id: 'circles',
afterDraw(chart, args, options) {
const {ctx, scales:{x,y}} = chart;
options.data.forEach((dataset, dsIndex) => {
const meta = chart.getDatasetMeta(dsIndex);
let even = true
dataset.data.forEach((value,index) => {
var xpos = x.getPixelForValue(value);
const elem = meta.data[index];
//var ypos = y.getPixelForValue(index) //HERE I WANT THE Y POSITION OF EACH BAR
var ypos = elem.y;
ctx.save();
ctx.fillStyle = dataset.backgroundColor;
ctx.beginPath();
ctx.arc(xpos, ypos, 10, 0, 2 * Math.PI);
ctx.fill();
ctx.stroke();
ctx.restore();
})
})
}
}
const chartOptions = {
maintainAspectRatio: false,
responsive:true,
indexAxis: 'y',
scales: {
x:{
min: 1,
max: 9,
},
y:{
ticks: {
stepSize: 1,
autoSkip: false,
},
min: 0,
max: 6,
position: 'left',
},
},
plugins: {
circles: {
data: [
{
"label": "Selbseinschätzung",
"backgroundColor": "rgb(208,55,25)",
"data": [
6,
4,
3,
7,
4,
4,
7
]
},
{
"label": "Selbseinschätzung",
"backgroundColor": "rgb(240,223,89)",
"data": [
7,
4,
4,
3,
6,
5,
2
]
}
]
}
}
}
const ctx = document.getElementById('myChart').getContext('2d');
const myChart = new Chart(ctx, {
type: 'bar',
data: data,
options: chartOptions,
plugins: [circles]
});
.myChartDiv {
max-width: 600px;
max-height: 400px;
}
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.9.1/dist/chart.min.js"></script>
<html>
<body>
<div class="myChartDiv">
<canvas id="myChart" width="600" height="400"/>
</div>
</body>
</html>
I have a simple scatterplot with two datasets: active and passive:
const data = {
"datasets": [{
"label": "Active",
"sentences": [
"A1",
"A2",
"A3"
],
"data": [
[
"0.4340433805869016",
"0.12813240157479788"
],
[
"-0.39983629799199083",
"0.12125799115087213"
],
[
"-0.04289228113339527",
"0.10106119377169194"
]
],
"borderColor": "#43a047",
"backgroundColor": "#7cb342"
},
{
"label": "Passive",
"sentences": [
"P1",
"P2",
"P3"
],
"data": [
[
"0.4295487808020268",
"0.19271652809947026"
],
[
"-0.4438451670978469",
"-0.08848766134414247"
],
[
"-0.10789534989054622",
"0.08013654263956245"
]
],
"borderColor": "#1e88e5",
"backgroundColor": "#039be5"
}
],
"labels": []
};
new Chart(document.getElementById("sentences"), {
type: "scatter",
data: data,
options: {
responsive: true,
plugins: {
legend: {
position: "top",
},
tooltip: {
callbacks: {
label: ctx => ctx.dataset.sentences[ctx.dataIndex]
}
}
}
}
});
(https://jsfiddle.net/br5dhpwx/)
Currently this renders fine as is:
However, I want to draw a line between the corresponding data points on mouseover. I.e. A1-P1, A2-P2, A3-P3, etc.
It should look something like this:
I tried to use the setHoverStyle event, but, so far, wasn't successful.
You can use a custom plugin for this:
const EXPANDO_KEY = 'customLinePlugin';
const data = {
"datasets": [{
"label": "Active",
"sentences": [
"A1",
"A2",
"A3"
],
"data": [
[
"0.4340433805869016",
"0.12813240157479788"
],
[
"-0.39983629799199083",
"0.12125799115087213"
],
[
"-0.04289228113339527",
"0.10106119377169194"
]
],
"borderColor": "#43a047",
"backgroundColor": "#7cb342"
},
{
"label": "Passive",
"sentences": [
"P1",
"P2",
"P3"
],
"data": [
[
"0.4295487808020268",
"0.19271652809947026"
],
[
"-0.4438451670978469",
"-0.08848766134414247"
],
[
"-0.10789534989054622",
"0.08013654263956245"
]
],
"borderColor": "#1e88e5",
"backgroundColor": "#039be5"
}
],
"labels": []
};
const plugin = {
id: "customLine",
afterInit: (chart) => {
chart[EXPANDO_KEY] = {
index: null
}
},
afterEvent: (chart, evt) => {
const activeEls = chart.getElementsAtEventForMode(evt.event, 'nearest', {
intersect: true
}, true)
if (activeEls.length === 0) {
chart[EXPANDO_KEY].index = null
return;
}
chart[EXPANDO_KEY].index = activeEls[0].index;
},
beforeDatasetsDraw: (chart, _, opts) => {
const {
ctx
} = chart;
const {
index
} = chart[EXPANDO_KEY];
if (index === null) {
return;
}
const dp0 = chart.getDatasetMeta(0).data[index]
const dp1 = chart.getDatasetMeta(1).data[index]
ctx.lineWidth = opts.width || 0;
ctx.setLineDash(opts.dash || []);
ctx.strokeStyle = opts.color || 'black'
ctx.save();
ctx.beginPath();
ctx.moveTo(dp0.x, dp0.y);
ctx.lineTo(dp1.x, dp1.y);
ctx.stroke();
ctx.restore();
}
}
new Chart(document.getElementById("sentences"), {
type: "scatter",
data: data,
options: {
responsive: true,
plugins: {
customLine: {
dash: [2, 2],
color: 'red',
width: 2
},
legend: {
position: "top",
},
tooltip: {
callbacks: {
label: ctx => ctx.dataset.sentences[ctx.dataIndex]
}
}
}
},
plugins: [plugin]
});
<body>
<canvas id="sentences"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.2/chart.js"></script>
</body>
EDIT:
For some reason stack snippet in creation works but doesnt like so itself, so here is a fiddle link: https://jsfiddle.net/Leelenaleee/btux41dz/
I'm trying to remove a dataset from label:
But the label callback is called twice, so i don't know how to do it.
I was expecting an array in the callback and that you can simply remove the one not needed.
here's what i have so far and tried:
var labels = [];
for (let index = 0; index < 12; index++) {
labels.push(index);
}
window.onload = function () {
var canvas = document.getElementById('elm-chart'),
ctx = canvas.getContext('2d');
var myLineChart = new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [
{
label: '-15',
data: [
{
x: 0,
y: 10,
},
{
x: 1,
y: 20,
},
],
borderColor: 'red',
},
{
label: '15',
data: [
{
x: 1,
y: 20,
},
{
x: 2,
y: 30,
},
],
borderColor: 'blue',
},
{
label: '25',
data: [
{
x: 2,
y: 30,
},
{
x: 3,
y: 35,
},
],
borderColor: 'yellow',
},
{
label: '-15',
data: [
{
x: 6,
y: -10,
},
{
x: 7,
y: -20,
},
],
borderColor: 'red',
},
{
label: '15',
data: [
{
x: 7,
y: -20,
},
{
x: 8,
y: -30,
},
],
borderColor: 'blue',
},
{
label: '25',
data: [
{
x: 8,
y: -30,
},
{
x: 9,
y: -35,
},
],
borderColor: 'yellow',
},
],
},
options: {
responsive: true,
plugins: {
legend: {
onClick: (evt, legendItem, legend) => {
let newVal = !legendItem.hidden;
legend.chart.data.datasets.forEach((dataset) => {
if (dataset.label === legendItem.text) {
dataset.hidden = newVal;
}
});
legend.chart.update();
},
labels: {
filter: (legendItem, chartData) => {
let entries = chartData.datasets.map((e) => e.label);
return entries.indexOf(legendItem.text) === legendItem.datasetIndex;
},
},
},
},
scales: {
x: {
type: 'linear',
ticks: {
stepSize: 30,
},
},
},
plugins: {
tooltip: {
callbacks: {
title: function (context) {
return [`test`, 'test2'];
},
label: function (context) {
console.log(context.dataset.label);
console.log(context.formattedValue);
console.log(context);
return [
`${context.dataset.label}:${context.formattedValue}`,
'test',
];
},
},
},
},
},
});
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.2.1/chart.min.js"></script>
<canvas id="elm-chart" width="640" height="480"></canvas>
So to be clear i don't want to remove the datapoint in the dataset. I just want to remove 1 datapoint from the label, the top one always
What you can do is instead of using the default tooltip instead use a html tooltip.
In the JS that makes the tooltip instead of looping over each active item you only take the first one and display that.
Official sample of html tooltip: https://www.chartjs.org/docs/master/samples/tooltip/html.html
I'm trying to make a gauge and want to have two band colors (wrong/red, good/green). I've an example of the amchart in their online Chart maker https://live.amcharts.com/new/edit/. But I'm not able to get this working in icCube.
current we have icCube reporting version 7.0.0 (5549).
This is my chart JSON:
{
"box": {
"id": "wb695",
"widgetAdapterId": "w28",
"rectangle": {
"left": 1510,
"top": 340,
"right": 1910,
"bottom": 640
},
"zIndex": 901
},
"data": {
"mode": "MDX",
"schemaSettings": {
"cubeName": null,
"schemaName": null
},
"options": {
"WIZARD": {
"measures": [],
"rows": [],
"rowsNonEmpty": false,
"columns": [],
"columnsNonEmpty": false,
"filter": []
},
"MDX": {
"statement": "with \n member [Measures].[Measure1] AS 0.9\n member [Measures].[Measure2] AS 0.1\nSELECT\n\n{[Measures].[Measure1], [Measures].[Measure2]} on 0\n\nFROM [cube]"
},
"DATASOURCE": {}
},
"ic3_name": "mdx Query-5",
"ic3_uid": "m17"
},
"data-render": {
"chartType": {
"label": "Gauge",
"proto": {
"chartPrototype": {
"type": "gauge",
"arrows": [
{
"id": "GaugeArrow-1"
}
],
"axes": [
{
"id": "GaugeAxis-1"
}
]
},
"graphPrototype": {},
"dataProviderType": 3
},
"id": "gauge-chart"
},
"graphsConfiguration": [
{
"graph": {}
}
],
"valueAxes": [],
"trendLinesGuides": {},
"configuredQuadrants": {},
"advanced": {
"titles": [],
"faceAlpha": 0,
"faceBorderAlpha": 0
},
"balloon": {
"offsetX": 8
},
"chartOptions": {
"axes": [
{
"axisAlpha": 0.25,
"bottomText": "SLA",
"bottomTextColor": "#2A3F56",
"tickAlpha": 0.25,
"bandOutlineAlpha": 1,
"bandAlpha": 1,
"bandOutlineThickness": 95,
"bandOutlineColor": "#0095BC",
"id": 1
}
],
"bands": [
{
"alpha": 0.8,
"color": "#B53728",
"endValue": 0.6,
"startValue": 0,
"id": "GaugeBand-1"
},
{
"alpha": 0.6,
"color": "#435035",
"endValue": 1,
"startValue": 0.6,
"innerRadius": 0.69,
"id": "GaugeBand-2"
}
]
},
"ic3Data": {
"chartTypeConfig": {
"pie-chart-donut": {
"chartType": {
"label": "Donut",
"proto": {
"chartPrototype": {
"type": "donut",
"pullOutRadius": 0,
"startDuration": 0,
"legend": {
"enabled": false,
"align": "center",
"markerType": "circle"
},
"innerRadius": "60%"
},
"dataProviderType": 1
},
"id": "pie-chart-donut"
},
"graphsConfiguration": [
{}
],
"valueAxes": [],
"trendLinesGuides": {},
"configuredQuadrants": {},
"advanced": {
"titles": []
},
"balloon": {
"offsetX": 8
},
"chartOptions": {
"showZeroSlices": false,
"labelsEnabled": false,
"innerRadius": "60%",
"startAngle": 270,
"radius": "",
"fontSize": 20,
"color": "#0095BC",
"outlineAlpha": 0.25,
"tapToActivate": false
}
}
}
},
"axes": [
{
"startValue": 0,
"endValue": 1,
"startAngle": -90,
"endAngle": 90
}
],
"valueFormatting": ""
},
"navigation": {
"menuVisibility": {
"back": true,
"axisXChange": "All",
"axisYChange": "All",
"filter": "All",
"reset": true,
"widget": true,
"others": "All"
},
"selectionMode": "disabled"
},
"events": {},
"filtering": {},
"hooks": {}
}
Sorry for the late answer, out of the box it's not possible but you can use hooks to change the javascript options sent to amcharts.
JS / On Widget Options :
function(context, options, $box) {
const bands = [
{
"color": "#00CC00",
"endValue": 300000,
"id": "GaugeBand-1",
"startValue": 0
},
{
"color": "#ffac29",
"endValue": 600000,
"id": "GaugeBand-2",
"startValue": 300000
},
{
"color": "#ea3838",
"endValue": 900000,
"id": "GaugeBand-3",
"innerRadius": "95%",
"startValue": 600000
}
];
options.axes[0]["bands"] = bands;
return options;
}
This should work
Working on google charts API (Line chart).I have same set of values which are used to draw lines for server and shipping, as the values are same two lines are overlapping as shown in the demo https://plnkr.co/edit/PNA1XQapRzvxGfm7behd?p=preview
Is there a way where we can see two lines instead of overlapping when they have the same values?
angular.module('myApp', ['googlechart'])
.controller('myController', function($scope) {
var chart1 = {};
chart1.type = "LineChart";
chart1.displayed = false;
chart1.data = {
"cols": [{
id: "month",
label: "Month",
type: "string"
}, {
id: "laptop-id",
label: "Laptop",
type: "number"
}, {
id: "desktop-id",
label: "Desktop",
type: "number"
}, {
id: "server-id",
label: "Server",
type: "number"
}, {
id: "cost-id",
label: "Shipping",
type: "number"
}],
"rows": [{
c: [{
v: "January"
}, {
v: 19,
}, {
v: 12,
}, {
v: 7, //server
}, {
v: 7 //shipping
}]
}, {
c: [{
v: "February"
}, {
v: 13
}, {
v: 1,
}, {
v: 12 //server
}, {
v: 12 //shipping
}]
}, {
c: [{
v: "March"
}, {
v: 24
}, {
v: 5
}, {
v: 11 //server
}, {
v: 11 //shipping
}
]
}]
};
chart1.options = {
"title": "Sales per month",
"colors": ['#0000FF', '#009900', '#CC0000', '#DD9900'],
"defaultColors": ['#0000FF', '#009900', '#CC0000', '#DD9900'],
"isStacked": "percent",
focusTarget: 'category',
"fill": 20,
"displayExactValues": true,
"vAxis": {
"title": "Sales unit",
"gridlines": {
"count": 10
}
},
"hAxis": {
"title": "Date"
}
};
chart1.view = {
columns: [0, 1, 2, 3, 4]
};
$scope.myChart = chart1;
});
use the series chart option to set pointSize on a specific series
the following will change the server series in the example provided...
series: {
2: {
pointSize: 8
}
}
see forked plnker...