Related
I'm trying to create simple animation to take the moon that I have drawn behind the clouds and allow users to move it across the x axis in the canvas. I have seen where others have done this with rectangles, and I have seen where their code seems basic enough for my inexperience to follow... but I'm struggling a bit with my code.
Every time I put code in that I think will work, it wipes out the canvas... which means I have placement and structural issues... but I'm having trouble figuring out where and how.
Can someone help me figure out how to animate my drawMoon so that it will move across the x axis when the left and right arrow keys are used?
NOTE I have tried using event listeners for keydown and keyup, but I'm sure I'm doing it wrong.
Attaching code that has nothing included so that you all have the base code without the animation attempt.
Any help is appreciated.
UPDATE I think I broke it more..... thoughts?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Howling at the Moon</title>
</head>
<body onload="init();">
<canvas id="myCanvas" width="900" height="900">Your browser does not support the canvas tag.</canvas>
<script type="text/javascript">
var canvas, ctx;
var moonx = 0;
var moony = 0;
var moonAngle = 0;
var incrementX = 0;
function init() {
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
window.addEventListener("keydown", handleKeydown, false);
window.addEventListener("keyup", handleKeyup, false);
drawMonster(260, 260);
drawMoon(100, 100);
drawCloud(150, 175);
requestId = requestAnimationFrame(animationLoop);
function handleKeydown(evt) {
if (evt.keyCode === 37) {
incrementX = -1;
} else if (evt.keyCode === 39) {
incrementX = 1;
}
}
function handleKeyup(evt) {
incrementX = 0;
}
function animationLoop() {
context.globalCompositeOperation = 'destination-out'
}
drawMoon(moonx, moony, moonAngle, "green", "yellow");
moonx += incrementX;
requestId = requestAnimationFrame(animationLoop);
}
function drawMonster(x, y) {
ctx.save();
ctx.beginPath();
ctx.arc(740, 750, 175, 0, Math.PI / 0.5);
ctx.fillStyle = "lightgrey";
ctx.fill();
ctx.lineWidth = 3;
ctx.stroke();
//mouth1
ctx.fillStyle = "black";
ctx.fillRect(x + 350, y + 550, 200, 20);
//mouth2
ctx.fillStyle = "black";
ctx.fillRect(x + 375, y + 540, 150, 20);
//mouth3
ctx.fillStyle = "black";
ctx.fillRect(x + 375, y + 560, 150, 20);
ctx.restore();
//eyes
addShadows2();
ctx.fillStyle = "lightslategrey";
ctx.fillRect(x + 350, y + 400, 40, 40);
ctx.fillRect(x + 450, y + 400, 40, 40);
//pupil
ctx.fillStyle = "black";
ctx.fillRect(x + 350, y + 400, 20, 20);
ctx.fillRect(x + 450, y + 400, 20, 20);
}
//moon
function drawMoon(moonx, moony) {
ctx.beginPath();
ctx.arc(100, 75, 150, 0, Math.PI / 0.5);
ctx.fillStyle = "lightgrey";
addShadows();
ctx.fill();
ctx.lineWidth = 3;
ctx.stroke();
}
//cloud
function drawCloud(x, y) {
ctx.beginPath();
ctx.arc(x, y, 60, Math.PI * 0.5, Math.PI * 1.5);
ctx.arc(x + 70, y - 60, 70, Math.PI * 1, Math.PI * 1.85);
ctx.arc(x + 152, y - 45, 50, Math.PI * 1.37, Math.PI * 1.91);
ctx.arc(x + 200, y, 60, Math.PI * 1.5, Math.PI * 0.5);
ctx.moveTo(x + 200, y + 60);
ctx.lineTo(x, y + 60);
ctx.strokeStyle = "#797874";
ctx.stroke();
ctx.fillStyle = "lightslategrey";
ctx.fill();
}
function addShadows() {
ctx.shadowColor = "beige"; // color
ctx.shadowBlur = 160; // blur level
ctx.shadowOffsetX = 15; // horizontal offset
ctx.shadowOffsetY = 15; // vertical offset
}
function addShadows2() {
ctx.shadowColor = "black";
ctx.shadowBlur = 40;
ctx.shadowOffsetX = 15;
ctx.shadowOffsetY = 10;
}
function addShadows3() {
ctx.shadowColor = "beige";
ctx.shadowBlur = 160;
ctx.shadowOffsetX = 10;
ctx.shadowOffsetY = 10;
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Howling at the Moon</title>
</head>
<body onload="init();">
<canvas id="myCanvas" width="900" height="900">Your browser does not support the canvas tag.</canvas>
<script type="text/javascript">
var canvas, ctx;
function init() {
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
window.addEventListener('keydown', handleKeydown, false);
window.addEventListener('keyup', handleKeyup, false);
drawMonster(260, 260);
drawMoon(100, 100);
drawCloud(150, 175);
function handleKeydown(evt) {
if (evt.keyCode === 37) {
//left key
incrementX = -1;
} else if (evt.keyCode === 39) {
// right key
incrementX = 1;
}
}
function drawMonster(x, y) {
ctx.save();
ctx.beginPath();
ctx.arc(740, 750, 175, 0, Math.PI / .5);
ctx.fillStyle = "lightgrey";
ctx.fill();
ctx.lineWidth = 3;
ctx.stroke();
//mouth1
ctx.fillStyle = 'black'
ctx.fillRect(x + 350, y + 550, 200, 20);
//mouth2
ctx.fillStyle = 'black'
ctx.fillRect(x + 375, y + 540, 150, 20);
//mouth3
ctx.fillStyle = 'black'
ctx.fillRect(x + 375, y + 560, 150, 20);
ctx.restore();
//eyes
addShadows2();
ctx.fillStyle = 'lightslategrey'
ctx.fillRect(x + 350, y + 400, 40, 40);
ctx.fillRect(x + 450, y + 400, 40, 40);
//pupil
ctx.fillStyle = 'black'
ctx.fillRect(x + 350, y + 400, 20, 20);
ctx.fillRect(x + 450, y + 400, 20, 20);
}
function animateMoon()
{
ctx.clearArc(0,0,canvas.width,canvas.height);
drawMoon(x,y);
requestId = requestAnimationFrame(animateMoon);
}
//moon
function drawMoon(x, y) {
ctx.beginPath();
ctx.arc(100, 75, 150, 0, Math.PI / .5);
ctx.fillStyle = "lightgrey";
addShadows();
ctx.fill();
ctx.lineWidth = 3;
ctx.stroke();
}
//cloud
function drawCloud(x, y) {
ctx.beginPath();
ctx.arc(x, y, 60, Math.PI * 0.5, Math.PI * 1.5);
ctx.arc(x + 70, y - 60, 70, Math.PI * 1, Math.PI * 1.85);
ctx.arc(x + 152, y - 45, 50, Math.PI * 1.37, Math.PI * 1.91);
ctx.arc(x + 200, y, 60, Math.PI * 1.5, Math.PI * 0.5);
ctx.moveTo(x + 200, y + 60);
ctx.lineTo(x, y + 60);
ctx.strokeStyle = "#797874";
ctx.stroke();
ctx.fillStyle = "lightslategrey";
ctx.fill();
}
function addShadows() {
ctx.shadowColor = "beige"; // color
ctx.shadowBlur = 160; // blur level
ctx.shadowOffsetX = 15; // horizontal offset
ctx.shadowOffsetY = 15; // vertical offset
}
function addShadows2() {
ctx.shadowColor = "black";
ctx.shadowBlur = 40;
ctx.shadowOffsetX = 15;
ctx.shadowOffsetY = 10;
}
function addShadows3() {
ctx.shadowColor = "beige";
ctx.shadowBlur = 160;
ctx.shadowOffsetX = 10;
ctx.shadowOffsetY = 10;
}
function start() {
// Start the animation loop, targets 60 frames/s
requestId = requestAnimationFrame(animationLoop);
}
function stop() {
if (requestId) {
cancelAnimationFrame(requestId);
}
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Howling at the Moon</title>
</head>
<body onload="init();">
<canvas id="myCanvas" width="900" height="900">Your browser does not support the canvas tag.</canvas>
<script type="text/javascript">
var canvas, ctx;
function init() {
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
window.addEventListener('keydown', handleKeydown, false);
window.addEventListener('keyup', handleKeyup, false);
drawMonster(260, 260);
drawMoon(100, 100);
drawCloud(150, 175);
function handleKeydown(evt) {
if (evt.keyCode === 37) {
//left key
incrementX = -1;
} else if (evt.keyCode === 39) {
// right key
incrementX = 1;
}
}
function drawMonster(x, y) {
ctx.save();
ctx.beginPath();
ctx.arc(740, 750, 175, 0, Math.PI / .5);
ctx.fillStyle = "lightgrey";
ctx.fill();
ctx.lineWidth = 3;
ctx.stroke();
//mouth1
ctx.fillStyle = 'black'
ctx.fillRect(x + 350, y + 550, 200, 20);
//mouth2
ctx.fillStyle = 'black'
ctx.fillRect(x + 375, y + 540, 150, 20);
//mouth3
ctx.fillStyle = 'black'
ctx.fillRect(x + 375, y + 560, 150, 20);
ctx.restore();
//eyes
addShadows2();
ctx.fillStyle = 'lightslategrey'
ctx.fillRect(x + 350, y + 400, 40, 40);
ctx.fillRect(x + 450, y + 400, 40, 40);
//pupil
ctx.fillStyle = 'black'
ctx.fillRect(x + 350, y + 400, 20, 20);
ctx.fillRect(x + 450, y + 400, 20, 20);
}
function animateMoon() {
ctx.clearArc(0, 0, canvas.width, canvas.height);
drawMoon(x, y);
requestId = requestAnimationFrame(animateMoon);
}
//moon
function drawMoon(x, y) {
ctx.beginPath();
ctx.arc(100, 75, 150, 0, Math.PI / .5);
ctx.fillStyle = "lightgrey";
addShadows();
ctx.fill();
ctx.lineWidth = 3;
ctx.stroke();
}
//cloud
function drawCloud(x, y) {
ctx.beginPath();
ctx.arc(x, y, 60, Math.PI * 0.5, Math.PI * 1.5);
ctx.arc(x + 70, y - 60, 70, Math.PI * 1, Math.PI * 1.85);
ctx.arc(x + 152, y - 45, 50, Math.PI * 1.37, Math.PI * 1.91);
ctx.arc(x + 200, y, 60, Math.PI * 1.5, Math.PI * 0.5);
ctx.moveTo(x + 200, y + 60);
ctx.lineTo(x, y + 60);
ctx.strokeStyle = "#797874";
ctx.stroke();
ctx.fillStyle = "lightslategrey";
ctx.fill();
}
function addShadows() {
ctx.shadowColor = "beige"; // color
ctx.shadowBlur = 160; // blur level
ctx.shadowOffsetX = 15; // horizontal offset
ctx.shadowOffsetY = 15; // vertical offset
}
function addShadows2() {
ctx.shadowColor = "black";
ctx.shadowBlur = 40;
ctx.shadowOffsetX = 15;
ctx.shadowOffsetY = 10;
}
function addShadows3() {
ctx.shadowColor = "beige";
ctx.shadowBlur = 160;
ctx.shadowOffsetX = 10;
ctx.shadowOffsetY = 10;
}
function start() {
// Start the animation loop, targets 60 frames/s
requestId = requestAnimationFrame(animationLoop);
}
function stop() {
if (requestId) {
cancelAnimationFrame(requestId);
}
}
</script>
</body>
</html>
There were several issues in your code and I'll share the changes I made to get the animation to work.
Errors
In your animationLoop, you referenced a variable named context which I believe you meant to reference ctx instead.
context.globalCompositeOperation = 'destination-out'
I can't say I've used this property of the CanvasRenderingContext2D, but I didn't notice any positive effects it produced for your code and the resulting animation. I first changed it to ctx.globalCompositeOperation and eventually removed it.
Another error was that you were declaring ctx and canvas in your init function even though you had variables declared outside the function. I opted to remove the declaration and just make it an assignment instead:
canvas = document.getElementById("myCanvas");
ctx = canvas.getContext("2d");
With these changes, the initial errors were resolved.
Issues
In init the shapes are drawn on the canvas and we have two identical lines using requestAnimationFrame:
requestId = requestAnimationFrame(animationLoop);
drawMoon(moonx, moony, moonAngle, "green", "yellow");
moonx += incrementX;
requestId = requestAnimationFrame(animationLoop);
I removed the first one (also removing the requestId assignment as it didn't seem necessary). Then, in order for the animationLoop to continue to animate, we need to call requestAnimationFrame(animationLoop) inside of the animationLoop function.
function animationLoop() {
// ...
requestAnimationFrame(animationLoop);
}
Then, in order to actually draw the shapes in each call of animationLoop, I moved the draw<shape> function calls inside of animationLoop. Also, we want to clear the canvas each time we draw on it to properly animate our shapes, so we'll need to use .clearRect. Now the animationLoop looks like this:
function animationLoop() {
moonx += incrementX;
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawMonster(260, 260);
drawCloud(150, 175);
drawMoon(moonx, moony, moonAngle, "green", "yellow");
requestAnimationFrame(animationLoop);
}
But the final reason the moon won't move when we press the left or right arrows is that we're not actually using the moonx and moony variables when drawing the moon. So, in drawMoon, instead of
ctx.arc(100, 75, 150, 0, Math.PI / .5);
this should be changed to the following
ctx.arc(moonx, moony, 150, 0, Math.PI / 0.5);
I believe I covered all of the major issues with your code to be able to draw all the shapes and move the moon with the left and right arrows. See the full code example below.
var canvas, ctx;
var moonx = 0;
var moony = 0;
var moonAngle = 0;
var incrementX = 0;
function init() {
canvas = document.getElementById("myCanvas");
ctx = canvas.getContext("2d");
window.addEventListener("keydown", handleKeydown, false);
window.addEventListener("keyup", handleKeyup, false);
requestAnimationFrame(animationLoop);
function handleKeydown(evt) {
if (evt.keyCode === 37) {
incrementX = -1;
} else if (evt.keyCode === 39) {
incrementX = 1;
}
}
function handleKeyup(evt) {
incrementX = 0;
}
function animationLoop() {
moonx += incrementX;
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawMonster(260, 260);
drawCloud(150, 175);
drawMoon(moonx, moony, moonAngle, "green", "yellow");
requestAnimationFrame(animationLoop);
}
}
function drawMonster(x, y) {
ctx.save();
ctx.beginPath();
ctx.arc(740, 750, 175, 0, Math.PI / 0.5);
ctx.fillStyle = "lightgrey";
ctx.fill();
ctx.lineWidth = 3;
ctx.stroke();
//mouth1
ctx.fillStyle = "black";
ctx.fillRect(x + 350, y + 550, 200, 20);
//mouth2
ctx.fillStyle = "black";
ctx.fillRect(x + 375, y + 540, 150, 20);
//mouth3
ctx.fillStyle = "black";
ctx.fillRect(x + 375, y + 560, 150, 20);
ctx.restore();
//eyes
addShadows2();
ctx.fillStyle = "lightslategrey";
ctx.fillRect(x + 350, y + 400, 40, 40);
ctx.fillRect(x + 450, y + 400, 40, 40);
//pupil
ctx.fillStyle = "black";
ctx.fillRect(x + 350, y + 400, 20, 20);
ctx.fillRect(x + 450, y + 400, 20, 20);
}
//moon
function drawMoon(moonx, moony) {
ctx.beginPath();
ctx.arc(moonx, moony, 150, 0, Math.PI / 0.5);
ctx.fillStyle = "lightgrey";
addShadows();
ctx.fill();
ctx.lineWidth = 3;
ctx.stroke();
}
//cloud
function drawCloud(x, y) {
ctx.beginPath();
ctx.arc(x, y, 60, Math.PI * 0.5, Math.PI * 1.5);
ctx.arc(x + 70, y - 60, 70, Math.PI * 1, Math.PI * 1.85);
ctx.arc(x + 152, y - 45, 50, Math.PI * 1.37, Math.PI * 1.91);
ctx.arc(x + 200, y, 60, Math.PI * 1.5, Math.PI * 0.5);
ctx.moveTo(x + 200, y + 60);
ctx.lineTo(x, y + 60);
ctx.strokeStyle = "#797874";
ctx.stroke();
ctx.fillStyle = "lightslategrey";
ctx.fill();
}
function addShadows() {
ctx.shadowColor = "beige"; // color
ctx.shadowBlur = 160; // blur level
ctx.shadowOffsetX = 15; // horizontal offset
ctx.shadowOffsetY = 15; // vertical offset
}
function addShadows2() {
ctx.shadowColor = "black";
ctx.shadowBlur = 40;
ctx.shadowOffsetX = 15;
ctx.shadowOffsetY = 10;
}
function addShadows3() {
ctx.shadowColor = "beige";
ctx.shadowBlur = 160;
ctx.shadowOffsetX = 10;
ctx.shadowOffsetY = 10;
}
init();
<canvas id="myCanvas" width="900" height="900">Your browser does not support the canvas tag.</canvas>
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
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);
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>
i want to create a curved text in qml it's possible? Is there a javascript library that i can import to do it?
My idea is that it's possible maybe with canvas element but i don't know how i can do it... it's a good idea??
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Canvas{
anchors.fill: parent
onPaint: {
var ctx = getContext("2d");
ctx.fillStyle = Qt.rgba(1, 0, 0, 1);
ctx.fillRect(0, 0, width, height);
//how i can create curved text???
}
}
}
Hello I tried the code into the link posted by #folibis , work perfectly!!!
This is the code :
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Canvas{
property string nameFont: webFont.name
function drawTextAlongArc(context, str, centerX, centerY, radius, angle)
{
context.save();
context.translate(centerX, centerY);
context.rotate(-1 * angle / 2);
context.rotate(-1 * (angle / str.length) / 2);
for (var n = 0; n < str.length; n++) {
context.rotate(angle / str.length);
context.save();
context.translate(0, -1 * radius);
var char1 = str[n];
context.fillText(char1, 0, 0);
context.restore();
}
context.restore();
}
anchors.fill: parent
onPaint: {
var ctx = getContext("2d");
ctx.fillStyle = Qt.rgba(1, 1, 1, 1);
ctx.fillRect(0, 0, width, height);
ctx.font='50px Verdana'
//ctx.font = '30px Courier New'
ctx.textAlign = "center";
var centerX = width / 2;
var centerY = height/2; //height - 30;
var angle = Math.PI * 0.8; // radians
var radius = 180;
ctx.fillStyle="#000000"
drawTextAlongArc(ctx, "Hello World", centerX, centerY, radius, angle);
}
}
}
How to add another stroke with a different color and length into the same circle?
This script use Mootools lib. Can it be converted in pure JavaScript or jQuery?
fiddle: http://jsfiddle.net/xc4xnzcq/1/
Thanks :)
// SVG stuff
var ctx = document.id('counter').getContext('2d');
var circ = Math.PI * 2;
var quart = Math.PI / 2;
ctx.beginPath();
ctx.strokeStyle = '#ff00ab';
ctx.lineCap = 'square';
ctx.closePath();
ctx.fill();
ctx.lineWidth = 10;
var imd = ctx.getImageData(0, 0, 160, 160);
var draw = function(current) {
ctx.putImageData(imd, 0, 0);
ctx.beginPath();
ctx.arc(119, 70, 60, -(quart), ((circ) * current) - quart, false);
ctx.stroke();
}
var myFx = new Fx({
duration: 5500,
transition: 'bounce:out',
onStep: function(step){
draw(step / 100);
}
});
myFx.set = function(now){
var ret = Fx.prototype.set.call(this, now);
this.fireEvent('step', now);
return ret;
};
myFx.start(0, 80);
Drawing a second path seems to work fine for me.
// SVG stuff
var ctx = document.id('counter').getContext('2d');
var circ = Math.PI * 2;
var quart = Math.PI / 2;
var imd = ctx.getImageData(0, 0, 160, 160);
var draw = function(current) {
ctx.putImageData(imd, 0, 0);
ctx.beginPath();
ctx.strokeStyle = '#ff00ab';
ctx.lineCap = 'square';
ctx.lineWidth = 10;
ctx.arc(119, 70, 60, -(quart), ((circ) * current) - quart, false);
ctx.stroke();
ctx.beginPath();
ctx.strokeStyle = '#bb00bc';
ctx.lineCap = 'square';
ctx.lineWidth = 5;
ctx.arc(119, 70, 60, -(quart), ((circ) * current) - quart, false);
ctx.stroke();
}
var myFx = new Fx({
duration: 5500,
transition: 'bounce:out',
onStep: function(step){
draw(step / 100);
}
});
myFx.set = function(now){
var ret = Fx.prototype.set.call(this, now);
this.fireEvent('step', now);
return ret;
};
myFx.start(0, 80);
I have a piece of code. But my problem is.. I have no idea where i can change the animation speed. I've tried to edit last line into animate('fast'); but without success..how can i solve it?
I know it is mainy javascript but so far I didnt find such code which will be better in jquery
$('#kim-jestesmy').waypoint(function(direction) {
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
window.requestAnimationFrame = requestAnimationFrame;
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var circles = [];
createCircle(100,100,'78', function() {
createCircle(270,100,'460', function() {
createCircle(440,100,'20', function() {
createCircle(610,100,'15', null);
});
});
});
function createCircle(x,y,text,callback) {
var radius = 75;
var endPercent = 101;
var curPerc = 0;
var counterClockwise = false;
var circ = Math.PI * 2;
var quart = Math.PI / 2;
context.lineWidth = 10;
context.strokeStyle = '#E60086';
context.shadowOffsetX = 0;
context.shadowOffsetY = 0;
function doText(context,x,y,text) {
context.lineWidth = 1;
context.fillStyle = "#919191";
context.lineStyle = "#919191";
context.font = "60px NillandBold";
context.textAlign = "center";
context.textBaseline = "middle";
context.fillText(text, x, y);
}
function animate(current) {
context.lineWidth = 10;
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.arc(x, y, radius, -(quart), ((circ) * current) - quart, false);
context.stroke();
curPerc++;
if (circles.length) {
for (var i=0; i<circles.length; i++) {
context.lineWidth = 10;
context.beginPath();
context.arc(circles[i].x, circles[i].y, radius, -(quart), ((circ) * circles[i].curr) - quart, false);
context.stroke();
doText(context,circles[i].x,circles[i].y,circles[i].text);
}
}
if (curPerc < endPercent) {
requestAnimationFrame(function () {
animate(curPerc / 100)
});
}else{
var circle = {x:x,y:y,curr:current,text:text};
circles.push(circle);
doText(context,x,y,text);
if (callback) callback.call();
}
}
animate();
}
});
Since you're not throttling the fps of your animation, each frame is being rendered as fast as possible with this code. If you want it to be faster, the simplest answer is to drop frames by incrementing the curPerc variable by more than one:
function animate(current) {
context.lineWidth = 10;
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.arc(x, y, radius, -(quart), ((circ) * current) - quart, false);
context.stroke();
curPerc += 2;
...
The above code will complete twice as quickly. If curPerc does not divide 100 evenly (100%curPerc != 0), then change the variable endPercent accordingly.