html5 canvas background image blur and resize - html

I have an idea of making a canvas the background with an image. The reason why I want the canvas element to be the background is because I would like to blur the image when the user is logged in. I think that would be a nice effect. And since I don't refresh the page I like it to animate a blurring effect. I am going to have multiple questions in here because they all rely on each other.
I have 2 ideas of how to make this. the first one will have a simple div tag with the background image set. then, when the user have logged in - a canvas element will be created by the script with the background image placed as in the div, then blur it and let it fade in over the div tag.
Another way would be to build the canvas element from the beginning and then let the image be set from the beginning.
This is how I make a background image.
var canvas = document.getElementById('bg_canvas');
var context = canvas.getContext('2d');
var imageObj = new Image();
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
imageObj.onload = function() {
context.drawImage(imageObj, 0, 0);
};
imageObj.src = '2.jpg';
Okay.. thats the easy part.. I need a way to make the height or width in the drawImage function set to auto. if the width is bigger than the height I want the height to be set to auto. I don't want the image to be stretched over the screen. How should I do that?
Now problem number 2. When the user resizes the screen, I would like to resize the image inside the canvas element as well. blurred or not blurred.
i assume it would be set to something like this:
$(document).ready(function() {
winResize();
$(window).resize(function() {
winResize());
}
});
function winResize() {
var canvas = document.getElementById('bg_canvas');
var context = canvas.getContext('2d');
var imageObj = new Image();
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
imageObj.onload = function() {
context.drawImage(imageObj, 0, 0, canvas.height, canvas.width);
};
imageObj.src = '2.jpg';
}
Now I still need the auto mechanism for the height or width of the image.
I am not going to ask for the blur effect, since it should be able to find online somewhere, but what i would like to know is what you would recommend for me to do, when fading in the blurred version. I don't remember there should be a way to fade inside a canvas element, so perhaps I have to duplicate the already existing canvas and then blur and then fade in.

Load the plain image, use a canvas to create a blurred version of the image, then turn that into a real image again for use in an <img> or css background:
function blurImage(imgURL) {
var img = new Image();
img.onload = function() {
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
var context = canvas.getContext("2d");
context.drawImage(img,0,0);
/*
code that actually blurs the image goes here
*/
var dataURI = canvas.toDataUrl("image/png");
setBlurredImage(dataURI);
};
img.src = imgURL;
}
with a set handler:
function setBlurredImage(dataURI) {
whateverElement.style.background = "url(" + dataURI + ")";
}
And now you have a background image that is blurred.

Related

HTML5 - scaled image is blurry when drawn on canvas in chrome & opera

When i draw scaled image on canvas using the drawImage() function it looks slightly blurry in Chrome & Opera, but if i draw the full size image first and then the scaled one it looks crisp. What causes the blurriness and how can i fix it?
Here is the original image:
Here is the result in Chrome & Opera:
const img = new Image();
const crisptCanvas = document.getElementById('crisp-canvas');
const crispContext = crisptCanvas.getContext('2d');
const blurryCanvas = document.getElementById('blurry-canvas');
const blurryContext = blurryCanvas.getContext('2d');
const sx = 0, sy = 0, sWidth = 1980, sHeight = 1251;
const dx = 0, dy = 0;
const scaleFactor = 0.4762626262626263;
// Draw an image on canvas
function scaleImage(scale, context)
{
const dWidth = (sWidth*scale);
const dHeight = (sHeight*scale);
context.drawImage(img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
};
// When image is loaded draw it on both canvases
img.onload = function(){
// First draw the source image in full scale and then using the -scaleFactor
setTimeout(()=> {
scaleImage(1, crispContext);
scaleImage(scaleFactor, crispContext);
}, 0);
// Draw the image using the -scaleFactor
scaleImage(scaleFactor, blurryContext);
}
img.src = "https://i.stack.imgur.com/eWDSw.png"
<canvas width="944" height="596" id="crisp-canvas" ></canvas>
<canvas width="944" height="596" id="blurry-canvas" ></canvas>
Well after one day trying everything i can think of, i was not able to find a solution when i draw the scaled image on canvas.
Here are some of the things i have tried:
1) I have tried using the scale() method, but results were the same.
2) I have tried setting the imageSmoothingEnabled property, that work well with pixelated art games, but for high resolution images the quality was awful.
3) I have tried using the window.requestAnimationFrame() method than on the first request draw the full scale image, on hidden canvas and after that draw the scaled image on my main canvas. That work well, but when i change the tab(focus on another tab), after a few minutes the images on my main canvas became blurry again. Then i added a method to check when the user focus on my tab, using the Page Visibility API, and again redraw the full scale image on the hidden canvas, but that did not work. Only the last drawn image on the hidden canvas was crisp and all images drawn before the last one were blurry. So the only solution was to create hidden canvases for each image and that is not practical, so i had to try another approach.
So here is the solution came up with:
1) Set width and height canvas properties to my original image size 1980x1251
2) I scaled the canvas, using its style width & height properties
Have in mind that using this method everything drawn on the canvas like shapes, text, lines... will also be scaled. So for example if you draw a rectangle (10x10) pixels. It will have width and height each equal to 10px, only when the canvas width & height style properties match the canvas width & height properties.
canvas.style.width = canvas.width + 'px';
canvas.style.height = canvas.height + 'px';
const img = new Image();
const crispCanvas = document.getElementById('crisp-canvas');
const crispContext = crispCanvas.getContext('2d');
const sx = 0, sy = 0, sWidth = 1980, sHeight = 1251;
const dx = 0, dy = 0;
const scaleFactor = 0.4762626262626263;
// Set crisp canvas width & height properties to match the source image
crispCanvas.width = sWidth;
crispCanvas.height = sHeight;
// Scale the source canvas using width & height style properties
function scaleCanvas(scale, canvas) {
const dWidth = (sWidth*scale);
const dHeight = (sHeight*scale);
canvas.style.width = dWidth + 'px';
canvas.style.height = dHeight + 'px';
}
// When image is loaded, scale the crisp canvas and draw the full size image
img.onload = function(){
scaleCanvas(scaleFactor, crispCanvas);
crispContext.drawImage(img, sx, sy);
}
img.src = "https://i.stack.imgur.com/eWDSw.png";
<canvas id="crisp-canvas" ></canvas>

Fit image to canvas by width and fit canvas to image new height

How to fit image that bigger that canvas width to canvas(with scale) and then to fit canvas to image height after fit by width.
// Create a variable for the canvas and it's context
var canvas = document.getElementById("imageCanvas");
var ctx = canvas.getContext("2d");
// Initialise an image object
var image = new Image();
// When it loads an image
image.onload = function() {
// Get the canvas' current style
var canvasStyle = getComputedStyle(canvas);
// Get it's current width, minus the px at the end
var canvasWidth = canvasStyle.width.replace("px", "");
// Work out the images ratio
var imageRatio = this.width/this.height;
// Work out the new height of the canvas, keeping in ratio with the image
var canvasHeight = canvasWidth/imageRatio;
// Set the canvas' height in the style tag to be correct
canvas.style.height = canvasHeight+"px";
// Set the width/height attributes to be correct (as this is what drawImage uses)
canvas.width = canvasWidth;
canvas.height = canvasHeight;
// Draw the image at the right width/height
ctx.drawImage(this, 0, 0, canvasWidth, canvasHeight);
};
// Load an image
image.src="https://placekitten.com/g/600/800";
#imageCanvas
{
width: 400px;
height: 400px;
}
<canvas id="imageCanvas" width="400px" height="400px"></canvas>
There you go, shrinks the image to the right width, resizes canvas to the right height. Hopefully the comments explain everything.

Use image for background of canvas

I am making the simple canvas application.
I want to use image for background of canvas.
I have found out that I should use drawImage(img,x,y).
This is my codes ,but drummap.img doesn't appear.
Where is wrong?
Test
<canvas id="leap-overlay"></canvas>
<script src="leap.js"></script>
<script>
var canvas = document.getElementById("leap-overlay");
// fullscreen
canvas.width = document.body.clientWidth;
canvas.height = document.body.clientHeight;
// create a rendering context
var ctx = canvas.getContext("2d");
ctx.translate(canvas.width/2,canvas.height);
var img = new Image();
img.src = "drummap.jpg";
ctx.drawImage(img,0,0,100,100);
Assuming that your image drummap.jpg is located in said directory, create the image, set the onload to use the new image, and then set the src (see):
var img = new Image();
img.onload = function () {
ctx.drawImage(img, 0, 0, 100, 100);
};
img.src = 'drummap.jpg';
I'm not sure how you're clearing your canvas or what your drawing, but remember your canvas is inherently transparent so feel free to give the canvas a css style background:
<canvas style = "background-image: url(pathtoyourimage.jpg);"></canvas>
Hope that helps.

HTML5 Canvas lines not having consistent width

I'm drawing a rectangle on HTML5 canvas using the below code:
canvasId = $('#objectData').find('#miImages '+imageId+' .imageContainer canvas').attr("id");
canvas = document.getElementById(canvasId);
context = canvas.getContext("2d");
context.beginPath();
context.rect(coordinateArray[0],coordinateArray[1],coordinateArray[2],coordinateArray[3]);
context.lineWidth = 2;
context.strokeStyle = "DarkBlue";
context.stroke();
The problem is that the two vertical lines are a lot thicker than the two horizontal lines, what is causing this?
EDIT: I have height set at 89 and width set at 802. When I remove the height the rectangle no longer distorts.
I was sizing my canvas with CSS instead of JavaScript which was scaling the canvas rather than actually resizeing it. I fixed this using the below code.
function applyCanvasSize(){
$("#objectData img").on('load', function(){
var theHeight = $(this).height();
var canvasId = $(this).next('canvas').attr('id');
var canvas = document.getElementById(canvasId);
if (canvas.getContext) {
canvas.width = 802;
canvas.height = theHeight;
}
});
}
Kinda late but had the same problem.
Somewhere in my code, I was changing the size of the canvas using style.width and style.height. Directly use width and height instead. Without "px" in the end (thus only accepts pixels ?). You wont get the distortion anymore.

How to resize the drawing of the canvas in HTML5?

I would like to resize the canvas to a smaller dimension than what it is. Here is my code:
var modelPane = document.getElementById('model_pane');
//create canvasclass="modelview"
var canvas_ = document.createElement('canvas');
canvas_.setAttribute('width', 1160);
canvas_.setAttribute('height', 500);
canvas_.setAttribute('id', 'canvas');
canvas_.setAttribute('class', 'modelview');
var ctx_ = canvas_.getContext('2d');
//draw
for (i=0;i<nodes.length;i++)
{
ctx_.strokeRect(nodes[i].x, nodes[i].y, nodes[i].width, nodes[i].height);
}
//scale
ctx_.scale(0.3,0.3);
modelPane.appendChild(canvas_);
Yet this doesn't work. Anyone know why? The canvas doesn't resize to the new dimensions.
You need to call scale first:
var ctx_ = canvas_.getContext('2d');
ctx_.scale(0.3,0.3);
//draw
for (i=0;i<nodes.length;i++)
ctx_.strokeRect(nodes[i].x, nodes[i].y, nodes[i].width, nodes[i].height);
}
Think about it, like you need to scale you canvas down. Then draw on the smaller canvas.
Example