使堆叠条形图可拖动 CanvasJS

Make Stacked Bar Graph Dragable CanvasJS

我想单独拖动每一列(黄油、花、牛奶、鸡蛋)并通过单击鼠标调整它们的数量。

我使用的资源是: https://canvasjs.com/javascript-charts/interactive-draggable-chart/

https://canvasjs.com/docs/charts/how-to/make-data-points-on-chart-draggable/

到目前为止,这是我的 JSFiddle:https://jsfiddle.net/mmfhq9d3/

window.onload = function () {

var chart = new CanvasJS.Chart("chartContainer", {
    animationEnabled: true,
    theme: "light2",
    title:{
        text: "Cost Of Pancake Ingredients"
    },
    axisY2:{
        prefix: "$",
        lineThickness: 0                
    },
    toolTip: {
        shared: true
    },
    legend:{
        verticalAlign: "top",
        horizontalAlign: "center"
    },
    data: [
    {     
        type: "stackedBar",
        showInLegend: true,
        name: "Butter (500gms)",
        axisYType: "secondary",
        color: "#7E8F74",
        dataPoints: [
            { y: 3, label: "India" },
            { y: 5, label: "US" },
            { y: 3, label: "Germany" },
            { y: 6, label: "Brazil" },
            { y: 7, label: "China" }
        ]
    },
    {
        type: "stackedBar",
        showInLegend: true,
        name: "Flour (1kg)",
        axisYType: "secondary",
        color: "#F0D6A7",
        dataPoints: [
            { y: .5, label: "India" },
            { y: 1.5, label: "US" },
            { y: 1, label: "Germany" },
            { y: 2, label: "Brazil" },
            { y: 2, label: "China" }
        ]
    },
    {
        type: "stackedBar",
        showInLegend: true,
        name: "Milk (2l)",
        axisYType: "secondary",
        color: "#EBB88A",
        dataPoints: [
            { y: 2, label: "India" },
            { y: 3, label: "US" },
            { y: 3, label: "Germany" },
            { y: 3, label: "Brazil" },
            { y: 4, label: "China" }
            ]
    },
    {
        type: "stackedBar",
        showInLegend: true,
        name: "Eggs (20)",
        axisYType: "secondary",
        color:"#DB9079",
        indexLabel: "$#total",
        dataPoints: [
            { y: 2, label: "India" },
            { y: 3, label: "US" },
            { y: 6, label: "Germany"},
            { y: 4, label: "Brazil" },
            { y: 4, label: "China" }
        ]
    }
    ]
});

chart.render();

var xSnapDistance = chart.axisX[0].convertPixelToValue(chart.get("dataPointWidth")) / 2;
var ySnapDistance = 3;

var xValue, yValue;

var mouseDown = false;
var selected = null;
var changeCursor = false;

var timerId = null;

function getPosition(e) {
    var parentOffset = $("#chartContainer > .canvasjs-chart-container").offset();           
    var relX = e.pageX - parentOffset.left;
    var relY = e.pageY - parentOffset.top;
    xValue = Math.round(chart.axisX[0].convertPixelToValue(relX));
    yValue = Math.round(chart.axisY[0].convertPixelToValue(relY));
}

function searchDataPoint() {
    var dps = chart.data[0].dataPoints;
    for(var i = 0; i < dps.length; i++ ) {
        if( (xValue >= dps[i].x - xSnapDistance && xValue <= dps[i].x + xSnapDistance) && (yValue >= dps[i].y - ySnapDistance && yValue <= dps[i].y + ySnapDistance) ) 
        {
            if(mouseDown) {
                selected = i;
                break;
            } else {
                changeCursor = true;
                break; 
            }
        } else {
            selected = null;
            changeCursor = false;
        }
    }
}

jQuery("#chartContainer > .canvasjs-chart-container").on({
    mousedown: function(e) {
        mouseDown = true;
        getPosition(e);  
        searchDataPoint();
    },
    mousemove: function(e) {
        getPosition(e);
        if(mouseDown) {
            clearTimeout(timerId);
            timerId = setTimeout(function(){
                if(selected != null) {
                    chart.data[0].dataPoints[selected].y = yValue;
                    chart.render();
                }   
            }, 0);
        }
        else {
            searchDataPoint();
            if(changeCursor) {
                chart.data[0].set("cursor", "n-resize");
            } else {
                chart.data[0].set("cursor", "default");
            }
        }
    },
    mouseup: function(e) {
        if(selected != null) {
            chart.data[0].dataPoints[selected].y = yValue;
            chart.render();
            mouseDown = false;
        }
    }
});

}

非常感谢任何帮助!

这里是一个可拖动堆叠条形图的示例,可以开始使用。

var chart = new CanvasJS.Chart("chartContainer", {
  animationEnabled: true,
  title: {
    text: "Try Dragging Any Bar to Resize"
  },
  axisX: {
    minimum: 5,
    maximum: 95
  },
  data: [{
  type: "stackedBar",
  dataPoints: [
   { x: 10, y: 71 },
   { x: 20, y: 55 },
   { x: 30, y: 50 },
   { x: 40, y: 65 },
   { x: 50, y: 95 },
   { x: 60, y: 68 },
   { x: 70, y: 28 },
   { x: 80, y: 34 },
   { x: 90, y: 14 }
  ]
 },{
  type: "stackedBar",
  dataPoints: [
   { x: 10, y: 71 },
   { x: 20, y: 55 },
   { x: 30, y: 50 },
   { x: 40, y: 65 },
   { x: 50, y: 95 },
   { x: 60, y: 68 },
   { x: 70, y: 28 },
   { x: 80, y: 34 },
   { x: 90, y: 14 }
  ]
 },{
  type: "stackedBar",
  dataPoints: [
   { x: 10, y: 71 },
   { x: 20, y: 55 },
   { x: 30, y: 50 },
   { x: 40, y: 65 },
   { x: 50, y: 95 },
   { x: 60, y: 68 },
   { x: 70, y: 28 },
   { x: 80, y: 34 },
   { x: 90, y: 14 }
  ]
 }]
});
chart.render();



var xSnapDistance = 2;
var ySnapDistance = 5;

var xValue, yValue;

var mouseDown = false;
var selectedDataSeries = null;
var selectedDataPointX = null;
var selectedDatapointIndex = null;
var selectedSumIndex = null;
var changeCursor = false;
var timerId = null;
var chartType = "stackedBar";


function getPosition(e) {
  var parentOffset = $("#chartContainer > .canvasjs-chart-container").offset();
  var relX = e.pageX - parentOffset.left;
  var relY = e.pageY - parentOffset.top;
  xValue = Math.round(chart.axisX[0].convertPixelToValue(relY));
  yValue = Math.round(chart.axisY[0].convertPixelToValue(relX));
}

function searchDataPoint(stackedValues) {
  for (x in stackedValues) {
    if (stackedValues.hasOwnProperty(x) && (xValue >= Number(x) - xSnapDistance && xValue <= Number(x) + xSnapDistance)) {
      for (var i = 0; i < stackedValues[x].length; i++)
        if (yValue >= stackedValues[x][i].stackedSum - ySnapDistance && yValue <= stackedValues[x][i].stackedSum + ySnapDistance) {
          if (mouseDown) {
            selectedDataPointX = x;
            selectedDataSeries = stackedValues[x][i].dataSeries;
            selectedDatapointIndex = stackedValues[x][i].dataPointIndex;
            selectedSumIndex = i;
            return;
          } else {
            changeCursor = true;
            return;
          }
        }
    } else {
      selectedDataPointX = null;
      selectedDataSeries = null;
      selectedDatapointIndex = null;
      selectedSumIndex = null;
      changeCursor = false;
    }
  }
}

function sumUpStacked(data, type) {
  var stackedSums = {};
  for (var i = 0; i < data.length; i++) {
    if (data[i].type === type) {
      var dataSeries = data[i].dataPoints;
      for (var j = 0; j < dataSeries.length; j++) {

        if (stackedSums[dataSeries[j].x]) {
          var slectedStackSums = stackedSums[dataSeries[j].x];
          slectedStackSums.push({
            dataSeries: dataSeries,
            dataPointIndex: j,
            stackedSum: slectedStackSums[slectedStackSums.length - 1].stackedSum + dataSeries[j].y
          });
        } else {
          stackedSums[dataSeries[j].x] = [{
            dataSeries: dataSeries,
            dataPointIndex: j,
            stackedSum: dataSeries[j].y
          }]
        }

      }
    }
  }
  return stackedSums;
}


$("#chartContainer > .canvasjs-chart-container").on({
  mousedown: function(e) {
    mouseDown = true;
    getPosition(e);
    var stackedSums = sumUpStacked(chart.data, chartType);
    searchDataPoint(stackedSums);
  },
  
  mousemove: function(e) {
    getPosition(e);
    if (mouseDown) {
      clearTimeout(timerId);
      var stackedSums = sumUpStacked(chart.data, chartType);
      timerId = setTimeout(function() {
        if (selectedDataSeries != null) {
          if (selectedSumIndex === 0)
            selectedDataSeries[selectedDatapointIndex].y = yValue;
          else
            selectedDataSeries[selectedDatapointIndex].y = yValue - stackedSums[selectedDataPointX][selectedSumIndex - 1].stackedSum;
          chart.render();
        }
      }, 0);
    } else {
      searchDataPoint(sumUpStacked(chart.data, chartType));
      if (changeCursor) {
        for (var i = 0; i < chart.data.length; i++)
          chart.options.data[i].cursor = "n-resize";
      } else {
        for (var i = 0; i < chart.data.length; i++)
          chart.options.data[i].cursor = "default";
      }
      chart.render();
    }
  },
  
  mouseup: function(e) {
    var stackedSums = sumUpStacked(chart.data, chartType);
    if (selectedDataSeries != null) {
      if (selectedSumIndex === 0)
        selectedDataSeries[selectedDatapointIndex].y = yValue;
      else
        selectedDataSeries[selectedDatapointIndex].y = yValue - stackedSums[selectedDataPointX][selectedSumIndex - 1].stackedSum;
      chart.render();
    }
    mouseDown = false;
  }
});
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>

<div id="chartContainer" style="height: 360px; width: 100%;"></div>