Home > Back-end >  discord/js and angle of arc function
discord/js and angle of arc function

Time:12-24

Example:

Try to get a handle on Arc and I'm running into a wall trying to figure out the end angle. I need something simple so can feed it a percentage and it make an arc that that's percent of a circle.

I got the arc to start at the top and I know math.pi*2 will get me all the way around but when I try to modify that with the old *0.p trick of a converted percentage I get this.

white is 0.1/10% red is 0.95/95% green is 0.5/50% blue is 0.7/70%

but none of them look like that and I just can't figure out the way it's figuring the arc.

    var radius = 250 / 2 - 5;
    var centerx = 250 / 2;
    var centery = 250 / 2;
    const startagle = Math.PI * 1.5;
    var endagle = (Math.PI * 2)*0.1;
    context.beginPath();
    context.fillStyle = 'white';
    context.arc(centerx, centery, radius, startagle, endagle, false);
    context.lineTo(centerx, centery);
    context.fill();
    context.closePath();        
    
    var endagle = (Math.PI * 2)*0.95;
    context.beginPath();
    context.fillStyle = 'red';
    context.arc(centerx, centery, radius-5, startagle, endagle, false);
    context.lineTo(centerx, centery);
    context.fill();
    context.closePath();        
    
    var endagle = (Math.PI * 2)*0.5;
    context.beginPath();
    context.fillStyle = 'green';
    context.arc(centerx, centery, radius-10, startagle, endagle, false);
    context.lineTo(centerx, centery);
    context.fill();
    context.closePath();        

    var endagle = (Math.PI * 2)*0.7;
    context.beginPath();
    context.fillStyle = 'blue';
    context.arc(centerx, centery, radius-15, startagle, endagle, false);
    context.lineTo(centerx, centery);
    context.fill();
    context.closePath();        

    context.beginPath();
    context.arc(centerx, centery, radius-20, 0, 360, false);
    context.closePath();
    context.clip();
    const avatar = await Canvas.loadImage('https://i.imgur.com/lleYAsg.png');
    context.drawImage(avatar, 10, 10, 250, 250);

Finalized/Fixed code

https://i.imgur.com/Y0IzgRJ.png

const Canvas = require('canvas');
      var canvas = Canvas.createCanvas(700, 250);
      var context = canvas.getContext('2d');
  
      const background = await Canvas.loadImage('./images/photo-1538370965046-79c0d6907d47.jpg');
      context.drawImage(background, 0, 0, canvas.width, canvas.height);
  
      context.strokeStyle = '#0099ff';
      context.strokeRect(0, 0, canvas.width, canvas.height);

        var answers = [
          "Red Ranger",
          "Blue Ranger",
          "Yellow Ranger",
          "Pink Ranger",
          "Green Ranger",
          "Black Ranger",
          "Orange Ranger",
          "Violet Ranger",
          "White Ranger",
          "Silver Ranger",
          "Gold Ranger",
          "Bronze Ranger",
          "Brown Ranger",
          "Extra Hero",
          "Meta Hero",
          "Rider",
          "Ultra",
          "Kaiju"
        ];
        var stats = [
          Math.floor(Math.random() * 99),
          Math.floor(Math.random() * 99),
          Math.floor(Math.random() * 99),
          Math.floor(Math.random() * 99),
          Math.floor(Math.random() * 99),
          Math.floor(Math.random() * 99),
          Math.floor(Math.random() * 99),
          Math.floor(Math.random() * 99),
          Math.floor(Math.random() * 99)
        ];
        var toonnamelist = [
          "Evelyn Leon",
          "Salvador Knight",
          "Alyson Hensley",
          "Tobias Harvey",
          "Selah Frazier",
          "Morgan Ward",
          "Ronald Shepherd",
          "Miriam Moody",
          "Maren Gallagher",
          "Alexia Crawford",
          "Aliya Weiss",
          "Jan Garrison"
        ];
        var toonavatars = [
          "https://i.imgur.com/lleYAsg.png",
          "https://i.imgur.com/0x008b.png",
          "https://i.imgur.com/ESPP3b.png",
          "https://i.imgur.com/qv7cvb.png",
          "https://i.imgur.com/VuYRAb.png",
          "https://i.imgur.com/RB6lSb.png",
          "https://i.imgur.com/hMlrIb.png",
          "https://i.imgur.com/mLuRIb.png",
          "https://i.imgur.com/QVQ7mb.png",
          "https://i.imgur.com/IXEuqb.png",
          "https://i.imgur.com/CgMlpb.png",
          "https://i.imgur.com/vO008b.png"
        ];
        var randomrank = answers[Math.floor(Math.random() * answers.length)];
        var randomavy = toonavatars[Math.floor(Math.random() * toonavatars.length)];
        var toonname = `${msg.member.displayName}`;
            toonname = toonnamelist[Math.floor(Math.random() * toonnamelist.length)];;
        var toonlevel = Math.floor(Math.random() * 99);
        var toonrank = randomrank;
        var curentexp = Math.floor(Math.random() * 9999);
        var maxexp = Math.floor(Math.random() * 9999);
        if (curentexp > maxexp){curentexp = maxexp;}

        const cFont = context.font;
        var fontArgs = context.font.split(' ');
        var newSize = '30px';
        context.font = newSize   ' '   fontArgs[fontArgs.length - 1];
        context.fillText(toonname, 250, 50);

        fontArgs = context.font.split(' ');
        newSize = '20px';
        context.font = newSize   ' '   fontArgs[fontArgs.length - 1];
        context.fillText(`Level: ` toonlevel, 250, 80);
        context.fillText(`Rank: ` toonrank, 350, 80);

        context.font = '30px monospace';
        context.fillText(`S:` stats[0], 250, 170);
        context.fillText(`P:` stats[1], 355, 170);
        context.fillText(`E:` stats[2], 450, 170);
        context.fillText(`W:` stats[3], 250, 200);
        context.fillText(`I:` stats[4], 355, 200);
        context.fillText(`L:` stats[5], 450, 200);
        context.fillText(`A:` stats[6], 250, 230);
        context.fillText(`F:` stats[7], 355, 230);
        context.fillText(`R:` stats[8], 450, 230);

        var recx = 250;
        var recy = 90;
        var recw = 300;
        var rech = 40;
        context.fillStyle = 'grey';
        context.strokeStyle = 'silver';
        context.lineWidth = '3';
        context.beginPath();
        context.fillRect(recx, recy, recw*(curentexp/maxexp), rech);
        context.strokeRect(recx, recy, recw, rech);
        context.fillStyle = 'white';
        context.font = '20px sans-serif';
        context.fillText('XP: ' curentexp '/' maxexp, 260, recy 28);
        context.closePath();        

        let strokeWidth = 5;
        var radius = 250 / 2 - strokeWidth;
        let center = {
          x: 250 / 2,
          y: 250 / 2,
        };
        //var centerX = 250 / 2;
        //var centerY = 250 / 2;
        //const fullCircle = Math.PI * 2;
        //const startAngle = Math.PI * 1.5;
        //let endAngle;
        let sectors = [
          { color: 'white', size: 0.1 },
          { color: 'crimson', size: 0.95 },
          { color: 'springgreen', size: 0.5 },
          { color: 'dodgerblue', size: 0.7 },
        ];

        function drawSector({ context, color, center, radius, size }) {
          let startAngle = Math.PI * 1.5;
          let endAngle = startAngle   Math.PI * 2 * size;
        
          context.beginPath();
          context.fillStyle = color;
          context.arc(center.x, center.y, radius, startAngle, endAngle);
          context.lineTo(center.x, center.y);
          context.fill();
          context.closePath();
        }

        sectors.forEach(({ color, size }, i) => drawSector({
          context, color, center, radius: radius - i * strokeWidth, size
        }));
        
        const conditionx = 575;
        const conditiony = 5;
        const conditionw = 125;
        const conditionh = 250;
        var conditionpic1 = await Canvas.loadImage('https://maskedriders.info/Mee6RP/PaperDoll/White_Base/NekollxComm_BaseV2ArmS1_White.png');
        var conditionpic2 = await Canvas.loadImage('https://maskedriders.info/Mee6RP/PaperDoll/White_Base/NekollxComm_BaseV2ArmS2_White.png');
        var conditionpic3 = await Canvas.loadImage('https://maskedriders.info/Mee6RP/PaperDoll/White_Base/NekollxComm_BaseV2Head_White.png');
        var conditionpic4 = await Canvas.loadImage('https://maskedriders.info/Mee6RP/PaperDoll/White_Base/NekollxComm_BaseV2Torso_White.png');
        var conditionpic5 = await Canvas.loadImage('https://maskedriders.info/Mee6RP/PaperDoll/White_Base/NekollxComm_BaseV2LegS1_White.png');
        var conditionpic6 = await Canvas.loadImage('https://maskedriders.info/Mee6RP/PaperDoll/White_Base/NekollxComm_BaseV2LegS2_White.png');

        var conditionpic3 = await Canvas.loadImage('https://maskedriders.info/Mee6RP/PaperDoll/White_Adjustments/CatPeople/NekollxComm2_CatHead_F_White.png');
        var conditionpic7 = await Canvas.loadImage('https://maskedriders.info/Mee6RP/PaperDoll/White_Adjustments/CatPeople/NekollxComm2_CatTail_F_White.png');
        context.drawImage(conditionpic1, conditionx, conditiony, conditionw, conditionh);
        context.drawImage(conditionpic2, conditionx, conditiony, conditionw, conditionh);
        context.drawImage(conditionpic3, conditionx, conditiony, conditionw, conditionh);
        context.drawImage(conditionpic4, conditionx, conditiony, conditionw, conditionh);
        context.drawImage(conditionpic5, conditionx, conditiony, conditionw, conditionh);
        context.drawImage(conditionpic6, conditionx, conditiony, conditionw, conditionh);
        context.drawImage(conditionpic7, conditionx, conditiony, conditionw, conditionh);

        context.beginPath();
        context.arc(center.x, center.y, radius - sectors.length * strokeWidth, 0, 360, false);
        context.closePath();
        context.clip();
        const avatar = await Canvas.loadImage(randomavy);
        context.drawImage(avatar, 10, 10, 250, 250);

CodePudding user response:

It's because you forgot that you changed the starting angle. You need to make the angle, at which the arc ends, to be relative to the starting angle. So if you increase the value by the starting value it will work as expected:

// ** For this demo only ** //
const canvas = document.querySelector('canvas');
const context = canvas.getContext('2d');

canvas.height = 250;
canvas.width = 250;
context.fillStyle = 'dimgray';
context.fillRect(0, 0, canvas.width, canvas.height);
// ** End ** //

const radius = canvas.width / 2 - 5;
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const fullCircle = Math.PI * 2;
const startAngle = Math.PI * 1.5;
let endAngle;

endAngle = startAngle   fullCircle * 0.1;
context.beginPath();
context.fillStyle = 'white';
context.arc(centerX, centerY, radius, startAngle, endAngle, false);
context.lineTo(centerX, centerY);
context.fill();
context.closePath();

endAngle = startAngle   fullCircle * 0.95;
context.beginPath();
context.fillStyle = 'crimson';
context.arc(centerX, centerY, radius - 5, startAngle, endAngle, false);
context.lineTo(centerX, centerY);
context.fill();
context.closePath();

endAngle = startAngle   fullCircle * 0.5;
context.beginPath();
context.fillStyle = 'springgreen';
context.arc(centerX, centerY, radius - 10, startAngle, endAngle, false);
context.lineTo(centerX, centerY);
context.fill();
context.closePath();

endAngle = startAngle   fullCircle * 0.7;
context.beginPath();
context.fillStyle = 'dodgerblue';
context.arc(centerX, centerY, radius - 15, startAngle, endAngle, false);
context.lineTo(centerX, centerY);
context.fill();
context.closePath();

context.beginPath();
context.arc(centerX, centerY, radius - 20, 0, 360, false);
context.closePath();
context.clip();

// ** For this demo only ** //
let url = 'https://i.imgur.com/lleYAsg.png';
let img = new Image();
new Promise((resolve) => (img.onload = resolve), (img.src = url)).then(() =>
  context.drawImage(img, 10, 10, 250, 250),
);
body {
  align-items: center;
  background-color: dimgray;
  display: flex;
  justify-content: center;
  margin: 0;
  min-height: 100vh;
}
<canvas></canvas>

It works as expected; however, you could also simplify the way you create the sectors. I would write a function to draw these (drawSector) and store the colours and sizes in an array (sectors).

// ** For this demo only ** //
let canvas = document.querySelector('canvas');
let context = canvas.getContext('2d');

canvas.height = 250;
canvas.width = 250;
context.fillStyle = '#232425';
context.fillRect(0, 0, canvas.width, canvas.height);
// ** End ** //

let center = {
  x: canvas.width / 2,
  y: canvas.height / 2,
};
let strokeWidth = 5;
let radius = canvas.width / 2 - strokeWidth;
let sectors = [
  { color: 'white', size: 0.1 },
  { color: 'crimson', size: 0.95 },
  { color: 'springgreen', size: 0.5 },
  { color: 'dodgerblue', size: 0.7 },
];

function drawSector({ context, color, center, radius, size }) {
  let startAngle = Math.PI * 1.5;
  let endAngle = startAngle   Math.PI * 2 * size;

  context.beginPath();
  context.fillStyle = color;
  context.arc(center.x, center.y, radius, startAngle, endAngle);
  context.lineTo(center.x, center.y);
  context.fill();
  context.closePath();
}

sectors.forEach(({ color, size }, i) => drawSector({
  context, color, center, radius: radius - i * strokeWidth, size
}));

context.beginPath();
context.arc(center.x, center.y, radius - sectors.length * strokeWidth, 0, 360);
context.closePath();
context.clip();

// ** For this demo only ** //
let url = 'https://i.imgur.com/lleYAsg.png';
let img = new Image();
new Promise((resolve) => (img.onload = resolve), (img.src = url)).then(() =>
  context.drawImage(img, 10, 10, 250, 250),
);
body {
  align-items: center;
  background-color: #232425;
  display: flex;
  justify-content: center;
  margin: 0;
  min-height: 100vh;
}
<canvas></canvas>

  • Related