locateganesh locateganesh - 6 months ago 26
jQuery Question

Radial shape in JS

I want to make this shape with javascript or jquery:

enter image description here

These dots will be dynamic and some anywhere in radial circle.
And it needs to be responsive also.

Is there any plugins for this?

Answer

enter image description here

You are drawing many circles

  • The circles showing orbits are stroked circles around a common center.
  • The circling bodies are filled circles rotated at angles around the circumference of the orbit that they are in.

Functions: an efficient way to write reusable code!

Instead of re-writing (repeating) code to draw your 2 types of circles, you can create reusable functions that take in variables specific to a circle and use those variables to draw your stroked or filled circles.

The function that strokes your orbits

The drawOrbit function takes in a radius and strokes a circle at that radius around the center point:

// cx,cy is the concentric centerpoint of your orbits -- cx,cy don't change
// radius is how far your orbit is from the centerpoint -- radius does change
function drawOrbit(radius){
    ctx.beginPath();
    ctx.arc(cx,cy,radius,0,Math.PI*2);
    ctx.stroke();    
}

The function that draws your orbital bodies (circles)

The circleInOrbit function takes in a radius and strokes a circle at that radius around the center point:

  • x,y are computed with trigonometry.
  • cx,cy is the orbit centerpoint
  • orbits[circle.orbitIndex] fetches the orbit object from the orbits array. Then the orbit object tells the function how far away from the centerpoint the orbit is.
  • Math.cos(angle) & Math.sin(angle) tells the function where on the circumference of the orbit the orbiting circle is

The drawOrbitingCircle function looks like this:

// Takes in a circle object that holds the circle's orbit & rotation angle
// It draws the orbiting circle on the specified orbit at the specified angle
function drawOrbitingCircle(circle){
    var x=cx+orbits[circle.orbitIndex]*Math.cos(circle.angle);
    var y=cy+orbits[circle.orbitIndex]*Math.sin(circle.angle);
    ctx.beginPath();
    ctx.arc(x,y,circleRadius,0,Math.PI*2);
    ctx.fillStyle='lightgray';
    ctx.fill();
    ctx.strokeStyle='white';
    ctx.stroke();
}

[Addition: show signed-center circle & prevent overlapping circles]

This function draws a blue filled circle containing your text-sign (plus):

  • Draw a blue-filled circle at the concentric point.
  • Use context.fillText('+',centerX,centerY) to draw a plus sign in the center of the blue circle.

Note that you can align text to be centered horizontally & vertically with context.textAlign = 'center' and context.textBaseline = 'middle'.

function drawSignedCenterCircle(signCharacter){
    ctx.beginPath();
    ctx.arc(cx,cy, 18, 0, 2 * Math.PI);
    ctx.fillStyle='blue';
    ctx.fill();
    ctx.fillStyle='white';
    ctx.font='24px verdana';
    ctx.textAlign='center';
    ctx.textBaseline='middle';
    ctx.fillText(signCharacter,cx,cy);
}

This code creates orbiting circles that won't overlap.

It works by giving each orbiting circle a unique slice of its orbit. Since each slice is unique, any circle won't overlap with any other circle in the same orbit.

// calculate non-overlapping placements of orbiting bodies
for(var o=0;o<orbits.length;o++){
    var count=circleCountByOrbit[o];
    var sweep=Math.PI*2/count;
    for(var c=0;c<count;c++){
        var midAngle=(sweep*c)+sweep/2;
        var randomOffset=Math.random()*0.50-1;
        var angle=midAngle+sweep*randomOffset;
        circles.push({orbitIndex:o, angle:angle});
    }
}

Example code and a Demo:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var cx=cw/2;
var cy=ch/2;
var circleRadius=10;
var orbits=[40,80,120];
var circleCountByOrbit=[3,5,7];
var circles=[];

// calculate non-overlapping placements of orbiting bodies
for(var o=0;o<orbits.length;o++){
    var count=circleCountByOrbit[o];
    var sweep=Math.PI*2/count;
    for(var c=0;c<count;c++){
        var midAngle=(sweep*c)+sweep/2;
        var randomOffset=Math.random()*0.50-1;
        var angle=midAngle+sweep*randomOffset;
        circles.push({orbitIndex:o, angle:angle});
    }
}

// draw the stroked orbits
for(var i=0;i<orbits.length;i++){
    drawOrbit(orbits[i]);
}

// draw the orbiting bodies
for(var i=0;i<circles.length;i++){
    drawOrbitingCircle(circles[i]);
}

// draw the signedCenterCircle
drawSignedCenterCircle('+');

function drawOrbit(radius){
    ctx.beginPath();
    ctx.arc(cx,cy,radius,0,Math.PI*2);
    ctx.stroke();    
}

function drawOrbitingCircle(circle){
    var x=cx+orbits[circle.orbitIndex]*Math.cos(circle.angle);
    var y=cy+orbits[circle.orbitIndex]*Math.sin(circle.angle);
    ctx.beginPath();
    ctx.arc(x,y,circleRadius,0,Math.PI*2);
    ctx.fillStyle='lightgray';
    ctx.fill();
    ctx.strokeStyle='white';
    ctx.stroke();
}

function drawSignedCenterCircle(signCharacter){
    ctx.beginPath();
    ctx.arc(cx,cy, 18, 0, 2 * Math.PI);
    ctx.fillStyle='blue';
    ctx.fill();
    ctx.fillStyle='white';
    ctx.font='24px verdana';
    ctx.textAlign='center';
    ctx.textBaseline='middle';
    ctx.fillText(signCharacter,cx,cy);
}
body{ background-color:white;padding:20px;}
#canvas{border:1px solid red; margin:0 auto; }
<canvas id="canvas" width=300 height=300></canvas>

Comments