我在画布上有一个饼图,我想在该饼的每个扇区中绘制随机点。
我有每个部门的领域。使用弧扇区
var arcsector = Math.PI * (2 * sector / total);
var startAngle = (lastend - offset) * (radius/Math.PI);
var endAngle = (lastend + arcsector - offset) * (radius/Math.PI);
var sectorAngle = arcsector * (radius/Math.PI);
var sectorArea = .5 * (sectorAngle*Math.PI/180) * (radius*radius);
如何在该区域内随机绘制点?
答案 0 :(得分:2)
简单的方法是:
您可以通过执行以下操作来创建临时弧形路径(调整以匹配您的情况)(并且无需笔划/填充):
ctx.beginPath();
ctx.moveTo(cx, cy);
ctx.arc(cx, cy, radius, startAngle, endAngle);
ctx.closePath();
然后在该弧的界限内创建随机点,或者只使用一种非常基本的方法(在大多数情况下可能足够快,除非你需要很多点) - 和<与使用基于半径的方法相比,strong> spread甚至:
var randomX = cx + radius * 2 * Math.random() - radius;
var randomY = cy + radius * 2 * Math.random() - radius;
最后点击测试:
if (ctx.isPointInPath(randomX, randomY)) {
// plot point, count etc.
}
<强> FIDDLE 强>
<强>更新强>
一种更有效的方法来生成弧形中的随机点(并将它们更均匀地展开)是直接绘制到离屏画布而不使用任何绑定检查和没有cos / sin操作,这是昂贵的,并且最后在弧形顶部复合(或使用圆弧作为剪辑)。
// create off-screen canvas
var ocanvas = document.createElement('canvas');
var octx = ocanvas.getContext('2d');
var d;
d = ocanvas.width = ocanvas.height = 300;
octx.fillStyle = '#fff';
while(count) {
var randomX = d * Math.random();
var randomY = d * Math.random();
octx.fillRect(randomX - 1, randomY - 1, 2, 2);
count--;
}
// composite random points with main arc
ctx.globalCompositeOperation = 'source-atop';
ctx.drawImage(ocanvas, 0, 0);
ctx.globalCompositeOperation = 'source-over';
可以通过让屏幕外画布仅表示弧形的边界来进一步优化。
<强> FIDDLE 强>
答案 1 :(得分:2)
饼图是圆圈的一部分,带有您的符号,从startAngle开始,到endAngle结束。
获得随机点的最简单方法是建立一个随机角度(在。之间) startAngle和endAngle)以及一个随机半径,然后你就可以看到这些线:
var randAngle = startAngle + Math.random()*( endAngle - startAngle );
var randRadius = Math.random()*radius;
var randX = centerX + randRadius * Math.cos(randAngle);
var randY = centerY + randRadius * Math.sin(randAngle);
ctx.fillRect ( randX, randY, 1, 1 ) ;
重复所需的次数!
答案 2 :(得分:0)
演示: http://jsfiddle.net/jv6nP/3/
点在边界处并不完美,因此它们的半径大于零会使它们重叠到饼图的其他部分上。这也导致他们越过黑色边界。
var can = $('#can')[0].getContext('2d'),
border=2,
x=100,
y=75,
r=60,
sRadius= 0,
leadAngle=null,
points= [],
dotRadius=2,
data = {
water:[30,'#5CC5FA'],
earth:[60,'#F0A71F'],
air:[10,'#26EDE3']
};
function reDraw(){
//making border...
can.beginPath();
can.arc(x,y,r+border,0,2*Math.PI);
can.fillStyle='black';
can.fill();
var newAngle=null;
for (var k in data) { //making piechart..
leadAngle = (2*Math.PI)*(data[k][0]/100);
newAngle = sRadius+leadAngle;
calPoints(sRadius,leadAngle,k);
can.beginPath();
can.arc(x,y,r,sRadius,newAngle);
can.lineTo(x,y);
can.fillStyle=data[k][1];
can.fill();
sRadius= newAngle;
}
//calculating points..
function calPoints(s,e,name) {
if (name!='water') return;
var py,px,rAngle,rRad;
for (var i=0; i<15; i++) {
rAngle=s+Math.random()*(e);
rRad = Math.random()*r;
px = (Math.cos(rAngle) * rRad)+x;
py = (Math.sin(rAngle) * rRad)+y;
points.push([px,py]);
}
}
//plotting dots from data...
points.forEach(function(v){
can.beginPath();
can.arc(v[0],v[1],dotRadius,0,2*Math.PI);
can.fillStyle='fff';
can.fill();
});
points=[];
requestAnimationFrame(reDraw);
}
reDraw();