I need to make some repetitions but I'm not really sure how to make it, when the user clicks the button "Part one" it should display the pig drawing every 100 pixels to the right and when the user clicks parte two it should display a circle of pigs in the center of the canvas but it has to delete the function that part one did.
can someone help me please?
"use strict";
let ctx;
function setup() {
let canvas = document.getElementById("myCanvas");
ctx = canvas.getContext("2d");
drawPig();
}
function drawPig() {
ctx.fillStyle = "pink"
ctx.beginPath();
ctx.arc(25, 40, 15, 0, 2 * Math.PI);
ctx.fill();
ctx.beginPath();
ctx.arc(40, 25, 10, 0, 2 * Math.PI);
ctx.fill();
ctx.fillRect(45, 20, 10, 10);
ctx.fillStyle = "black"
ctx.beginPath();
ctx.arc(42, 18, 1.5, 0, 2 * Math.PI);
ctx.fill();
ctx.beginPath();
ctx.moveTo(35, 50);
ctx.lineTo(50, 60);
ctx.moveTo(35, 50);
ctx.lineTo(35, 62);
ctx.moveTo(15, 50);
ctx.lineTo(5, 60);
ctx.moveTo(15, 50);
ctx.lineTo(15, 60);
ctx.stroke();
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Repetitions</title>
<script src="javascript.js" type="text/javascript"></script>
</head>
<body onload="setup()">
<h1>Repeat</h1>
<canvas id="myCanvas" height="500" width="500" style="border: 1px solid black"></canvas>
<br>
<button onclick="firstPart"> First Part</button>
<button onclick="secondPart">Second Part</button>
</body>
</html>
You can use CanvasRenderingContext2D.translate:
for (int i=0; i<ctx.canvas.width; i+=100){
for (int j=0; j=ctx.canvas.height; j+=100){
ctx.translate(i,j);
drawPig();
ctx.translate(-i,-j);
}
}
This will draw a pig every 100 px. You could use a similar function do draw something else.
As for clearing the canvas, you can use ctx.clearRect(clearRect(0, 0, canvas.width, canvas.height); to set all pixels to 0 alpha black. You can also use this function to clear only part of the canvas if you so desire.
Related
I've got a very simple HTML page with a Canvas element.
When I pass the 4th parameter of arc as Math.PI * 2, I get the red circle I expect, but when I try to do the same thing passing 3.1415 * 2, I get no red circle.
I expect that in both cases I would get the same result with a red circle.
const canvas = document.getElementById("solar-canvas");
const context = canvas.getContext("2d", { alpha: false });
context.beginPath();
context.fillStyle = "red";
//const val = Math.PI * 2;
const val = 3.1415 * 2;
context.arc(190,150, 9, 0, val, true);
context.fill();
context.closePath();
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Simple Solar System</title>
</head>
<body>xxx
<canvas
id="solar-canvas"
width="380"
height="300"
style="border: 1px solid #aaaaaa"
></canvas>
</body>
</html>
I think what you are experiencing is best seen on an example:
const canvas = document.getElementById("canvas");
const context = canvas.getContext("2d");
let end = 0
function draw() {
context.clearRect(0, 0, 90, 90)
context.beginPath()
context.arc(22, 40, 20, 0, end, true);
context.stroke();
context.beginPath()
context.arc(65, 40, 20, 0, end);
context.fillText(end, 10,10)
context.stroke();
end += 0.05
}
setInterval(draw, 100)
<canvas id="canvas" width="90" height="90"></canvas>
3.1415 * 2 is close to Math.PI * 2 but not exactly the same...
It's not failing just the arc is very small
PI 3.14159265... could be rounded to 3.1416
if you use that in your counterclockwise arc you will get the full circle.
There is some weirdness with that last parameter counterclockwise why with big numbers it keeps deleting the arc that might be an interesting question to look into
I am struggling to make this canvas drawing to zoom in and out and panning it. There are some examples with panning and zooming images but my case is different and I don't know what or how should I do it in my case cause it is not images. I would appreciate any tips or any library that you could suggest?
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
canvas{border:#666 1px solid;}
</style>
<script type="application/javascript" language="javascript">
window.onload=draw;//execute draw function when DOM is ready
function draw(){
//assign our canvas element to a variable
var canvas=document.getElementById('canvas1');
//create the html5 context object to enable draw methods
var ctx=canvas.getContext("2d");
ctx.beginPath();
ctx.arc(150, 200, 20, 0, 2 * Math.PI);
ctx.fill();
ctx.beginPath();
ctx.moveTo(150,200);
ctx.lineTo(230,75);
ctx.stroke();
ctx.beginPath();
ctx.arc(230, 75, 20, 0, 2 * Math.PI);
ctx.fill();
ctx.beginPath();
ctx.moveTo(230,75);
ctx.lineTo(300,200);
ctx.stroke();
ctx.beginPath();
ctx.arc(300,200, 20, 0, 2 * Math.PI);
ctx.fill();
ctx.beginPath();
ctx.moveTo(300,200);
ctx.lineTo(150,200);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(300,200);
ctx.lineTo(225,300);
ctx.stroke();
ctx.beginPath();
ctx.arc(225,300, 20, 0, 2 * Math.PI);
ctx.fill();
//fillStyle (r, g, b, alpha)
//ctx.fillStyle = "rgba(0,200,0,1)";
//fillRect (X, Y, Width, height)
//ctx.fillRect(36,10,220,120);
}
</script>
</head>
<body>
<center>
<canvas id="canvas1" width="800" height="600" ></canvas>
</body>
</html>
This is a screenshot of my drawing that I am trying to make it zoom in mouse cursor:
canvas drawing
Panzoom (https://github.com/timmywil/panzoom) says that it supports panning and zoom basically any HTMLElement, including a canvas:
Panzoom uses CSS transforms to take advantage of hardware/GPU
acceleration in the browser, which means the element can be anything:
an image, a video, an iframe, a canvas, text, WHATEVER.
If you're okay with buttons instead of "drag to pan", you can use translate method for panning. You can also use save() and restore() methods or following approach. Here's what I used in similar situation, but I've used buttons:
<html>
<head>
<script>
window.onload = function() {
scale = 1;
canvas = document.getElementById("canvas"); //Replace with id of your canvas
ctx = canvas.getContext("2d");
ctx.translate(150, 75);
drawcanvas();
}
function drawcanvas() {
ctx.beginPath();
//call to function(s) which draws necessary things
//..
//..
drawarrow(ctx);
ctx.stroke();
}
function clearcanvas() {
let current_transform = ctx.getTransform();
ctx.setTransform(1.1, 0, 0, 1.1, 0, 0);
ctx.clearRect(0, 0, canvas.width*scale, canvas.height*scale);
ctx.setTransform(current_transform);
}
function zoomin() {
clearcanvas();
scale = 1.1;
ctx.scale(scale, scale);
drawcanvas();
}
function zoomout() {
clearcanvas();
scale = 1.0/1.1;
ctx.scale(scale, scale);
drawcanvas();
}
function moveleft() {
clearcanvas();
ctx.translate(-10, 0);
drawcanvas();
}
function moveright() {
clearcanvas();
ctx.translate(10, 0);
drawcanvas();
}
</script>
</head>
<body>
<canvas id="c" class="container h-75" style="border: solid 1px blue"></canvas><br />
<button onclick="zoomin()" class="btn btn-dark">+</button>
<button onclick="zoomout()" class="btn btn-dark">-</button>
<button onclick="moveleft()" class="btn btn-dark"><-</button>
<button onclick="moveright()" class="btn btn-dark">-></button>
</body>
</html>
EDIT: I found better solution for panning problem, check this question and it's accepted answer.
Hey guys i have the below design to create
Now i usually use a image in such a situation ,but was just wondering if this was possible in any other way I.E. maybe canvas ? I have just started learning canvas , so i can't say for certain.
FIDDLE HERE
HTML:
<div class='bnr'></div>
<div class='main'></div>
CSS:
.bnr {
height: 35vh;
background: #990853;
}
.main {
background: #fff;
height: 80vh;
}
Now how do i add those curved lines apart from using an image ?
Thank you.
<body onload="draw();">
<canvas id="canvas" width="985px" height="300px" ></canvas>
</body>
<script>
function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(10,10);
ctx.lineTo(985,10);
ctx.lineTo(985,245);
ctx.quadraticCurveTo(965,270,965,280);
ctx.quadraticCurveTo(920,130,640,150);
ctx.quadraticCurveTo(530,160,350,190);
ctx.quadraticCurveTo(210,220,10,190);
ctx.lineTo(10,10);
ctx.stroke();
ctx.strokeStyle="#FFF";
ctx.fillStyle = "green";
ctx.fill();
ctx.beginPath();
ctx.moveTo(10,10);
ctx.lineTo(985,10);
ctx.lineTo(985,220);
ctx.quadraticCurveTo(965,230,955,255);
ctx.quadraticCurveTo(920,130,640,135);
ctx.quadraticCurveTo(510,140,350,170);
ctx.quadraticCurveTo(190,200,10,160);
ctx.lineTo(10,10);
ctx.stroke();
ctx.strokeStyle="#FFF";
ctx.fillStyle = "#990853";
ctx.fill();
ctx.beginPath();
ctx.arc(805, 150, 50, 0, 2 * Math.PI);
ctx.stroke();
ctx.strokeStyle="#FFF";
ctx.fillStyle = "#FFF";
ctx.fill();
ctx.beginPath();
ctx.arc(805, 150, 45, 0, 2 * Math.PI);
ctx.stroke();
ctx.strokeStyle="#FFF";
ctx.fillStyle = "#ce758b";
ctx.fill();
}
}
</script>
That how it looks with the previous code :
You can use canvas for obtain exaclty what you want. Use fill for background color and curve.
You can learn more about canvas:
canvas : http://www.w3schools.com/html/html5_canvas.asp
curve : http://www.w3schools.com/tags/canvas_beziercurveto.asp and http://www.w3schools.com/tags/canvas_quadraticcurveto.asp
fill : http://www.w3schools.com/tags/canvas_fill.asp
a lot of tutorial : http://www.html5canvastutorials.com/
Try my demo:
https://jsfiddle.net/pjxgLkm7/2/
Or
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.moveTo(0,0);
ctx.bezierCurveTo(0,50,20,50,200,0);
ctx.fillStyle = "#990853";
ctx.fill();
ctx.strokeStyle = '#990853';
ctx.stroke();
<canvas id="myCanvas" style="width:100%"></canvas>
I have this simple code of setting rectangle.
I'm stroking its border with a black color.
However , I dont see any black here but gray.
<!doctype html>
<html lang="en">
<canvas id="canvas" width=300 height=300></canvas>
<script>
function draw()
{
ctx.beginPath();
ctx.strokeStyle = "#000000";
ctx.strokeRect(rect.x, rect.y, rect.w, rect.h);
}
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
var rect = {
x: 10,
y: 10,
w: 40,
h: 100
};
draw();
</script>
</html>
Question :
What am I doing wrong and how can I set the color to be as I define ?
When you create a canvas line, it will make a line passing through the points you declared, and with a width of lineWidth. If the line is between 2 pixels (for example when you create a line passing through borders, meaning you choose integer values for x and y) it will dissolve the color to balance the 2 pixels your line is crossing, in this case 50% to the pixel on the left, and 50% to the pixel on the right, resulting in a greyish color.
Adding .5 to your x and y makes the line always stay in 1 pixel
<!doctype html>
<html lang="en">
<canvas id="canvas" width=300 height=300></canvas>
<script>
function draw()
{
ctx.beginPath();
ctx.strokeStyle = "#000000";
ctx.strokeRect(rect.x, rect.y, rect.w, rect.h);
}
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
var rect = {
x: 10.5,
y: 10.5,
w: 40,
h: 100
};
draw();
</script>
</html>
If you run the snippet you'll see that the lines are straight black, and occupying only 1 pixel in width. I just added .5 to your x and y
Alright so ive looked around and found a code that will successfulyl enable me to draw a circle on canvas and use that circle as a mask for my image.
The code looks like this: (codus to the real creater that i dont know)
var ctx = document.getElementById('your_canvas').getContext("2d");
ctx.arc(100,100, 50, 0, Math.PI*2,true); // you can use any shape
ctx.clip();
var img = new Image();
img.addEventListener('load', function(e) {
ctx.drawImage(this, 0, 0, 200, 300);
}, true);
img.src="/path/to/image.jpg";
Lets assume I want to have 5 different circles all with different images and all and each positioned differently.
Anyone got an idea on how id go about that?
To keep the code short, create a function with parameters for the settings that will change from image to image.
Reusable function:
function drawImageCircle(ctx, circleX, circleY, radius,
imageX, imageY, imageWidth, imageHeight, imageUrl) {
var img = new Image();
img.onload = function(){
ctx.save();
ctx.beginPath();
ctx.arc(circleX, circleY, radius, 0, Math.PI*2, true);
ctx.clip();
ctx.drawImage(this, imageX, imageY, imageWidth, imageHeight);
ctx.restore();
};
img.src = imageUrl;
}
var ctx = document.getElementById('your_canvas').getContext("2d");
drawImageCircle(ctx, 100,100, 50, 0,0, 200,300, 'image1.jpg');
drawImageCircle(ctx, 400,400, 50, 300,300, 200,300, 'image2.jpg');
The use of save() and restore() is important when doing this more than once.
Yep, pretty much what Matt said...
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/Vu2Fm/
You can improve this code by using an image preloader to load all 5 of your images prior to drawing on the canvas.
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var img1=new Image();
img1.onload=function(){
var img2=new Image();
img2.onload=function(){
// draw a clipping circle and then an image to clip
ctx.save();
ctx.beginPath();
ctx.strokeStyle="blue";
ctx.arc(100, 100, 50, 0 , 2 * Math.PI, false);
ctx.stroke();
ctx.clip();
ctx.beginPath();
ctx.arc(100, 100, 50, 0 , 2 * Math.PI, false);
ctx.drawImage(img1,10,0);
ctx.restore();
// draw a second clipping circle and then an image to clip
ctx.save();
ctx.beginPath();
ctx.strokeStyle="green";
ctx.arc(275, 100, 75, 0 , 2 * Math.PI, false);
ctx.stroke();
ctx.clip();
ctx.beginPath();
ctx.drawImage(img2,150,0);
ctx.restore();
}
img2.src="http://dl.dropbox.com/u/139992952/coffee.png";
}
img1.src="http://dl.dropbox.com/u/139992952/house%20vector.png";
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=400 height=250></canvas>
</body>
</html>