绘制圆扇区中的随机点

时间:2014-05-02 14:05:29

标签: javascript canvas html5-canvas

我在画布上有一个饼图,我想在该饼的每个扇区中绘制随机点。

我有每个部门的领域。使用弧扇区

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);

如何在该区域内随机绘制点?

3 个答案:

答案 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();