I've got the following HTML file:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Canvas Hello World</title>
<link href="default.css" rel="stylesheet" />
<script src="jquery-2.0.0.min.js"></script>
</head>
<body>
<h1>ArcTo</h1>
<h2>Two arcs</h2>
<canvas id="arcToNormalCanvas" width="500" height="500">HTML5 not supported
</canvas>
<hr />
<h1>Simple drawing:</h1>
<canvas id="rectangleCanvas" width="500" height="500">HTML5 not supported
</canvas>
<hr />
<script>
$(document).ready(function () {
doRectangleCanvas();
drawTwoArcs();
});
function doRectangleCanvas() {
var canvas = $('#rectangleCanvas')[0],
ctx = canvas.getContext('2d');
ctx.fillRect(50, 100, 150, 200);
ctx.stroke();
}
function drawTwoArcs() {
var canvas = $('#arcToNormalCanvas')[0],
ctx = canvas.getContext('2d');
ctx.strokeStyle = 'blue';
ctx.lineWidth = 5;
ctx.beginPath();
ctx.moveTo(100, 100);
ctx.lineTo(200, 200);
ctx.moveTo(300, 200);
ctx.lineTo(400, 100);
ctx.stroke();
ctx.beginPath();
ctx.strokeStyle = 'green';
ctx.moveTo(200, 200);
ctx.arcTo(200, 200, 300, 200, 100);
ctx.stroke();
}
</script>
</body>
</html>
However, the output is only the lines, with no arc!
Any ideas?
arcTo is only supported by Firefox and Safari. For full browser support, you should use arc:
ctx.beginPath();
ctx.arc(250,200,50,Math.PI,Math.PI*2,true);
ctx.strokeStyle = "green";
ctx.stroke();
Also, I have to ask, why on earth are you using $('#rectangleCanvas')[0] when you should be using document.getElementById('rectangleCanvas')?
If you want to connect the two lines, which is what I think you want, I have to change this lines...
//...
ctx.moveTo(200, 200);
ctx.arcTo(250, 250, 300, 200, 50);
// A radius of 100 is not what you want I believe.
// I used 50 for this example.
// You might want Math.cos(Math.Pi / 4) * 100, which is around 70.7
// You might also want to add here a line to actually connect with (300, 200). As if you use a too short or too long radius your arc will not be connected.
ctx.lineTo(300, 200);
ctx.stroke();
... As this function will define an arc between the two tangents not from point to point.
BTW, arcTo function is well supported in all major browsers that support the canvas element.
Related
I wrote the following code which is similar to my objective but falls short; because I want to fill inside the text in multiple colors; currently only in #FF00FF.
Playground
I think the problem is that I don't know how to use the text "ABC" as the clipping path. Please show me how to do it, or any answer equivalent for my objective.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>canvas</title>
<script type="text/javascript">
function test() {
var canvas = document.getElementById('sample');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.beginPath();
for(let i=1;i<100;i++){
//mock1: ctx.fillStyle = "rgb(" + [i, i, i] + ")";
ctx.moveTo(0,5*i);
ctx.lineTo(380,5*i);
ctx.lineTo(300,5*i+3);
ctx.lineTo(0,5*i+3);
ctx.lineTo(0,5*i);
}
ctx.closePath();
ctx.clip();
ctx.font = "bold 72px 'Sans-selif'";
ctx.fillStyle = "#FF00FF";
ctx.fillText("ABC", 90, 60);
}
}
</script>
</head>
<body onLoad="test()">
<h2>Canvas</h2>
<canvas width="300" height="150" id="sample" style="background-color:yellow;">
</canvas>
</body>
</html>
The 2DCanvas API unfortunately doesn't expose the text's contour in a way it could be used as a Path2D or in methods like clip() or isPointInPath().
However for what you wish to do, you don't need a path, this can be done by using compositing instead of clipping:
var canvas = document.getElementById('sample');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
// draw the full lines first
ctx.beginPath();
for (let i = 1; i < 100; i++) {
ctx.moveTo(0, 5 * i);
ctx.lineTo(380, 5 * i);
ctx.lineTo(300, 5 * i + 3);
ctx.lineTo(0, 5 * i + 3);
ctx.lineTo(0, 5 * i);
}
ctx.fillStyle = "#00FF00";
ctx.fill();
// with this mode
// every previous pixel that is not under the next drawing
// will get cleared
ctx.globalCompositeOperation = "destination-atop"
ctx.font = "bold 72px 'Sans-serif'";
ctx.fillStyle = "#FF00FF";
ctx.fillText("ABC", 90, 60);
// reset to default mode
ctx.globalCompositeOperation = "source-over"
}
<canvas width="300" height="150" id="sample" style="background-color:yellow;"></canvas>
Firstly I have tried to find solution to my problem but I do not think that I know how to search online for solutions.
Okay so I have this image that is drawn via line segments : moveTo, lineTo etc.
As you can see we could divide the image into 4 parts that are essentially the same but rotated and placed next to other elements. What I mean by this if you draw 4 lines from the center with 90 angle you can notice the same pattern.
Basically what I am trying to do is to have one part of the canvas drawn manually by inserting moveTo and the rest to somehow generate to save some time ofc.
Not sure if I explained well my problem, excuse me this is my first stackoverflow question posted.
I mean I found a way to do this by having 4 different CANVAS elements and then rotate each canvas. I am looking for a way to do everything in one CANVAS element. But not sure if that is possible.
My code below:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Model 1</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body onload="draw();">
<canvas id="canvas_id" width="150" height="150" style="border:1px solid #000000;"></canvas>
<!-- 1---->
<script type="text/javascript">
function draw() {
var canvas = document.getElementById('canvas_id');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
//top left square
ctx.beginPath();
ctx.moveTo(10, 10);
ctx.lineTo(10, 40);
ctx.lineTo(40, 40);
ctx.lineTo(40, 10);
ctx.lineTo(10, 10);
ctx.fillStyle = "red";
ctx.fill();
//down left square
ctx.beginPath();
ctx.moveTo(10, 100);
ctx.lineTo(10, 130);
ctx.lineTo(40,130);
ctx.lineTo(40, 100);
ctx.lineTo(10, 100);
ctx.fillStyle = "red";
ctx.fill();
//top right square
ctx.beginPath();
ctx.moveTo(100, 10);
ctx.lineTo(130, 10);
ctx.lineTo(130, 40);
ctx.lineTo(100, 40);
ctx.lineTo(100, 10);
ctx.fillStyle = "red";
ctx.fill();
//down right square
ctx.beginPath();
ctx.moveTo(100, 100);
ctx.lineTo(130, 100);
ctx.lineTo(130, 130);
ctx.lineTo(100, 130);
ctx.lineTo(100, 100);
ctx.fillStyle = "red";
ctx.fill();
//center figure
//1
ctx.beginPath();
ctx.moveTo(70, 10);
ctx.lineTo(10, 70);
ctx.lineTo(70, 130);
ctx.lineTo(130, 70);
ctx.lineTo(70, 10);
// inside
ctx.moveTo(70, 30);
ctx.lineTo(30, 70);
ctx.lineTo(70, 110);
ctx.lineTo(110, 70);
ctx.lineTo(70, 30);
//square 1
ctx.moveTo(60, 60);
ctx.lineTo(80, 60);
ctx.lineTo(80, 80);
ctx.lineTo(60, 80);
ctx.lineTo(60, 60);
//square 2
ctx.moveTo(50, 50);
ctx.lineTo(90, 50);
ctx.lineTo(90, 90);
ctx.lineTo(50, 90);
ctx.lineTo(50, 50);
ctx.stroke();
}
}
</script>
</body>
</html>
I hope that I understood well what you need.
You can either parametrize your draw function with an angle, and a x, y position parameters, or copy, rotate and paste a part of the canvas. I assumed you would prefer the second solution.
Basically, copy your canvas, rotate it, draw something, then restore your changes.
You can use this function:
function draw(canvas, ctx, x, y, angle) {
ctx.save();
ctx.translate(canvas.width / 2, canvas.height / 2);
ctx.rotate(angle * Math.PI / 180);
ctx.translate(-(canvas.width / 2), -(canvas.height / 2));
// drawing begin
ctx.beginPath();
ctx.moveTo(10, 10);
ctx.lineTo(10, 40);
ctx.lineTo(40, 40);
ctx.lineTo(40, 10);
ctx.lineTo(10, 10);
ctx.lineTo(30, 30);
ctx.strokeStyle = "red";
ctx.stroke();
// drawing end
ctx.restore();
}
You can use it like this:
// draw something with a 90° angle
draw(canvas, ctx, 0, 0, 90);
// draw something with a 180° angle
draw(canvas, ctx, 0, 0, 180);
The x and y coordinates are the ones of the rotated canvas, so 0, 0 will be in the angle each time.
Here's a fiddle: https://jsfiddle.net/nmerinian/kt3f782o/19/
I'm trying to move the tank when the user pressed the right/left key. When I use rotate() it is affecting all the elements of the canvas. Is there a way to only move the third rectangle of the tank when the user presses the right or left key?
The goal is to change the angle by a certain amount on pressing the keys. I searched, but couldn't find something basic enough for me to understand how to implement it.
var canvas=document.getElementById('canvas');
var ctx=canvas.getContext('2d');
var rightPressed=false;
var leftPressed=false;
var score1=0;
var score2=0;
var turn=0;
document.addEventListener("keydown",keyDownHandler,false);
document.addEventListener("keyup",keyUpHandler,false);
function keyDownHandler(e) {
if(e.keyCode==37)
leftPressed=true;
else if(e.keyCode==39)
rightPressed=true;
}
function keyUpHandler(e) {
if(e.keyCode==37)
leftPressed=false;
else if(e.keyCode==39)
rightPressed=false;
}
function drawMountain() {
ctx.beginPath();
ctx.moveTo(250, 400);
ctx.bezierCurveTo(250, 100, 500, 100, 500, 400);
ctx.fillStyle="green";
ctx.fill();
ctx.closePath();
}
function drawTanks() {
ctx.beginPath();
ctx.rect(20,360,50,40);
ctx.rect(620,360,50,40);
ctx.rect(30,340,30,20);
ctx.rect(630,340,30,20);
ctx.rect(40,300,10,40);
ctx.rect(640,300,10,40);
ctx.fillStyle="blue";
ctx.fill();
ctx.closePath();
}
function rotateTank() {
ctx.beginPath();
ctx.rect(20,20,130,40);
ctx.rect(560,20,130,40);
ctx.fillStyle="green";
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.fillStyle="white";
ctx.font="20px Verdana";
ctx.fillText('Player 1: '+ score1,28,45);
ctx.closePath();
ctx.beginPath();
ctx.fillStyle="white";
ctx.font="20px Verdana";
ctx.fillText('Player 2: '+ score2,570,45);
ctx.closePath();
}
function drawGame() {
ctx.clearRect(0,0,canvas.width,canvas.height);
drawMountain();
drawTanks();
rotateTank();
}
setInterval(drawGame,10);
#canvas {
background-color: black;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" href="game.css">
</head>
<body>
<center><canvas id="canvas" width="700" height="400"></canvas></center>
<script src="game.js">
</script>
</body>
</html>
Let's say that we have two rectangles.
ctx.fillStyle = "#F00";
ctx.fillRect(10, 10, 20, 10);
ctx.fillStyle = "#00F";
ctx.fillRect(50, 50, 20, 10);
And you want to rotate only the first one.
There are two ways to do it:
Move the red rectangle after the blue one and rotate it
ctx.fillStyle = "#00F";
ctx.fillRect(50, 50, 20, 10);
ctx.rotate(20*Math.PI/180);
ctx.fillStyle = "#F00";
ctx.fillRect(10, 10, 20, 10);
Just set ctx.rotate to a negative number (in our case -20) after the red rectangle
ctx.rotate(20*Math.PI/180);
ctx.fillStyle = "#F00";
ctx.fillRect(10, 10, 20, 10);
ctx.rotate(-20*Math.PI/180); //This "resets" the rotation.
ctx.fillStyle = "#00F";
ctx.fillRect(50, 50, 20, 10);
Here's a code snippet:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');
function draw() {
ctx.rotate(20*Math.PI/180);
ctx.fillStyle = "#F00";
ctx.fillRect(10, 10, 20, 10);
ctx.rotate(-20*Math.PI/180);
ctx.fillStyle = "#00F";
ctx.fillRect(50, 50, 20, 10);
}
draw();
<canvas id="canvas" width=100 height=100 style="border: 1px solid #000"></canvas>
I want to create a circle and cut out a part of it if it goes outside another shape.
For example, if half of the circle goes outside a square, cut out everything on the outside but not on the inside. Something like this snippet, except the part outside the square is hidden. I prefer to avoid masking it since this will go on top of another canvas, which covers the whole screen.
Code
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
ctx.rect(20,20,100,100);
ctx.stroke();
ctx.closePath();
ctx.beginPath();
ctx.arc(70, 90, 60, 0, Math.PI * 2, false)
ctx.stroke();
ctx.restore();
<html>
<body>
<canvas id="canvas"></canvas>
</body>
</html>
You can clip() the circle, like so;
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
ctx.rect(20,20,100,100);
ctx.stroke();
ctx.closePath();
ctx.clip(); // clip circle
ctx.beginPath();
ctx.arc(70, 90, 60, 0, Math.PI * 2, false)
ctx.stroke();
ctx.restore();
<html>
<body>
<canvas id="canvas"></canvas>
</body>
</html>
This is the dimensions I've adjusted for cropping the outside part of sqaure
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
ctx.rect(20,20,100,100);
ctx.stroke();
ctx.closePath();
ctx.beginPath();
ctx.arc(70, 90, 60, 10, -4*Math.PI * .05 , false)
ctx.stroke();
ctx.restore();
<html>
<body>
<canvas id="canvas"></canvas>
</body>
</html>
I have a HTML5 canvas and Javascript. How can I make it move like move it's arms and feet?
I tried Googling for some tutorials but failed.
Attached here is my image and my codes:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="canvascss.css">
</head>
<body>
<div>
<canvas id="canvas" width="400px" height="300px" >
Your browser does not support HTML5 Canvas element
</canvas>
</div>
<script>
var canvas = document.getElementById("canvas");
if (canvas.getContext("2d")) { // Check HTML5 canvas support
context = canvas.getContext("2d"); // get Canvas Context object
context.beginPath();
context.fillStyle = "black"; // #ffe4c4
context.arc(200, 50, 30, 0, Math.PI * 2, true); // draw circle for head
context.fill();
context.beginPath();
context.strokeStyle = "black"; // color
context.lineWidth = 3;
context.arc(200, 50, 20, 0, Math.PI, false); // draw semicircle for smiling
context.stroke();
// eyes
context.beginPath();
context.fillStyle = "black"; // color
context.arc(190, 45, 3, 0, Math.PI * 2, true); // draw left eye
context.fill();
context.arc(210, 45, 3, 0, Math.PI * 2, true); // draw right eye
context.fill();
// body
context.beginPath();
context.moveTo(200, 80);
context.lineTo(200, 180);
context.strokeStyle = "black";
context.stroke();
// arms
context.beginPath();
context.strokeStyle = "black"; // blue
context.moveTo(200, 80);
context.lineTo(150, 130);
context.moveTo(200, 80);
context.lineTo(250, 130);
context.stroke();
// legs
context.beginPath();
context.strokeStyle = "black";
context.moveTo(200, 180);
context.lineTo(150, 280);
context.moveTo(200, 180);
context.lineTo(250, 280);
context.stroke();
}
</script>
</body>
</html>
Result:
From HTML5 Canvas Animation with requestAnimFrame:
To create an animation using HTML5 Canvas, we can use the
requestAnimFrame shim which enables the browser to determine the
optimal FPS for our animation. For each animation frame, we can
update the elements on the canvas, clear the canvas, redraw the
canvas, and then request another animation frame.
In short your point of departure is the following:
requestAnimationFrame
You will need a javascript function to CHANGE aspects of your starting image, and then to call that javascript code at regular intervals.
setInterval is another key word to google and learn from.