Cannot draw text in javascript - javascript

I am trying to display simple text on the screen via update() and setInterval() functions, but it's not working. Note that I create a canvas on which I want the text to be displayed. Please , check the code below.
var canvas, canvasContext;
window.onload = function() {
canvas = document.getElementById('theCanvas');
canvasContext = canvas.getContext('2d');
var fps = 30;
setInterval(update, 1000 / fps);
}
function update() {
drawText();
}
function drawText() {
canvasContext.fillStyle = 'black';
canvasContext.font = 'bold 40px Monospace';
canvasContext.fillText('POC ......', 150, 150);
}
#canvasHolder {
position: absolute;
left: 0px;
top: 0px;
}
#theCanvas {
background-color: lightgreen;
width: 100pc;
height: 100pc;
}
<div id="canvasHolder">
<canvas id="theCanvas"></canvas>
</div>

The issue is that the canvas is being stretched to fill the element. Both the canvas itself and the canvas element have a size. If you don't specify the size of the canvas (you haven't), it defaults to 300x150. When the size of the element and the canvas don't match, the canvas content is scaled to fit into the element.. So the text is being drawn, it's just really big; scroll to the right and down and you'll find it.
My guess is that you meant for the canvas and the element to be the same size. If so, you need to set the size of the canvas. You can do that with width and height attributes on the canvas element, but those values will be in pixels, not picas as in your CSS. So we do it dynamically by getting the computed width and height of the element (because they'll come back to us in pixels), and then setting those values for the width and height attributes of the canvas:
// Set the canvas size to match the element size
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
Updated snippet:
var canvas, canvasContext;
window.onload = function() {
canvas = document.getElementById('theCanvas');
// Set the canvas size to match the element size
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
canvasContext = canvas.getContext('2d');
canvasContext.canvas.width = canvas.width;
canvasContext.canvas.height = canvas.height;
var fps = 30;
setInterval(update, 1000 / fps);
};
function update() {
drawText();
}
function drawText() {
canvasContext.fillStyle = 'black';
canvasContext.font = 'bold 40px Monospace';
canvasContext.fillText('POC ......', 150, 150);
}
#canvasHolder {
position: absolute;
left: 0px;
top: 0px;
}
#theCanvas {
background-color: lightgreen;
width: 100pc;
height: 100pc;
}
<div id="canvasHolder">
<canvas id="theCanvas"></canvas>
</div>
Note that right now, you're just redrawing it at the same location every time, but I assume moving it was your next task...

The text is already rendered but if you want to animate your text then you have to change your draw function because each time you are drawing your text in the same position -
function drawText() {
canvasContext.fillStyle = 'black';
canvasContext.font = 'bold 40px Monospace';
canvasContext.fillText('POC ......', 150, 150); //here you have given the fixed position.
}
and you have to clear your canvas before rendering your text in new position-
please refer -
How to clear the canvas for redrawing

Related

Canvas fill viewport and keep image ratio

I am trying to make the canvas area and image fill the viewport without the image stretching and retain its aspect ratio when you resize the page. Below is my current code.
var ctx = $("#demo")[0].getContext("2d"),
img = new Image(),
radius = 35,
blurryImageSrc = "https://s9.postimg.cc/u9nsmzlwf/image.jpg";
img.src = blurryImageSrc;
$(img).on("load", function() {
resizeCanvas();
$("#demo").on("mousemove", function(e) {
erase(getXY(e));
});
$("#reset").on("click", function() {
ctx.globalCompositeOperation = "source-over";
ctx.drawImage(img, 0, 0);
ctx.globalCompositeOperation = "destination-out";
});
ctx.drawImage(img, 0, 0, window.innerWidth, window.innerHeight);
ctx.globalCompositeOperation = "destination-out";
});
function getXY(e) {
var r = $("#demo")[0].getBoundingClientRect();
return { x: e.clientX - r.left, y: e.clientY - r.top };
}
function erase(pos) {
ctx.beginPath();
ctx.arc(pos.x, pos.y, radius, 0, 2 * Math.PI);
ctx.closePath();
ctx.fill();
}
var can = document.getElementById('demo');
function resizeCanvas() {
can.style.width = window.innerWidth + 'px';
setTimeout(function() {
can.style.height = window.innerHeight + 'px';
}, 0);
}
window.onresize = resizeCanvas;
resizeCanvas();
https://jsfiddle.net/65fph0mn/8/
To retain the image's correct proportions, you need to query it's 'natural' width and height. The image object itself has two properties for this purpose: naturalWidth and naturalHeight.
As the image finished loading you must decide by which factor to scale the image based on the dimensions of the browser window and the longer side of your image.
Let's have a look at a simple example. Say your browser window's width is 1200 pixel and the image 250. If we now divide 1200 by 250 we get 4.8 - that's the factor we need to multiply the image's width and height to fill the current browser window in one direction while maintaining it's correct aspect ratio.
Here's an example:
var ctx = $("#demo")[0].getContext("2d"),
img = new Image(),
radius = 35,
blurryImageSrc = "https://s9.postimg.cc/u9nsmzlwf/image.jpg";
/// setup logic
img.src = blurryImageSrc;
$(img).on("load", function() {
resizeCanvas();
});
var can = document.getElementById('demo');
function resizeCanvas() {
can.width = window.innerWidth;
can.height = window.innerHeight;
if (img.width > 0) {
let factor = can.width / img.naturalWidth * img.naturalHeight > window.innerHeight ? can.height / img.naturalHeight : can.width / img.naturalWidth;
ctx.drawImage(img, 0, 0, img.naturalWidth * factor, img.naturalHeight * factor);
}
}
window.onresize = resizeCanvas;
resizeCanvas();
body {
background: lightgrey;
margin: 0;
}
.container {
position: relative;
background: blue;
width: 100vw;
height: 100vh;
}
#demo {
cursor: crosshair;
width: 100vw;
height: 100vh;
}
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<div class="container">
<canvas id="demo" width=640 height=640></canvas>
</div>
Here I'm waiting for the image to load. Then I can add the eventlistener for window resize and call the function resizeCanvas. This function will then resize the canvas and paint the image in the canvas.
The image must be repainted every time the window is resized.
To keep the aspect ratio the height of the image is calculated from the scaled width.
const canvas = document.getElementById('demo');
var ctx = canvas.getContext("2d"),
img = new Image(),
blurryImageSrc = "https://s9.postimg.cc/u9nsmzlwf/image.jpg";
img.src = blurryImageSrc;
img.addEventListener("load", e => {
window.addEventListener('resize', resizeCanvas);
resizeCanvas();
});
function paint() {
var newHeight = Math.round(img.width/canvas.width*img.height);
ctx.drawImage(img, 0, 0, img.width, newHeight, 0, 0, canvas.width, canvas.height);
}
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
paint();
}
body {
background: lightgrey;
margin: 0;
}
.container {
position: relative;
background: blue;
width: 100vw;
height: 100vh;
}
#demo {
cursor: crosshair;
width: 100vw;
height: 100vh;
}
<div class="container">
<canvas id="demo" width="640" height="640"></canvas>
</div>

Keep canvas object in one place against changing size of the entire canvas

l was wondering about the logic required in-order to position a canvas object, in this instance it is a image, in the bottom right corner of the canvas persistently. l essentially need help with the canvas object staying in one place without it moving up,down,left,right due to the resizable canvas.
l also have tested using event listeners to constantly update the position of the canvas object depending on the window size of the canvas but l believe it would end up becoming an inefficient solution.
To see it working, full screen/expand the code snippet and change your window size by double clicking your browser's tab or simply resize it, then you should be able to see it in action.
var canvas = document.getElementById("c");
var ctx = canvas.getContext("2d");
var the_button = document.getElementById("the_button");
var the_background = document.getElementById("the_background");
var button_imageX = 115;
var button_imageY = 85;
window.onload = function() {
ctx.drawImage(the_background, 0, 0, canvas.width, canvas.height);
ctx.drawImage(the_button, button_imageX, button_imageY, 130, 75);
}
initialize();
function initialize() {
window.addEventListener('resize', resizeCanvas, false);
resizeCanvas();
}
function redraw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(the_background, 0, 0, canvas.width, canvas.height);
ctx.drawImage(the_button, button_imageX, button_imageY, 130, 75);
}
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
redraw();
}
html,
body {
width: 100%;
height: 100%;
margin: 0px;
border: 0;
overflow: hidden;
display: block;
}
<html>
<canvas id="c"></canvas>
<img style="display: none;" id="the_button" src="https://i.imgur.com/wO7Wc2w.png" />
<img style="display: none;" id="the_background" src="https://img.freepik.com/free-photo/hand-painted-watercolor-background-with-sky-clouds-shape_24972-1095.jpg?size=626&ext=jpg" />
</html>
This is all about rectangle geometry.
Basically the culprit is this line that is present at 2 different places.
ctx.drawImage(the_button, button_imageX, button_imageY, 130, 75);
When you want the button to be a certain fixed position when you resize, you should provide fixed values as the 2nd and 3rd params for the drawImage function.
Change it to this,
ctx.drawImage(the_button, button_imageX, canvas.height - button_imageY, 130, 75);
The 2nd param button_imageX is already fixed.
But the 3rd param is the value of y from the top of the canvas where your button should be. Not from the bottom. You must be confused with cartesian coordinate system.
So if you want your button to be always a fixed position from bottom. you should canvas.height.
So canvas.height - button_imageY means that the top left point of your button will always be button_imageY pixels above the bottom of the canvas.
You might also want to consider the height of the button, so the new 3rd parameter will become canvas.height - button_imageY - button_height
Check the snippet for full code.
var canvas = document.getElementById("c");
var ctx = canvas.getContext("2d");
var the_button = document.getElementById("the_button");
var the_background = document.getElementById("the_background");
var button_imageX = 25;
var button_imageY = 25;
window.onload = function() {
ctx.drawImage(the_background, 0, 0, canvas.width, canvas.height);
drawButton();
}
initialize();
function initialize() {
window.addEventListener('resize', resizeCanvas, false);
resizeCanvas();
}
function drawButton() {
ctx.drawImage(the_button, button_imageX, canvas.height - button_imageY - 75, 130, 75);
}
function redraw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(the_background, 0, 0, canvas.width, canvas.height);
drawButton();
}
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
redraw();
}
html,
body {
width: 100%;
height: 100%;
margin: 0px;
border: 0;
overflow: hidden;
display: block;
}
<html>
<canvas id="c"></canvas>
<img style="display: none;" id="the_button" src="https://i.imgur.com/wO7Wc2w.png" />
<img style="display: none;" id="the_background" src="https://img.freepik.com/free-photo/hand-painted-watercolor-background-with-sky-clouds-shape_24972-1095.jpg?size=626&ext=jpg" />
</html>

Scaling canvas shapes with 100% width canvas

I am trying to create an example of a canvas element with 100% width, containing a red square "border" rect. If I set the width of a canvas element in CSS to be 100%, it will successfully grow to fit the full width of the viewport, but the rect is blurred because CSS just stretches the canvas. This is demonstrated here:
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
ctx.strokeStyle = "red";
ctx.strokeRect(0, 0, 300, 150);
canvas {
width: 100%;
}
<canvas></canvas>
I can set the canvas height and width to be equal to clientWidth and clientHeight as demonstrated below, which means the canvas will not bet stretched, but now my canvas context dimensions are no longer 300 x 150, and I won't know what the actual dimensions are in advance. How can do my canvas drawing with predictable dimensions liek 300 x 150, but also scale the canvas element to be 100% width? Webgl has gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); which I believe solves this problem, does canvas have a similar approach, or do you need to scale all the of dimensions of your shapes to have the same scaling that is applied to the canvas element? e.g. multiply by clientWidth / 300 and clientHeight / 150?
const canvas = document.querySelector("canvas");
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
const ctx = canvas.getContext("2d");
ctx.strokeStyle = "red";
ctx.strokeRect(0, 0, 300, 150);
canvas {
width: 100%;
}
<canvas></canvas>
A good solution seems to be using the .scale() method on the canvas context as per below. This way you can work with whatever coordinate system you like in the canvas context.
const canvas = document.querySelector("canvas");
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
const ctx = canvas.getContext("2d");
ctx.scale(canvas.clientWidth / 300, canvas.clientHeight / 150);
ctx.strokeStyle = "red";
ctx.strokeRect(0, 0, 300, 150);
canvas {
width: 100%;
}
<canvas></canvas>

Draw an image on top of another image with an animated element

Initially what I am trying to do is place a blurry image on top of the same image that is clear. Then having another element(div box) that animates across the blurry image showing the clear image. Thus giving the effect like it is a pair of glasses.. Now I KNOW this can be achieved through html5 canvas, however I am not very knowledgable with this api and how to achieve it. There are two things that I am struggling with doing.
The first thing would be to change out the grey fillColor that gets erased so you can see the image behind it, with the blurry image. Now I have attempted to perform the drawImage() function. But cannot seem to get it to work with the current code that I have. Any suggestions or examples would be greatly appreciated.
The second thing would be to have the animating div do the 'erasing' instead of the user performing a mouse down functionality.
Third and last thing (more worried about just getting the first two figured out), would be for the image to go back to the reblur image after the div has moved.
I am open to ideas of better approaches as well. I greatly appreciate any time spent assisting myself.
animateLense();
function animateLense() {
$("#lense").animate({
left: 200,
top: 150
}, 2000 );
}
(function() {
// Creates a new canvas element and appends it as a child
// to the parent element, and returns the reference to
// the newly created canvas element
function createCanvas(parent, width, height) {
var canvas = {};
canvas.node = document.createElement('canvas');
canvas.context = canvas.node.getContext('2d');
canvas.node.width = width || 100;
canvas.node.height = height || 100;
parent.appendChild(canvas.node);
return canvas;
}
function init(container, width, height, fillColor) {
var canvas = createCanvas(container, width, height);
var ctx = canvas.context;
// define a custom fillCircle method
ctx.fillCircle = function(x, y, radius, fillColor) {
this.fillStyle = fillColor;
this.beginPath();
this.moveTo(x, y);
this.arc(x, y, radius, 0, Math.PI * 2, false);
this.fill();
};
ctx.clearTo = function(fillColor) {
ctx.fillStyle = fillColor;
ctx.fillRect(0, 0, width, height);
};
ctx.clearTo(fillColor || "#ddd");
// bind mouse events
canvas.node.onmousemove = function(e) {
if (!canvas.isDrawing) {
return;
}
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
var radius = 10; // or whatever
var fillColor = '#ff0000';
ctx.globalCompositeOperation = 'destination-out';
ctx.fillCircle(x, y, radius, fillColor);
};
canvas.node.onmousedown = function(e) {
canvas.isDrawing = true;
};
canvas.node.onmouseup = function(e) {
canvas.isDrawing = false;
};
// bind mouse end
}
var container = document.getElementById('canvas');
init(container, 300, 250, '#ddd');
})();
.canvas {
position: absolute;
width: 300px;
height: 250px;
left: 0px;
top: 0px;
background: url("http://www.atlantisbahamas.com/media/Things%20To%20Do/Water%20Park/Beaches/Gallery/waterpark_covebeach.jpg");
background-size: 300px, 250px
}
.lense {
position: absolute;
height: 50px;
width: 50px;
border: 2px black solid;
top: 0;
left: 0;
}
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<div class="canvas" id="canvas">
<div class="lense" id="lense"></div>
</div>
</body>
</html>
Just draw two images in the same location.
Draw the second one on top of the first one with:
ctx.globalAlpha = 0.5; // Set to animated value
Animate globalAlpha.
Note: You don't draw images inside <canvas> using HTML elements. You have to load them up via JavaScript and use the drawImage method.

Make canvas fill the whole page

How can I make canvas be 100% in width and height of the page?
Well I have it working here: Are Google's Bouncing Balls HTML5? by using the following CSS:
* { margin: 0; padding: 0;}
body, html { height:100%; }
#c {
position:absolute;
width:100%;
height:100%;
}
Where #c is the id of the canvas element.
you can use these codes without jquery
var dimension = [document.documentElement.clientWidth, document.documentElement.clientHeight];
var c = document.getElementById("canvas");
c.width = dimension[0];
c.height = dimension[1];
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
maybe that easy?
This has something to do with <canvas> tag.
when create fullscreen canvas, <canvas> will cause scrollbar if not set to display:block.
detail: http://browser.colla.me/show/canvas_cannot_have_exact_size_to_fullscreen
You can programatically set the canvas width + height:
// Using jQuery to get window width + height.
canvasObject.width = $(window).width();
canvasObject.height = $(window).height();
I've tested this and it as long as you redraw what's on the canvas after you've resized it won't change the scaling.
on my observations this runs effectively, and gives a blue shade
var c = document.getElementById('can');
var ctx = canvas.getContext('2d');
ctx.rect(0, 0, canvas.width, canvas.height);
// add linear gradient
var g = ctx.createLinearGradient(0, 0, c.width, c.height);
// light blue color
g.addColorStop(0, '#8ED6FF');
// dark blue color
g.addColorStop(1, '#004CB3');
context.fillStyle = g;
context.fill();
<script>
var c = document.getElementById('can');
var ctx = canvas.getContext('2d');
ctx.rect(0, 0, canvas.width, canvas.height);
// add linear gradient
var g = ctx.createLinearGradient(0, 0, c.width, c.height);
// light blue color
g.addColorStop(0, '#8ED6FF');
// dark blue color
g.addColorStop(1, '#004CB3');
context.fillStyle = g;
context.fill();
</scrip
html,body
{
height:98.0%;
width:99.5%;
}
canvas
{
display:block;
width:100%;
height:100%;
}
<html>
<body>
<canvas id="can"></canvas>
</body>
</html>
Does this work for you?
<html>
<body style="height: 100%; margin: 0;">
<canvas style="width: 100%; height: 100%;"></canvas>
</body>
</html>
from Force canvas element in html to take up the entire window?

Categories