Amcharts Serial chart with drag and drop functionality
Posted By : Satwinder Singh | 06-Nov-2017
Amcharts:- Serial chart with drag and drop functionality
To add drag and drop functionality to chart, we need to setup
Steps to setup
1. Firstly download amCharts from https://www.amcharts.com/download/
2. Then create a simple
<div id="chartdiv"></div>
- In the head section of our page, we will need to reference amCharts javascript and
css library:-
<script src="https://www.amcharts.com/lib/3/amcharts.js"></script>
<script src="https://www.amcharts.com/lib/3/serial.js"></script>
<script src="https://www.amcharts.com/lib/3/plugins/export/export.min.js"></script>
<link rel="stylesheet" href="https://www.amcharts.com/lib/3/plugins/export/export.css" type="text/css" media="all" />
<script src="https://www.amcharts.com/lib/3/themes/light.js"></script>
- Now we will create a serial chart with some dummy data values using
following function:-
var chart = AmCharts.makeChart("chartdiv", {
"type": "serial",
"titles": [{ "text": "Staffing Level Chart" }],
"theme": "light",
"addClassNames": true,
"autoMarginOffset": 25,
"chartCursor": {
"cursorPosition": "mouse",
"bulletsEnabled": true,
"graphBulletAlpha": 1,
"cursorAlpha": 0.3,
"valueLineEnabled": false,
"valueLineAlpha": 0.5,
"zoomable": false,
},
"categoryField": "time",
"categoryAxis": {
"gridPosition": "start",
"tickPosition": "middle",
"parseDates": false,
"gridAlpha": 0,
" title": "Hours",
"autoGridCount": true,
},
"dataProvider": [{
"time": "1",
"value3": 15,
"value2": 13,
"value1": 13,
"value4": 0,
"value5": 0,
"value6": 0,
"lineColor1": "transparent",
"lineColor3": "transparent",
"value8": 0
}, {
"time": "2",
"value3": 15,
"value2": 13,
"value1": 13,
"value4": 0,
"value5": 0,
"value6": 0,
"lineColor1": "transparent",
"lineColor3": "transparent",
"value8": 0
}, {
"time": "3",
"value3": 30,
"value2": 13,
"value1": 15,
"value4": -4,
"value5": 0,
"value6": -4,
"lineColor1": "transparent",
"lineColor3": "transparent",
"value8": 0
}, {
"time": "4",
"value3": 30,
"value2": 13,
"value1": 15,
"value4": -4,
"value5": 0,
"value6": -8,
"lineColor1": "transparent",
"lineColor3": "transparent",
"value8": 0
}, {
"time": "5",
"value3": 30,
"value2": 23,
"value1": 15,
"value4": -4,
"value5": 0,
"value6": -8,
"start": 2,
"bulletPosition": "middle",
"value7": 7,
"opacity": 1,
"lineColor1": "transparent",
"lineColor3": "#9c1003",
"value8": 0
}, {
"time": "6",
"value3": 30,
"value2": 23,
"value1": 15,
"value4": -4,
"value5": 0,
"value6": -8,
"start": 2,
"value8": 0,
"lineColor1": "transparent",
"lineColor3": "#9c1003"
}, {
"time": "7",
"value3": 30,
"value2": 23,
"value1": 21,
"value4": -4,
"value5": -4,
"value6": -8,
"start": 2,
"value8": 0,
"lineColor1": "transparent",
"lineColor3": "#9c1003"
}, {
"time": "8",
"value3": 30,
"value2": 23,
"value1": 33,
"value4": -4,
"value5": -4,
"value6": -8,
"start": 2,
"value8": 0,
"lineColor1": "#e3da7d",
"lineColor3": "transparent"
}, {
"time": "9",
"value3": 30,
"value2": 18,
"value1": 33,
"value4": -4,
"value5": -4,
"value6": -8,
"start": 2,
"value8": 0,
"lineColor1": "#e3da7d",
"lineColor3": "transparent"
}, {
"time": "10",
"value3": 30,
"value2": 18,
"value1": 33,
"value4": -4,
"value5": -4,
"value6": 0,
"start": 2,
"value8": 0,
"lineColor1": "#e3da7d",
"lineColor3": "transparent"
}, {
"time": "11",
"value3": 15,
"value2": 18,
"value1": 33,
"value4": 0,
"value5": 0,
"value6": 0,
"lineColor1": "#e3da7d",
"lineColor3": "transparent",
"value8": 0
}, {
"time": "12",
"value3": 15,
"value2": 5,
"value1": 33,
"value4": 0,
"value5": 0,
"value6": 0,
"lineColor1": "#e3da7d",
"lineColor3": "transparent",
"value8": 0
}, {
"time": "13",
"value3": 5,
"value2": 5,
"value1": 33,
"value4": 0,
"value5": 0,
"value6": 0,
"lineColor1": "#e3da7d",
"lineColor3": "transparent",
"value8": 0
}, {
"time": "14",
"value3": 5,
"value2": 5,
"value1": 20,
"value4": 0,
"value5": 0,
"value6": 0,
"lineColor1": "#e3da7d",
"lineColor3": "transparent",
"value8": 0
}, {
"time": "15",
"value3": 5,
"value2": 5,
"value1": 5,
"value4": 0,
"value5": 0,
"value6": 0,
"lineColor1": "#e3da7d",
"lineColor3": "transparent",
"value8": 0
}],
"valueAxes": [{
"axisAlpha": 0,
"position": "left",
}],
"graphs": [
{
"id": "g1",
"type": "step",
"balloonColor": "transparent",
"bullet": "square",
"bulletAlpha": 0,
"bulletSize": 2,
"bulletBorderAlpha": 0,
"valueField": "value1",
"lineThickness": 2,
"fillColorsField": "lineColor1",
"fillAlphas": 1,
"lineColorField": "#e3da7d",
"fillToGraph": "g3",
"showHandOnHover": true,
"pointPosition": "middle",
},
{
"id": "g2",
"type": "step",
"lineThickness": 2,
"balloonColor": "transparent",
"bullet": "square",
"bulletAlpha": 0,
"bulletSize": 4,
"bulletBorderAlpha": 0,
"valueField": "value2",
"fillColors": "#9c1003",
"lineColor": "#577c1d",
"lineThickness": 2,
"fillAlphas": 1,
"fillColorsField": "lineColor3",
"fillToGraph": "g1",
"showHandOnHover": true,
"pointPosition": "middle",
},
{
"id": "g3",
"type": "step",
"lineThickness": 2,
"balloonColor": "transparent",
"bullet": "square",
"bulletAlpha": 0,
"bulletSize": 4,
"bulletBorderAlpha": 0,
"valueField": "value3",
"lineColor": "#e14972",
"lineThickness": 2,
"fillColors": "#fff",
"showHandOnHover": true,
"pointPosition": "middle",
},
{
"id": "g4",
"type": "step",
"lineThickness": 2,
"showBalloon": false,
"bullet": "square",
"bulletAlpha": 0,
"bulletSize": 4,
"bulletBorderAlpha": 0,
"valueField": "value4",
"showHandOnHover": true,
"pointPosition": "middle",
},
{
"id": "g5",
"type": "step",
"lineThickness": 2,
"showBalloon": false,
"bullet": "square",
"bulletAlpha": 0,
"bulletSize": 4,
"bulletBorderAlpha": 0,
"valueField": "value5",
"showHandOnHover": true,
"pointPosition": "middle",
},
{
"id": "g6",
"type": "step",
"lineThickness": 2,
"showBalloon": false,
"bullet": "square",
"bulletAlpha": 0,
"bulletSize": 4,
"bulletBorderAlpha": 0,
"valueField": "value6",
"showHandOnHover": true,
"pointPosition": "middle",
},
{
"id": "g7",
"type": "column",
"openField": "start",
"lineThickness": 2,
"lineColor": "#000",
"lineAlpha": "opacity",
"showBalloon": true,
"bullet": "square",
"bulletAlpha": 0,
"bulletSize": 4,
"bulletBorderAlpha": 0,
"fillAlphas": 1,
"showHandOnHover": false,
"valueField": "value7",
"rotate": true,
"columnWidth": 1,
"patternField": "pattern",
"pointPosition": "end",
"pattern": {
"url": "https://www.amcharts.com/lib/3/patterns/black/pattern1.png",
"width": 4,
"height": 4
}
},
{
"id": "g8",
"type": "step",
"lineThickness": 2,
"showBalloon": false,
"bullet": "square",
"bulletAlpha": 0,
"bulletSize": 4,
"bulletBorderAlpha": 0,
"valueField": "value8",
"showHandOnHover": true,
"lineAlpha": 1,
"lineColor": "#fff"
},
],
"listeners": [{
"event": "clickGraphItem",
"method": function (event) {
graphIndex = event.target.index;
bulletIndex = event.index;
mousePosition = chart.chartCursor.mouseX;
},
}],
});
Now we will add rendered event to chart using addListener method of
chart.addListener("rendered", function (event) {
var moveLeft = true,
moveRight = true,
mouseChange = false,
currPosition;
var categoryWidth = chart.graphs[6].columnsArray[0].column.w;
var dataArray = [];
for (i = 0; i < chart.categoryAxis.allLabels.length; i++) {
dataArray.push(Math.round(chart.categoryAxis.allLabels[i].x));
}
console.log(dataArray);
chart.chartCursor.addListener("moved", function (event) {
var columnStart = chart.graphs[6].columnsArray[0].column.set.x,
columnEnd = chart.graphs[6].columnsArray[0].column.set.x + chart.graphs[6].columnsArray[0].column.w;
if (chart.chartCursor.mouseX >= columnStart && chart.chartCursor.mouseX <= columnStart + 5 || chart.chartCursor.mouseX <= columnEnd && chart.chartCursor.mouseX >= columnEnd - 5) {
$(".amcharts-graph-column.amcharts-graph-g7").css("cursor", "pointer");
}
else if (chart.chartCursor.mouseX > columnStart + 5 && chart.chartCursor.mouseX < columnEnd - 5) {
$(".amcharts-graph-column.amcharts-graph-g7").css("cursor", "move")
}
if (dataArray.indexOf(chart.chartCursor.mouseX) > -1) {
mouseChange = true;
}
else {
mouseChange = false;
}
/**
* ChartCursor and its value line must be enabled for this to work
*/
if (chart.chartCursor === undefined ||
chart.chartCursor.valueLineAxis === undefined)
return;
/**
* Add generic mouse events
*/
chart.mouseIsDown = false;
chart.mouseTimeout;
document.body.onmousedown = function () {
chart.mouseIsDown = true;
currPosition = chart.chartCursor.mouseX;
if (chart.chartCursor.mouseX >= columnStart && chart.chartCursor.mouseX <= columnStart + 5) {
stretchGraph = 0;
// 0 for cursor at the column begining
}
else if (chart.chartCursor.mouseX > columnStart + 5 && chart.chartCursor.mouseX < columnEnd - 5) {
stretchGraph = 1;
// 1 for cursor in the column center
}
else if (chart.chartCursor.mouseX <= columnEnd && chart.chartCursor.mouseX >= columnEnd - 5) {
stretchGraph = 2;
// 2 for cursor in the column end
}
}
});
document.body.onmousemove = function () {
if (chart.chartCursor.mouseX < mousePosition) {
moveLeft = true;
}
else if (chart.chartCursor.mouseX > mousePosition) {
moveLeft = false;
}
if (graphIndex == undefined) {
return;
}
if (chart.mouseIsDown && graphIndex !== 6) {
updatePosition();
}
else if (chart.mouseIsDown && graphIndex == 6) {
dragGraph();
}
}
document.body.onmouseup = function () {
chart.mouseIsDown = false;
graphIndex = undefined;
mousePosition = undefined;
}
/**
* Add click event for plot area
*/
function updatePosition() {
// click outside plot area
if (chart.chartCursor.index === undefined)
return;
// get index of the category clicked
var index = chart.chartCursor.index;
// get value clicked
var value = chart.chartCursor.valueLineAxis.coordinateToValue(chart.chartCursor.mouseY);
// round the value
value = Math.round(value);
// update data
chart.dataProvider[bulletIndex][chart.graphs[graphIndex].valueField] = value;
chart.validateData();
};
var count = 0;
function dragGraph() {
// click outside plot area
var graphStart = chart.graphs[6].columnsArray[0].column.set.x,
graphEnd = chart.graphs[6].columnsArray[0].column.set.x + chart.graphs[6].columnsArray[0].column.w;
var condition = chart.graphs[6].pointPosition === "end" ? "middle" : "end";
var index;
if (chart.chartCursor.index === undefined)
return;
for (i = 0; i < chart.dataProvider.length; i++) {
if (chart.dataProvider[i].value7 == 7) {
index = i;
}
}
// get index of the category clicked
dragIndex = chart.chartCursor.categoryLineAxis.coordinateToValue(chart.chartCursor.mouseX);
// get value clicked
dragIndex = Math.round(dragIndex);
// round the value
if (stretchGraph == 1) {
delete chart.dataProvider[index].value7;
chart.dataProvider[dragIndex][chart.graphs[graphIndex].valueField] = 7;
chart.dataProvider[dragIndex][chart.graphs[graphIndex].openField] = 2;
chart.validateData();
// update data
}
else if (stretchGraph == 0) {
if (moveLeft == true && chart.graphs[6].columnWidth < 6) {
if (count == 0) {
chart.graphs[6].columnWidth += 1;
chart.graphs[6].pointPosition = condition;
count++;
} else if (count == 1) {
delete chart.dataProvider[index].value7;
chart.graphs[6].columnWidth += 1;
chart.dataProvider[index - 1].value7 = 7;
chart.dataProvider[index - 1].start = 2;
chart.graphs[6].pointPosition = condition;
count--;
}
chart.validateData();
}
else if (moveLeft == false && chart.graphs[6].columnWidth > 1) {
if (count == 0 && chart.graphs[6].pointPosition == "middle") {
chart.graphs[6].columnWidth -= 1;
chart.graphs[6].pointPosition = condition;
count++;
}
else if (count == 1 && chart.graphs[6].pointPosition == "end") {
delete chart.dataProvider[index].value7;
chart.graphs[6].columnWidth -= 1;
chart.dataProvider[index + 1].value7 = 7;
chart.dataProvider[index + 1].start = 2;
chart.graphs[6].pointPosition = condition;
count--;
}
else if (count == 0 && chart.graphs[6].pointPosition == "end") {
delete chart.dataProvider[index].value7;
chart.graphs[6].columnWidth -= 1;
chart.dataProvider[index + 1].value7 = 7;
chart.dataProvider[index + 1].start = 2;
chart.graphs[6].pointPosition = condition;
count++;
}
else if (count == 1 && chart.graphs[6].pointPosition == "middle") {
chart.graphs[6].columnWidth -= 1;
chart.graphs[6].pointPosition = condition;
count--;
}
chart.validateData();
}
}
else if (stretchGraph == 2) {
if (moveLeft == false && chart.graphs[6].columnWidth < 6) {
if (count == 0 && chart.graphs[6].pointPosition == "end") {
delete chart.dataProvider[index].value7;
chart.graphs[6].columnWidth += 1;
chart.dataProvider[index + 1].value7 = 7;
chart.dataProvider[index + 1].start = 2;
chart.graphs[6].pointPosition = condition;
count++;
}
else if (count == 1 && chart.graphs[6].pointPosition == "middle") {
chart.graphs[6].columnWidth += 1;
chart.graphs[6].pointPosition = condition;
count--;
}
else if (count == 0 && chart.graphs[6].pointPosition == "middle") {
chart.graphs[6].columnWidth += 1;
chart.graphs[6].pointPosition = condition;
count++;
}
else if (count == 1 && chart.graphs[6].pointPosition == "end") {
delete chart.dataProvider[index].value7;
chart.graphs[6].columnWidth += 1;
chart.dataProvider[index + 1].value7 = 7;
chart.dataProvider[index + 1].start = 2;
chart.graphs[6].pointPosition = condition;
count--;
}
chart.validateData();
}
else if (moveLeft == true && chart.graphs[6].columnWidth > 1) {
if (count == 0 && chart.graphs[6].pointPosition == "end") {
chart.graphs[6].columnWidth -= 1;
chart.graphs[6].pointPosition = condition;
count++;
}
else if (count == 1 && chart.graphs[6].pointPosition == "middle") {
delete chart.dataProvider[index].value7;
chart.graphs[6].columnWidth -= 1;
chart.graphs[6].pointPosition = condition;
chart.dataProvider[index - 1].value7 = 7;
chart.dataProvider[index - 1].start = 2;
count--;
}
else if (count == 0 && chart.graphs[6].pointPosition == "middle") {
delete chart.dataProvider[index].value7;
chart.graphs[6].columnWidth -= 1;
chart.graphs[6].pointPosition = condition;
chart.dataProvider[index - 1].value7 = 7;
chart.dataProvider[index - 1].start = 2;
count++;
}
else if (count == 1 && chart.graphs[6].pointPosition == "end") {
chart.graphs[6].columnWidth -= 1;
chart.graphs[6].pointPosition = condition;
count--;
}
chart.validateData();
}
}
};
});
chart.addListener("dataUpdated", function (event) {
var Array0 = [],
Array1 = [],
Array2 = [];
for (i = 0; i < chart.graphs[0].allBullets.length; i++) {
Array0.push(chart.graphs[0].allBullets[i].y)
}
for (j = 0; j < chart.graphs[2].allBullets.length; j++) {
Array2.push(chart.graphs[2].allBullets[j].y)
}
for (k = 0; k < chart.graphs[1].allBullets.length; k++) {
Array1.push(chart.graphs[1].allBullets[k].y)
}
for (m = 0; m < 15; m++) {
if (Array2[m] > Array0[m]) {
chart.dataProvider[m].lineColor1 = "#e3da7d";
}
else {
chart.dataProvider[m].lineColor1 = "transparent";
}
}
for (n = 0; n < 15; n++) {
if (Array1[n] < Array0[n]) {
chart.dataProvider[n].lineColor3 = "#9c1003";
}
else {
chart.dataProvider[n].lineColor3 = "transparent";
}
}
});
Some styles are also added to show some creativity during drag and
<style>
#chartdiv {
width: 100%;
height: 500px;
margin: 0 auto;
}
.amcharts-graph-bullet {
cursor: pointer;
}
.amcharts-graph-column.amcharts-graph-g7 {
cursor: move;
}
</style>
Cookies are important to the proper functioning of a site. To improve your experience, we use cookies to remember log-in details and provide secure log-in, collect statistics to optimize site functionality, and deliver content tailored to your interests. Click Agree and Proceed to accept cookies and go directly to the site or click on View Cookie Settings to see detailed descriptions of the types of cookies and choose whether to accept certain cookies while on the site.
About Author
Satwinder Singh
Satwinder had been working as a free-lancer for past 1-year and recently joined Oodles Technologies as a UI-Developer. His skills are : Jquery , Html , Css , Bootstrap and Javascript.