I have a simple canvas in which I'm drawing a rectangle using Rough.js library. The issue I'm having is Rough js randomizing the draw pattern so each time the rectangle method is called, it seems to shake/jitter inside requestAnimationFrame. I'm not too familiar with the library I'm wondering if anyone here has any experience to either set some constants to force the rectangle to be drawn the exact same way or disable randomisation altogether.
<html>
<head>
<script type='text/javascript' src="https://unpkg.com/roughjs#4.3.1/bundled/rough.js"></script>
</head>
<body>
<canvas id="canvas" width="480" height="640"></canvas>
</body>
<script>
window.addEventListener('DOMContentLoaded',event=>{
let canvas = document.getElementById("canvas");
let ctx = canvas.getContext('2d');
let r = rough.canvas(canvas);
function draw(tick){
requestAnimationFrame(draw);
ctx.clearRect(0,0,480,640);
r.rectangle(50, 50, 80, 80, {
fill: 'rgba(255,0,200,0.2)',
fillStyle: 'solid' // solid fill
});
}
requestAnimationFrame(draw);
});
</script>
</html>
When you run the snippet you can see the jittering/shaking. That's what I wish to disable.
You'll want to use the RoughGenerator to create a rectangle instruction once and reuse it:
const canvas = document.querySelector("canvas")
const ctx = canvas.getContext("2d");
const r = rough.canvas(canvas);
// First we set up a rectangle
const rect = r.generator.rectangle(50, 50, 80, 80, {
fill: 'rgba(255,0,200,0.2)',
fillStyle: 'solid' // solid fill
});
(function draw(tick) {
requestAnimationFrame(draw);
ctx.clearRect(0, 0, 480, 640);
// Then we draw it as many times as we want
r.draw(rect);
})();
<script src="https://unpkg.com/roughjs#4.3.1/bundled/rough.js"></script>
<canvas></canvas>
Related
I'm new to image processing. I found the "gpu.js" package and it seems to be very powerful for any kind of image operations in the browser, but there is not much information on google about it and I don't understand how to use it properly.
What I'm trying to do now: I've drawn a canvas with a black (0,0,0) background. I also overlaid a few pixels of different colors on it. I want to get the coordinates (x, y) of all exact RGB pixels on the canvas but I am stuck on this and I don't even see is it possible.
The code for canvas:
const draw = async () => {
const canvas = document.createElement('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
canvas.style.backgroundColor = 'rgb(0,0,0)'
document.body.appendChild(canvas);
const ctx = canvas.getContext('2d');
ctx.fillStyle = "rgb(234,0,255)";
ctx.fillRect(100,100,1,1);
ctx.fillStyle = "rgb(0,0,255)";
ctx.fillRect(600,600,1,1);
ctx.fillStyle = "rgb(0,255,0)";
ctx.fillRect(600,450,1,1);
ctx.fillStyle = "rgb(0,254,253)";
ctx.fillRect(230,230,1,1);
ctx.fillStyle = "rgb(140,8,9)";
ctx.fillRect(230,118,1,1);
}
draw();
const gpu = new GPU({mode: "gpu"});
* {
margin: 0;
padding: 0;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>GPU</title>
<script src="https://cdn.jsdelivr.net/npm/gpu.js#latest/dist/gpu-browser.min.js"></script>
<style>
</style>
</head>
<body>
</body>
</html>
For example I'd like to find coordinates of pixels with colors rgb(234,0,255) and rgb(140,8,9)
What should I do to achieve it?
I am using this jQuery plugin to make free drawing over a canvas.
I want to clear the canvas for redrawing but after I do and when I click inside canvas for redrawing the old drawing that I cleared appears again
$('#canvasFirst').sketch();
$('button').on("click", (evt) => {
var canvas = document.getElementById('canvasFirst');
let context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
});
canvas { border: 1px solid; vertical-align: top }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/mobomo/sketch.js#master/lib/sketch.min.js"></script>
<p>Draw on the below canvas, then press "clear" and try to draw again.</p>
<canvas id="canvasFirst">
</canvas>
<button>clear</button>
This plugin stores all the drawing commands in an actions array, and at each redraw it will go through that whole list and draw the full thing again. (Which allows to avoid having holes in your stroke).
The docs are very hard to grasp, but you can set this options's content through the .sketch("options", value) method.
As hinted in this issue, setting it to an empty Array will thus remove all the previous commands. All you have to do then is to redraw the whole scene, now empty:
const $canvas = $('#canvasFirst');
$canvas.sketch();
$('button').on("click", (evt) => {
$canvas.sketch("actions", []);
$canvas.sketch("redraw");
});
canvas { border: 1px solid; vertical-align: top }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/mobomo/sketch.js#master/lib/sketch.min.js"></script>
<p>Draw on the below canvas, then press "clear" and try to draw again.</p>
<canvas id="canvasFirst">
</canvas>
<button>clear</button>
You can try to save the state of the canvas as a blob. For example, as image/png.
There are two bad things here:
A small inconvenience. Methods for converting a blob to an image and back are asynchronous. Promises have to be used.
Speed. I strongly doubt that this solution is suitable for tasks that require speed - games, videos, etc.
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const saveCanvasState = (canvas) => {
const ctx = canvas.getContext('2d');
ctx.save(); // save state
let blob;
return new Promise((r) => {
canvas.toBlob( // toBlob is async method
(b) => {
blob = b;
r(() =>
new Promise((r) => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.restore();
const img = new Image();
img.addEventListener('load', () => {
URL.revokeObjectURL(img.src);
ctx.drawImage(img, 0, 0);
r();
});
img.src = URL.createObjectURL(blob);
}));
},
'image/png',
1
);
});
};
ctx.fillStyle = 'green';
ctx.fillRect(10, 10, 100, 100);
saveCanvasState(canvas).then((restore) => {
ctx.fillStyle = 'black';
ctx.fillRect(150, 40, 100, 100);
ctx.fillRect(100, 40, 100, 100);
restore().then(() => {
console.log('restored, can draw');
});
});
<canvas id="canvas"></canvas>
How to fill the whole HTML5 <canvas> with one color.
I saw some solutions such as this to change the background color using CSS but this is not a good solution since the canvas remains transparent, the only thing that changes is the color of the space it occupies.
Another one is by creating something with the color inside the canvas, for example, a rectangle(see here) but it still does not fill the whole canvas with the color (in case the canvas is bigger than the shape we created).
Is there a solution to fill the whole canvas with a specific color?
Yes, fill in a Rectangle with a solid color across the canvas, use the height and width of the canvas itself:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
canvas{ border: 1px solid black; }
<canvas width=300 height=150 id="canvas">
If you want to do the background explicitly, you must be certain that you draw behind the current elements on the canvas.
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
// Add behind elements.
ctx.globalCompositeOperation = 'destination-over'
// Now draw!
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
You can change the background of the canvas by doing this:
<head>
<style>
canvas {
background-color: blue;
}
</style>
</head>
let canvas = document.getElementById('canvas');
canvas.setAttribute('width', window.innerWidth);
canvas.setAttribute('height', window.innerHeight);
let ctx = canvas.getContext('2d');
//Draw Canvas Fill mode
ctx.fillStyle = 'blue';
ctx.fillRect(0,0,canvas.width, canvas.height);
* { margin: 0; padding: 0; box-sizing: border-box; }
body { overflow: hidden; }
<canvas id='canvas'></canvas>
We don't need to access the canvas context.
Implementing hednek in pure JS you would get canvas.setAttribute('style', 'background-color:#00F8'). But my preferred method requires converting the kabab-case to camelCase.
canvas.style.backgroundColor = '#00F8'
You know what, there is an entire library for canvas graphics. It is called p5.js
You can add it with just a single line in your head element and an additional sketch.js file.
Do this to your html and body tags first:
<html style="margin:0 ; padding:0">
<body style="margin:0 ; padding:0">
Add this to your head:
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/p5.js"></script>
<script type="text/javascript" src="sketch.js"></script>
The sketch.js file
function setup() {
createCanvas(windowWidth, windowHeight);
background(r, g, b);
}
Images are not drawing to bg_canvas with a z-index of 0, only my main game canvas overlay is showing, i have only included the start of the code.
// HTML
<canvas id="bg-canvas" width="768" height="600"></canvas>
<canvas id="canvas" width="768" height="600"></canvas>
// CSS
canvas {
position: absolute;
top: 0;
left: 0;
}
#canvas {
z-index: 1
}
#bg-canvas {
z-index: 0
}
// Javascript
const bg_canvas = document.getElementById('bg-canvas');
const bg_ctx = bg_canvas.getContext("2d");
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const map = {
object: {
brickwall: new Image(),
woodenbox: new Image()
}
};
map.object.brickwall.src = "objects/brickwall.jpeg";
map.object.woodenbox.src = "objects/boximage.jpg";
ctx.clearRect(0,0,canvas.width,canvas.height);
bg_ctx.clearRect(0,0,bg_canvas.width,bg_canvas.height);
// var currentItemEquipped;
// drawImage(imgsrc, xcoord, ycoord, sizex, sizey) // drawImage parameters
map.object.brickwall.onload = () => bg_ctx.drawImage(map.object.brickwall, 100, 100, 100, 100);
map.object.woodenbox.onload = () => bg_ctx.drawImage(map.object.woodenbox, 200, 200, 100, 100);
The player is drawing and the rest of the code is working completely fine however, i am not able to draw these images to the canvas, it may be a problem with z-indexes or that the overlaying canvas is not transparent.
Have you tried "window.addEventListener" ?
Because sometimes i got the same issue in some browsers...
try this:
function LoadImages(){
bg_ctx.drawImage(map.object.brickwall, 100, 100, 100, 100);
bg_ctx.drawImage(map.object.woodenbox, 200, 200, 100, 100);
}
window.addEventListener("load", LoadImages);
Had to call the function inside the draw method, not sure why though since the background canvas is never cleared.
Please help me to understand the events of the canvas.
Take for example two of the square. Each has its own area where you need to process such events:
Hover the square fills it with colour.
Click invokes filling the square third color and displays in a separate block, for example, the ID of the square.
Accordingly, it is possible to work with only one square. Click on the second square will reset the first square and output data from the second.
While moving the mouse in the area of one of the squares near the mouse, a pop-up window that displays the ID of the square.
And how can I make a link to a separate square? That is, to the user clicks a link that invokes the event, similar to a click on a separate square.
HTML code
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript" src="scripts/canvas.js"></script>
<script>
window.onload = function()
{
drawCanvas('mainCanvas');
};
</script>
</head>
<body style="margin: 0px;">
<canvas id="mainCanvas" width="300" height="200"></canvas>
<aside>ID of the square</aside>
</body>
</html>
JS code
function makeRect(x, y, w, h)
{
return { x: x, y: y, w: w, h: h };
}
function drawCanvas(canvasId)
{
//// General Declarations
var canvas = document.getElementById(canvasId);
var context = canvas.getContext('2d');
//// Color Declarations
var blackColor = 'rgba(0, 0, 0, 1)';
var whiteColor = 'rgba(255, 255, 255, 1)';
//// Frames
var frameOne = makeRect(64, 70, 50, 50);
var frameTwo = makeRect(194, 70, 50, 50);
//// RectangleOne Drawing
context.beginPath();
context.rect(frameOne.x, frameOne.y, 50, 50);
context.fillStyle = whiteColor;
context.fill();
context.strokeStyle = blackColor;
context.lineWidth = 1;
context.stroke();
//// RectangleTwo Drawing
context.beginPath();
context.rect(frameTwo.x, frameTwo.y, 50, 50);
context.fillStyle = whiteColor;
context.fill();
context.strokeStyle = blackColor;
context.lineWidth = 1;
context.stroke();
}
You ask a really broad question!
This will get you started:
About canvas rectangles
When you draw a rect on the canvas it becomes just “painted pixels” (like a painting of a rectangle on an artists canvas).
Nothing about the rect is “remembered” by canvas.
This means you can’t hit-test the rect to see if your mouse is hovering over that rect. The canvas doesn’t know anything about your rect.
Keeping track of rectangles
You must keep track of each rect’s properties yourself (x-coordinate, y-coordinate, width, height, color).
A convienient way to do this is creating a javascript object with the rect’s properties:
var rect1 = { x:30, y:30, width:50, height:25, color:"blue" };
Then use this rect1 object to draw the rect on your canvas
context.fillStyle=rect1.color;
context.fillRect( rect1.x, rect1.y, rect1.width, rect1.height );
Now you can always refer to rect1 to get the properties of your rectangle.
Mouse events
The canvas mouse events always relate to the canvas element itself, never to a rect drawn on the canvas.
Here’s how to listen to the mouse events on canvas:
// use jQuery to ask the browser to call `handleMouseMove` whenever the mouse is moved
$("#canvas").mousemove(function(e){handleMouseMove(e);});
// this is called every time your mouse moves
function handleMouseMove(e){
// get the mouses current X,Y position
// Note: offsetX/offsetY -- you must adjust for the offset of the canvas relative to the web page
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
}
Testing if the mouse is inside the rect
Remember that canvas knows nothing about your rect1, so use the rect1 object to “hit-test” whether the mouse is inside rect1:
if(
mouseX>=rect1.x &&
mouseX<=rect1.x+rect1.width &&
mouseY>=rect1.y &&
mouseY<=rect1.y+rect1.height
){
// the mouse is inside rect1
ctx.fillStyle="red";
ctx.fillRect(rect1.x,rect1.y,rect1.width,rect1.height);
}else{
// the mouse is not inside rect1
ctx.fillStyle=rect1.color;
ctx.fillRect(rect1.x,rect1.y,rect1.width,rect1.height);
}
This introduction should get you started coding…experiment for yourself!
Here’s a working demo: http://jsfiddle.net/m1erickson/tPjWX/
<!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 $canvas=$("#canvas");
var canvasOffset=$canvas.offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var rect1 = { x:30, y:30, width:50, height:25, color:"blue" };
ctx.fillStyle=rect1.color;
ctx.fillRect(rect1.x,rect1.y,rect1.width,rect1.height);
function handleMouseMove(e){
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
if(
mouseX>=rect1.x &&
mouseX<=rect1.x+rect1.width &&
mouseY>=rect1.y &&
mouseY<=rect1.y+rect1.height
){
ctx.fillStyle="red";
ctx.fillRect(rect1.x,rect1.y,rect1.width,rect1.height);
}else{
ctx.fillStyle=rect1.color;
ctx.fillRect(rect1.x,rect1.y,rect1.width,rect1.height);
}
}
$("#canvas").mousemove(function(e){handleMouseMove(e);});
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
Canvas is only an element.
You can catch event for all canvas not for squares, circle, line...
But you can hold the position of square , line, circle and check "if ( mouse's position in square position) and redraw canvas
Personally, you can try to use SVG and you can catch the events for individual element.