2015-03-13 52 views

回答

2

饼图段是一个真正的楔。你有几种方法来测试一个楔子。

一种方法是数学方法:

  • 测试鼠标是否由楔形创建一个圆的半径之内。

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

  • 将该角度与每个楔块进行比较。如果角度在特定楔形弧的起始角度和结束角度之间,则鼠标位于该楔形内。

另一种方法是使用内置的路径命中测试方法画布: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>