【问题标题】:How do i bind onclick event to piechart segment?如何将 onclick 事件绑定到饼图段?
【发布时间】:2015-03-14 03:52:25
【问题描述】:

如何将 onclick 事件绑定到饼图段?

https://github.com/sauminkirve/HTML5/blob/master/PieChart/piechart.html

【问题讨论】:

  • 不清楚你在问什么。请详细说明您尝试实现的目标,在问题本身中包含相关代码 - 如果可能,设置一个小提琴(或使用内置的实时代码生成器)来显示您需要修复的部分。

标签: html5-canvas


【解决方案1】:

饼图段实际上是一个楔形。你有几种方法来测试挖起杆。

一种方法是数学方法:

  • 测试鼠标是否在楔子创建的圆的半径内。

  • 如果半径测试为真,则计算鼠标相对于圆中心点的角度。

  • 将该角度与每个楔形进行比较。如果角度介于特定楔形圆弧的起始角和终止角之间,则鼠标位于该楔形内部。

另一种方法是使用canvas内置的路径命中测试方法:isPointInPath

  • 重新定义一个楔形。没有必要实际抚摸或填充那个楔子。只需执行从beginPathclosePath 的命令即可。

  • 使用context.isPointInPath(mouseX,mouseY) 来测试鼠标是否在那个楔子内。

  • 如果 isPointInPath 返回 true,则您已发现鼠标下方的楔形。如果不是,则重新定义并命中测试其他每个楔子。

这是我不久前编写的代码,它在悬停时对饼图的楔形进行命中测试,并在单击楔形时将楔形移出饼形。

它使用isPointInPath 方法进行命中测试:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.lineJoin = "round";

var $canvas = $("#canvas");
var canvasOffset = $canvas.offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var scrollX = $canvas.scrollLeft();
var scrollY = $canvas.scrollTop();

function Wedge(cx, cy, radius, startAngleDeg, endAngleDeg, fill, stroke, linewidth) {
  this.cx = cx;
  this.cy = cy;
  this.radius = radius;
  this.startAngle = startAngleDeg * Math.PI / 180;
  this.endAngle = endAngleDeg * Math.PI / 180;
  this.fill = fill;
  this.stroke = stroke;
  this.lineWidth = linewidth;
  this.offsetX = 0;
  this.offsetY = 0;
  this.rr = radius * radius;


  this.centerX = cx;
  this.centerY = cy;

  this.midAngle = this.startAngle + (this.endAngle - this.startAngle) / 2;
  this.offsetDistance = 15;
  this.explodeX = this.offsetDistance * Math.cos(this.midAngle);
  this.explodeY = this.offsetDistance * Math.sin(this.midAngle);
  this.isExploded = false;



};
Wedge.prototype.draw = function(fill, stroke) {
  this.define();
  this.fillStroke(fill, stroke);
  ctx.beginPath();
  ctx.arc(this.cx, this.cy, this.radius, 0, Math.PI * 2);
  ctx.closePath();
  ctx.lineWidth = 0.50;
  ctx.stroke();
}
Wedge.prototype.fillStroke = function(fill, stroke) {
  ctx.fillStyle = fill || this.fill;
  ctx.fill();
  ctx.strokeStyle = stroke, this.stroke;
  ctx.lineWidth = this.lineWidth;
  ctx.stroke();
}
Wedge.prototype.define = function() {
  var x = this.cx + this.offsetX;
  var y = this.cy + this.offsetY;
  ctx.beginPath();
  ctx.arc(x, y, this.radius, this.startAngle, this.endAngle);
  ctx.lineTo(x, y);
  ctx.closePath();
}
Wedge.prototype.ptAtAngle = function(radianAngle) {
  var xx = (this.cx + this.offsetX) + this.radius * Math.cos(radianAngle);
  var yy = (this.cy + this.offsetY) + this.radius * Math.sin(radianAngle);
  return ({
    x: x,
    y: y
  });
}
Wedge.prototype.explode = function(isExploded) {
  this.isExploded = isExploded;
  this.offsetX = isExploded ? this.explodeX : 0;
  this.offsetY = isExploded ? this.explodeY : 0;
  this.draw();
}
Wedge.prototype.isPointInside = function(x, y) {
  var dx = x - (this.cx + this.offsetX);
  var dy = y - (this.cy + this.offsetY);
  if (dx * dx + dy * dy > this.rr) {
    return (false);
  }
  var angle = (Math.atan2(dy, dx) + Math.PI * 2) % (Math.PI * 2);
  return (angle >= this.startAngle && angle <= this.endAngle);
}
Wedge.prototype.marker = function(pos) {
  ctx.beginPath();
  ctx.arc(pos.x, pos.y, 3, 0, Math.PI * 2);
  ctx.closePath();
  ctx.fillStyle = "red";
  ctx.fill();
}


function handleMouseDown(e) {
  e.preventDefault();
  mouseX = parseInt(e.clientX - offsetX);
  mouseY = parseInt(e.clientY - offsetY);

  clear();
  for (var i = 0; i < wedges.length; i++) {
    var wedge = wedges[i].wedge;
    if (wedge.isPointInside(mouseX, mouseY)) {
      wedge.explode(!wedge.isExploded);
    }
    wedge.draw();
  }
}

function handleMouseUp(e) {
  e.preventDefault();
  mouseX = parseInt(e.clientX - offsetX);
  mouseY = parseInt(e.clientY - offsetY);

  // Put your mouseup stuff here
  isDown = false;
}

function handleMouseOut(e) {
  e.preventDefault();
  mouseX = parseInt(e.clientX - offsetX);
  mouseY = parseInt(e.clientY - offsetY);

  // Put your mouseOut stuff here
  isDown = false;
}

function handleMouseMove(e) {
  e.preventDefault();
  mouseX = parseInt(e.clientX - offsetX);
  mouseY = parseInt(e.clientY - offsetY);

  for (var i = 0; i < wedges.length; i++) {
    var wedge = wedges[i].wedge;
    if (wedge.isPointInside(mouseX, mouseY)) {
      wedge.draw("black");
    } else {
      wedge.draw();
    }
  }


}

$("#canvas").mousedown(function(e) {
  handleMouseDown(e);
});
$("#canvas").mousemove(function(e) {
  handleMouseMove(e);
});
$("#canvas").mouseup(function(e) {
  handleMouseUp(e);
});
$("#canvas").mouseout(function(e) {
  handleMouseOut(e);
});

function clear() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
}

var PI2 = Math.PI * 2;
var cx = 150;
var cy = 150;
var r = 100;
var line = 2;
var stroke = "black";
var wedges = [];
wedges.push({
  percent: 18,
  fill: "red"
});
wedges.push({
  percent: 30,
  fill: "blue"
});
wedges.push({
  percent: 25,
  fill: "green"
});
wedges.push({
  percent: 13,
  fill: "purple"
});
wedges.push({
  percent: 14,
  fill: "gold"
});
var rAngle = 0;
for (var i = 0; i < wedges.length; i++) {
  var wedge = wedges[i];
  var angle = 360 * wedge.percent / 100;
  wedge.wedge = new Wedge(cx, cy, r, rAngle, rAngle + angle, wedge.fill, "black", 1);
  wedge.wedge.draw();
  rAngle += angle;
}

window.onscroll = function(e) {
  var BB = canvas.getBoundingClientRect();
  offsetX = BB.left;
  offsetY = BB.top;
}
body {
  background-color: ivory;
}
#canvas {
  border: 1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Hover wedge to highlight it<br>Click wedge to explode that wedge</h4>
<canvas id="canvas" width=300 height=300></canvas>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-20
    • 1970-01-01
    • 2010-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多