2D Canvas (behind a 3D Canvas) not drawing images - javascript

I'm currently exploring with Three.js, and working on a small project of mine.
The project consists on having a canvas focused on 3D models and animations, and another one behind, which handles the simpler 2D work.
I've set up the 3D canvas properly, so it's background is transparent, and I can see boxes I draw manually on the 2D canvas, which leads me to assume the setup is right.
The issue I'm having is when it comes to images. I simply cannot get an image to display on the 2D canvas. I've experimented on a separate project, and could draw Images there, no problem. The code is pretty basic, and I actually found it here, but is as follows:
window.onload = function() {
var canvas = document.getElementById('bgcanvas');
var context = canvas.getContext('2d');
var logoText = new Image();
logoText.onload = function() {
context.drawImage(logoText, 69, 50);
};
logoText.src = 'images/logotext.png';
}
#canvas {
position: fixed;
z-index: 0;
}
#bgcanvas {
z-index: -10;
position: fixed;
width: 100vw;
height: 100vh;
}
<div id="fixedContainer">
<canvas id="bgcanvas"></canvas>
<canvas id="canvas"></canvas>
</div>
What's going on that I'm unaware of?
Massive thanks in advance!
UPDATE EDIT: The issue was that I had an image on which the top left corner was transparent, and didn't know the image would stretch. user3412847's comment helped me figure it out

Specifying image width and height is a good habit to get into. Use this syntax: context.drawImage(image, x, y, width, height).
Hope this helps.

I'm guessing you don't have an image at that path; It works fine for me with a valid image (eg: http://lorempixel.com/100/100):
window.onload = function() {
var canvas = document.getElementById('bgcanvas');
var context = canvas.getContext('2d');
var logoText = new Image();
logoText.onload = function() {
context.drawImage(logoText, 69, 50);
};
logoText.src = 'http://lorempixel.com/100/100';
}
#canvas {
position: fixed;
z-index: 0;
}
#bgcanvas {
z-index: -10;
position: fixed;
width: 100vw;
height: 100vh;
}
<div id="fixedContainer">
<canvas id="bgcanvas"></canvas>
<canvas id="canvas"></canvas>
</div>

Related

Split parts from a regular sized image sheet into separate images with JS

I am trying to display parts from an image sheet into separate images.
There's a way to do it with CSS, as in how Reddit Flairs work on the old version of Reddit.
Below is an image that acts as a sheet. I am going to call it unicode_page_00.png
body {
background-color: rgb(20, 20, 20);
}
<body>
<div>
<div style="background: url(https://i.stack.imgur.com/GxJOx.png); image-rendering: pixelated; width: 64px; height: 64px; background-size: 1024px; background-position: -64px 0px;">
</div>
</div>
<br>
<div>
<img src="https://i.stack.imgur.com/GxJOx.png">
</div>
</body>
https://jsfiddle.net/0ztpr5cq/1/
 
The first part displays an image taken from the image sheet. For this example, the sheet is 256x256 pixels and each character is 16x16 pixels.
I took it and zoomed it in by 4. So the first image shows as 64x64. Then I've shifted the position to display the second character on the sheet from left to right.
And below is the entire image sheet for demonstration.
This is done with CSS. The issue is that you can not save the image the way it was cropped and modified with CSS. Even if it would be made possible with CSS, it would take the entire image sheet and save that instead.
I am trying to display every character on the image sheet as separate images. That you could then freely zoom in with the pixelated effect.
 
The idea that I have is to turn them into Base64 or something and make the modifications there or before. And at the end, display the final result back into an image, as base64 or blob or other. And that all with the help of JavaScript.
But how would it work? What would the actual process be?
A good solution I came up with was this https://jsfiddle.net/1rmya08u/
You would have to use the canvas element. Here's the solution:
<canvas id="canvas" width="64" height="64"></canvas>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.imageSmoothingEnabled = false; // For pixelated drawing
var sheet = new Image();
sheet.src = "https://i.stack.imgur.com/GxJOx.png";
sheet.onload = function () {
var sx = 0;
var sy = 0;
var sWidth = 16;
var sHeight = 16;
var dx = 0;
var dy = 0;
var dWidth = 64;
var dHeight = 64;
ctx.drawImage(sheet, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
};
We're taking a 16x16 sample from the image sheet and rendering it at 64x64. For a better understanding of these arguments, take a look at the reference for ctx.drawImage()
And finally, you can get the result as an image with HTMLCanvasElement.toDataURL()

Trying to refresh specific canvas element

I'm simply trying to refresh a canvas element.
I've tried doing this
function reload(){
var container = document.querySelectorAll('[canvas]');
var content = container.innerHTML;
container.innerHTML= content;
console.log("Refreshed"); //Watches console.
}
But it simply doesn't refresh the canvas element? I can use Jquery on the site if it's easier.
Here is the HTML of the canvas element.
<canvas width="800" height="500" style="position: absolute; top: 39px; left: 136px; background-color: transparent; z-index: 10;"></canvas>
If you can help me find a solution please.
You should get the container using querySelector
var container = document.querySelector('canvas');
or querySelectorAll
var container = document.querySelectorAll('canvas')[0];
Now, you attempt to refresh the canvas by changing its inner HTML to the formerly known HTML value:
var content = container.innerHTML;
container.innerHTML= content;
console.log("Refreshed"); //Watches console.
if changing the inner HTML of the canvas would refresh it, then it is a hacky approach and it should only work according to my opinion if the HTML actually changes. Instead, it would be better to just store the content of the canvas somewhere, then clear it:
ctx.clearRect(0, 0, canvas.width, canvas.height);
and draw it again.
Currently theres a few issues. First, [canvas] should be just canvas. Second, you are using querySelectorAll which returns a NodeList of all canvas objects. So either, use that but then loop over it to update all canvases, or change to querySelector which returns just one. And I would recommend using an ID in that case.
Also, this might seem silly but are you calling the function? Or just defining it?
Here it is with querySelectorAll and canvas:
function reload(){
var canvases = document.querySelectorAll('canvas');
for(let canvas of canvases) {
var ctx = canvas.getContext("2d");
var content = ctx.getImageData(0, 0, canvas.width, canvas.height);
ctx.putImageData(ctx,0,0)
console.log("Refreshed"); //Watches console.
}
}
<canvas width="800" height="500" style="position: absolute; top: 39px; left: 136px; background-color: transparent; z-index: 10;"></canvas>
You are wrong in using document.querySelectorAll(). Since you are selecting a single target, you should use document.querySelector(). Try this.
function reload(){
var container = document.querySelector('canvas');
var content = container.innerHTML;
container.innerHTML = content;
console.log("Refreshed");
}

How to change the shape of the canvas itself?

I'm working on a project and I use createCapture(VIDEO); using p5js libraries, to get the video using my web camera. Then I store every image of that capture (from < video> element) and draw it in a canvas in the function draw().
I was wondering if it's possible the change the shape of the canvas(such as a mirror for example (oval or circle)).
Again, notice that I don't want to crop the image but the canvas itself.
Here is some code:
function setup(){
canvas = createCanvas(640, 480); //480p
canvas.parent('editedCanvas-container');
originalCapture = createCapture(VIDEO);
originalCapture.parent('originalVideo-container');
originalCapture.size(640, 480); //480p
}
function draw(){
frame = image(originalCapture, 0, 0, width, height);
}
If somebody has a clue please let me know.
You can change the shape of your canvas tag by applying css rules,
So try this css code
#canvasObject {
border: 2px solid black;
width: 200px;
height: 150px;
border-radius: 100px / 50px;
}
<canvas id="canvasObject">
</canvas>
For more info about how to achieve shapes in css, please refer this amazing post for css-tricks

Is there any way to make an html5 canvas element resizeable?

Is there a native solution that provides a handle in the corner of my HTML5 canvas similar to that in a default <textarea> element.
<textarea>resizeable</textarea>
I assume this will clear the canvas and will require a redraw as this is the case when resizing the canvas programmatically with canvas.width and canvas.height.
I looked around and found nothing, but wanted to check before rolling my own. If anyone is sure that there is no "easy" way, then that is a perfectly acceptable answer. Thanks!
The best I could come up with was use jQueryUI Resizable like so
jsFiddle : https://jsfiddle.net/n24dbaw9/
Html
<div class="resizable">
<canvas id="myCanvas"></canvas>
</div>
CSS
.resizable{
width: 400px;
height: 400px;
}
#myCanvas{
width: 100%;
height: 100%;
}
Javascript
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "#777";
$(function() {
$(".resizable").resizable();
});
setInterval(function(){ ctx.fillRect(0, 0, 400, 400); }, 3);
Basically I have styled the canvas to fit inside of the "resizble" div, which is set to 400 by 400 at default. The canvas has a style which is 100% width and height so when the user resizes the "resizble" div the canvas will then just stretch out.
You will want to put the canvas into a JavaScript draw() function:
function draw() {
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext('2d');
ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;
}
and your body element in css should have height and width set to 100%

How to draw a background image on an HTML5 canvas

I'm working on my first HTML5 Canvas game. I am trying to put in a background image, and I don't know how to do it. The game will change backgrounds throughout levels, but I think I understand how to make that happen. However, if I just try to draw an image, then it appears above my title text. Any ideas how to fix this? I don't think the CSS method will work, because the background will change. Here is my code:
<!DOCTYPE html>
<html>
<head>
<title>How Well Do You Know Your Swedish?</title>
</head>
<body>
<canvas width="640" height="480" id="game" style="display: block; margin-left: auto; margin-right: auto; border: 1px solid black;" Your Browser is not compatible with this game. We recommend Google Chrome, Mozilla Firefox, or Opera.></canvas>
<script>
var game_canvas = document.getElementById("game");
var game_context = game_canvas.getContext("2d");
var swedishflagbg = new Image();
swedishflagbg.src = "resources/images/swedishflagbg.png";
swedishflagbg.onload = function() {
game_context.drawImage(swedishflagbg, 0, 0);
}
game_context.fillStyle = "#000000";
game_context.font = "35px Ubuntu";
game_context.textAlign = "center";
game_context.textBaseline = "top";
game_context.fillText("How Well Do You Know Your Swedish?", 320, 0);
</script>
</body>
</html>
I am new to JavaScript, and even newer to the HTML5 Canvas.
Extending from comment:
The "why":
Because the background image is drawn in an onload event, which will happen "later", while text is drawn immediately.
So the text is drawn first, and then sometimes later the image is drawn, thus causing the text to be covered.
The "how":
Depending on how "dynamic" the background image is, you can consider:
use CSS background-image on cancas/canvas container, and use className/classList to switch between different backgrounds;
put an <img> tag underneath the canvas, and change its src property;
use an additional "background" canvas underneath the current one, so you can draw the game content in current one, and draw the (probably not frequently-updated) background in the new one.
Credit of idea 1 and 2 goes to #markE :)
First things:
Check the size of your image. It should be equivalent to the size of the canvas.
context.drawImage can also take width and height parameter for the image.
Syntax: context.drawImage(img, x, y, width, height);
After editing, it should look like this
let game_canvas = document.getElementById("game");
let game_context = game_canvas.getContext("2d");
let swedishflagbg = new Image();
swedishflagbg.src = "resources/images/swedishflagbg.png";
swedishflagbg.onload = function() {
game_context.drawImage(swedishflagbg, 0, 0, game_canvas.width, game_canvas.height);
}
game_context.fillStyle="#000000";
game_context.font="35px Ubuntu";
game_context.textAlign="center";
game_context.textBaseline="top";
game_context.fillText("How Well Do You Know Your Swedish?", 320, 0);
To anyone who is still facing the problem of background image overlaying text (Image above text), I thought "why not drawing text inside onload function after loading bg image!?"
And it worked!! The browser (Or whatever) loads image first and load my text above image.
<canvas width="534" height="104" id="game" style="display: block; margin-left: auto; margin-right: auto; border: 1px solid black;" Your Browser is not compatible with this game. We recommend Google Chrome, Mozilla Firefox, or Opera.></canvas>
<script>
let game_canvas = document.getElementById("game");
let game_context = game_canvas.getContext("2d");
let swedishflagbg = new Image();
swedishflagbg.src = "./img/logo1.png";
swedishflagbg.onload = function() {
game_context.drawImage(swedishflagbg, 0, 0, game_canvas.width, game_canvas.height);
game_context.fillStyle = "#000000";
game_context.font = "35px Ubuntu";
game_context.textAlign = "center";
game_context.textBaseline = "top";
game_context.fillText("How Well Do You Know Your Swedish?", 320, 0);
}
</script>

Categories

Resources