将事件监听器添加到 SVG 条形图

时间:2021-01-27 16:40:09

标签: javascript svg

我有以下使用 SVG 绘制图表的代码

var studentexamdata = new Array();
//ID and Grade
studentexamdata[0] = "01,80";
studentexamdata[1] = "02,40";
studentexamdata[2] = "03,70";
studentexamdata[3] = "04,80";
studentexamdata[4] = "05,30";
studentexamdata[5] = "06,90";
studentexamdata[6] = "07,70";
studentexamdata[7] = "08,80";
studentexamdata[8] = "09,100";
studentexamdata[9] = "10,60";

var svg;
var svgWidth, svgHeight, svgMargin, svgSpace;
var MarginSpace, MarginHeight;
var barchartWidth, barchartMargin, totalChartBars, maximumDataValue;
var LabelOnYAxis;

function drawBarChart() {
  svg = document.getElementsByTagName('svg')[0];

  var barchart = document.getElementById('barchart');
  barchart.addEventListener('click', function() {
    clear();
    ChartSettings();
    drawAxis();
    drawChart("Bar");
  }, false);

  var pointchart = document.getElementById('pointchart');
  pointchart.addEventListener('click', function() {
    clear();
    ChartSettings();
    drawAxis();
    drawChart("Point");
  }, false);
}

function clear() {
  while (svg.lastChild) {
    svg.removeChild(svg.lastChild);
  }
}

function ChartSettings() {
  svgMargin = 20;
  svgSpace = 60;

  svgHeight = svg.height.baseVal.value - 2 * svgMargin - svgSpace;
  svgWidth = svg.width.baseVal.value - 2 * svgMargin - svgSpace;

  MarginSpace = svgMargin + svgSpace;
  MarginHeight = svgMargin + svgHeight;

  barchartMargin = 15;
  totalChartBars = studentexamdata.length;
  barchartWidth = (svgWidth / totalChartBars) - barchartMargin;

  maximumDataValue = 0;
  for (var i = 0; i < totalChartBars; i++) {
    var arrVal = studentexamdata[i].split(",");
    var barVal = parseInt(arrVal[1]);
    if (parseInt(barVal) > parseInt(maximumDataValue))
      maximumDataValue = barVal;
  }

  LabelOnYAxis = 10;
}

function drawAxis() {
  //Y-Axis
  drawXYAxis(MarginSpace, MarginHeight, MarginSpace, svgMargin);
  //X-Axis
  drawXYAxis(MarginSpace, MarginHeight, MarginSpace + barchartWidth + 500, MarginHeight);
  drawMarkers();
}

function drawXYAxis(x1, y1, x2, y2) {
  var newdataAxis = document.createElementNS("http://www.w3.org/2000/svg", 'line');
  newdataAxis.setAttribute("x1", x1);
  newdataAxis.setAttribute("y1", y1);
  newdataAxis.setAttribute("x2", x2);
  newdataAxis.setAttribute("y2", y2);
  newdataAxis.style.stroke = "black";
  newdataAxis.style.strokeWidth = "2px";
  svg.appendChild(newdataAxis);
}

function drawMarkers() {
  var numberMarkers = parseInt(maximumDataValue / LabelOnYAxis);
  for (var i = 0; i < LabelOnYAxis + 1; i++) {
    markerVal = i * numberMarkers;
    markerValHt = i * numberMarkers * svgHeight;
    var xaxisMarkers = MarginSpace - 5;
    var yaxisMarkers = MarginHeight - (markerValHt / maximumDataValue);
    textelement = document.createElementNS("http://www.w3.org/2000/svg", 'text');
    textelement.setAttribute('dx', xaxisMarkers - 40);
    textelement.setAttribute('dy', yaxisMarkers);
    txtnode = document.createTextNode(markerVal);
    textelement.appendChild(txtnode);
    svg.appendChild(textelement);
  }
  for (var i = 0; i < totalChartBars; i++) {
    arrVal = studentexamdata[i].split(",");
    name = arrVal[0];
    markerXPosition = MarginSpace + barchartMargin + (i * (barchartWidth + barchartMargin)) + (barchartWidth / 2);
    markerYPosition = MarginHeight + 20;
    textelement = document.createElementNS("http://www.w3.org/2000/svg", 'text');
    textelement.setAttribute('dx', markerXPosition);
    textelement.setAttribute('dy', markerYPosition);
    txtnode = document.createTextNode(name);
    textelement.appendChild(txtnode);
    svg.appendChild(textelement);
  }
}

function drawRectangleForChart(x, y, wd, ht, fill) {
  var rect = document.createElementNS("http://www.w3.org/2000/svg", 'rect');
  rect.setAttributeNS(null, 'x', x);
  rect.setAttributeNS(null, 'y', y);
  rect.setAttributeNS(null, 'width', wd);
  rect.setAttributeNS(null, 'height', ht);
  rect.setAttributeNS(null, 'fill', "blue");
  svg.appendChild(rect);
}

function drawEllipse(x, y, rx) {
  var circle = document.createElementNS("http://www.w3.org/2000/svg", 'circle');
  circle.setAttributeNS(null, 'cx', x);
  circle.setAttributeNS(null, 'cy', y);
  circle.setAttributeNS(null, 'r', rx);
  circle.setAttributeNS(null, 'fill', "darkred");
  svg.appendChild(circle);
}

function drawChart(chart) {
  for (var i = 0; i < totalChartBars; i++) {
    var arrchartVal = studentexamdata[i].split(",");
    bcVal = parseInt(arrchartVal[1]);
    bcHt = (bcVal * svgHeight / maximumDataValue);
    bcX = MarginSpace + (i * (barchartWidth + barchartMargin)) + barchartMargin + 10;
    bcY = (MarginHeight - bcHt - 2);
    switch (chart) {
      case "Bar":
        drawRectangleForChart(bcX, bcY, barchartWidth, bcHt, true);
        break;

      case "Point":
        drawEllipse(bcX, bcY, 5, 5);
        break;
    }
  }
}
window.onload = drawBarChart;
#chartcontainer {
  height: 250px;
  width: 400px;
  border: double;
  background-color: aliceblue;
}

#charttype {
  border: double;
  height: 75px;
  width: 100px;
}
<div id="charttype">
  <br />
  <input type="radio" id="barchart" name="Chart" />Bar Chart
  <br />
  <input type="radio" id="pointchart" name="Chart" />Point Chart
</div>
<div id="chartcontainer">
  <svg id="svgcontainer" height="250" width="400">
        </svg>
</div>

输出很好,因为:

enter image description here

我需要的是以下内容:

  1. 将 eventlistner 添加到条形图,这样一旦我将鼠标悬停在每个条形上,我就会看到一些详细信息,例如 ID 和等级
  2. 将 eventlistner 添加到条形图中,我可以通过向上或向下拖动条形顶部来更改值,即通过更改条形高度来更改等级

1 个答案:

答案 0 :(得分:0)

创建每个元素(矩形或椭圆)时,可以添加eventListener

var studentexamdata = new Array();
//ID and Grade
studentexamdata[0] = "01,80";
studentexamdata[1] = "02,40";
studentexamdata[2] = "03,70";
studentexamdata[3] = "04,80";
studentexamdata[4] = "05,30";
studentexamdata[5] = "06,90";
studentexamdata[6] = "07,70";
studentexamdata[7] = "08,80";
studentexamdata[8] = "09,100";
studentexamdata[9] = "10,60";


var svg;
var svgWidth, svgHeight, svgMargin, svgSpace;
var MarginSpace, MarginHeight;
var barchartWidth, barchartMargin, totalChartBars, maximumDataValue;
var LabelOnYAxis;

function drawBarChart() {
  svg = document.getElementsByTagName('svg')[0];

  var barchart = document.getElementById('barchart');
  barchart.addEventListener('click', function() {
    clear();
    ChartSettings();
    drawAxis();
    drawChart("Bar");
  }, false);

  var pointchart = document.getElementById('pointchart');
  pointchart.addEventListener('click', function() {
    clear();
    ChartSettings();
    drawAxis();
    drawChart("Point");
  }, false);
}

function clear() {
  while (svg.lastChild) {
    svg.removeChild(svg.lastChild);
  }
}

function ChartSettings() {
  svgMargin = 20;
  svgSpace = 60;

  svgHeight = svg.height.baseVal.value - 2 * svgMargin - svgSpace;
  svgWidth = svg.width.baseVal.value - 2 * svgMargin - svgSpace;

  MarginSpace = svgMargin + svgSpace;
  MarginHeight = svgMargin + svgHeight;

  barchartMargin = 15;
  totalChartBars = studentexamdata.length;
  barchartWidth = (svgWidth / totalChartBars) - barchartMargin;

  maximumDataValue = 0;
  for (var i = 0; i < totalChartBars; i++) {
    var arrVal = studentexamdata[i].split(",");
    var barVal = parseInt(arrVal[1]);
    if (parseInt(barVal) > parseInt(maximumDataValue))
      maximumDataValue = barVal;
  }

  LabelOnYAxis = 10;
}

function drawAxis() {
  //Y-Axis
  drawXYAxis(MarginSpace, MarginHeight, MarginSpace, svgMargin);
  //X-Axis
  drawXYAxis(MarginSpace, MarginHeight, MarginSpace + barchartWidth + 500, MarginHeight);
  drawMarkers();
}

function drawXYAxis(x1, y1, x2, y2) {
  var newdataAxis = document.createElementNS("http://www.w3.org/2000/svg", 'line');
  newdataAxis.setAttribute("x1", x1);
  newdataAxis.setAttribute("y1", y1);
  newdataAxis.setAttribute("x2", x2);
  newdataAxis.setAttribute("y2", y2);
  newdataAxis.style.stroke = "black";
  newdataAxis.style.strokeWidth = "2px";
  svg.appendChild(newdataAxis);
}

function drawMarkers() {
  var numberMarkers = parseInt(maximumDataValue / LabelOnYAxis);
  for (var i = 0; i < LabelOnYAxis + 1; i++) {
    markerVal = i * numberMarkers;
    markerValHt = i * numberMarkers * svgHeight;
    var xaxisMarkers = MarginSpace - 5;
    var yaxisMarkers = MarginHeight - (markerValHt / maximumDataValue);
    textelement = document.createElementNS("http://www.w3.org/2000/svg", 'text');
    textelement.setAttribute('dx', xaxisMarkers - 40);
    textelement.setAttribute('dy', yaxisMarkers);
    txtnode = document.createTextNode(markerVal);
    textelement.appendChild(txtnode);
    svg.appendChild(textelement);
  }
  for (var i = 0; i < totalChartBars; i++) {
    arrVal = studentexamdata[i].split(",");
    name = arrVal[0];
    markerXPosition = MarginSpace + barchartMargin + (i * (barchartWidth + barchartMargin)) + (barchartWidth / 2);
    markerYPosition = MarginHeight + 20;
    textelement = document.createElementNS("http://www.w3.org/2000/svg", 'text');
    textelement.setAttribute('dx', markerXPosition);
    textelement.setAttribute('dy', markerYPosition);
    txtnode = document.createTextNode(name);
    textelement.appendChild(txtnode);
    svg.appendChild(textelement);
  }
}

function displayInfo(info){
  let bx = document.getElementById('infoblock');
  bx.innerHTML = info;
}

function showInfo(evt, stId){
  let info = studentexamdata[stId];
  let show = `${stId} - ${info}`;
  displayInfo(show);
}

function modifyInfo(evt, stId){
  displayInfo(evt.clientY);
}

function drawRectangleForChart(stId, x, y, wd, ht, fill) {
  var rect = document.createElementNS("http://www.w3.org/2000/svg", 'rect');
  rect.setAttributeNS(null, 'x', x);
  rect.setAttributeNS(null, 'y', y);
  rect.setAttributeNS(null, 'width', wd);
  rect.setAttributeNS(null, 'height', ht);
  rect.setAttributeNS(null, 'fill', "blue");
  rect.addEventListener('mouseover', function(e){showInfo(e, stId)});
  rect.addEventListener('click', function(e){modifyInfo(e, stId)});
  svg.appendChild(rect);
}

function drawEllipse(stId, x, y, rx) {
  var circle = document.createElementNS("http://www.w3.org/2000/svg", 'circle');
  circle.setAttributeNS(null, 'cx', x);
  circle.setAttributeNS(null, 'cy', y);
  circle.setAttributeNS(null, 'r', rx);
  circle.setAttributeNS(null, 'fill', "darkred");
  circle.addEventListener('mouseover', function(e){showInfo(e, stId)});
  circle.addEventListener('click', function(e){modifyInfo(e, stId)});
  svg.appendChild(circle);
}

function drawChart(chart) {
  for (var i = 0; i < totalChartBars; i++) {
    var studentId = i;
    var arrchartVal = studentexamdata[i].split(",");
    bcVal = parseInt(arrchartVal[1]);
    bcHt = (bcVal * svgHeight / maximumDataValue);
    bcX = MarginSpace + (i * (barchartWidth + barchartMargin)) + barchartMargin + 10;
    bcY = (MarginHeight - bcHt - 2);
    switch (chart) {
      case "Bar":
        drawRectangleForChart(studentId, bcX, bcY, barchartWidth, bcHt, true);
        break;

      case "Point":
        drawEllipse(studentId, bcX, bcY, 5, 5);
        break;
    }
  }
}
window.onload = drawBarChart;
#chartcontainer {
  height: 250px;
  width: 400px;
  border: double;
  background-color: aliceblue;
}
#infoblock {
  position: fixed;
  right: 0;
  top: 0;
  background-color: aliceblue;
}

#charttype {
  border: double;
  height: 75px;
  width: 100px;
}
<div id="charttype">
  <br />
  <input type="radio" id="barchart" name="Chart" />Bar Chart
  <br />
  <input type="radio" id="pointchart" name="Chart" />Point Chart
</div>
<div id="infoblock">
</div>
<div id="chartcontainer">
  <svg id="svgcontainer" height="250" width="400">
        </svg>
</div>

一些注意事项:

  • 我添加了一个 displayInfo 函数来在右上角显示数据,您可能希望以不同的方式显示它。

  • 我没有添加拖动事件侦听器,因为它不是微不足道的。您可以看到 click 事件的工作原理。 modifyInfo 函数显示事件的 clientY 坐标。从这里开始,您需要考虑到比例和边距来处理该坐标。同样,并非微不足道,因为 svg 本身可能具有转换和/或视图框。您可以查找显示 getScreenCTM 用于此任务的示例。