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 amchart first:-

 

Steps to setup amchart :-

1. Firstly download amCharts from https://www.amcharts.com/download/

 

2. Then create a simple html file to add chart div in body :-

<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 amchart:-

Rendered method is always dispatched when the chart is build. this method is called every time user drags the mouse over graph and updates new points in the graph. We used this method to get new cursor positions on graph along x and y axis.

 

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 drop :-

<style>

#chartdiv {

width: 100%;

height: 500px;

margin: 0 auto;

}

 

.amcharts-graph-bullet {

cursor: pointer;

}

 

.amcharts-graph-column.amcharts-graph-g7 {

cursor: move;

}

</style>

 

 

About Author

Author Image
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.

Request for Proposal

Name is required

Comment is required

Sending message..