How to resize the drawing of the canvas in HTML5? - html

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

Related

HTML5 canvas apply color to image where shape overlays

I have this image drawn to a HTML5 canvas:
What I want to do is apply color to just a part of it.
The part where I want to apply color is defined by the following overlay image:
So, basically, I would like to guide my coloring by the overlay. So where the overlay pixels meets the main image pixels I should apply a color on the main image. At least that's how I see it working.
Notice that the overlay matches the whole image except for the lacing.
The catch is that I would like to retain the main image texture while applying the color. You can see that it has a leather texture and a "real" feel which I want to keep.
Can you please show me some methods of achieving this or share some thoughts?
Thank you!
globalCompositeOperation is your friend here.
Basically, you draw your overlay, then you set the gCO to 'source-atop' composite mode, which will make all your future drawings to only stay where there were already opaque pixels drawn, so it is important that your overlay has transparent parts.
So then you just fill a rectangle of your desired command, and finally you draw your original image, either behind, or blended to the new shape we just created.
var ctx = canvas.getContext('2d');
var loaded = 0;
function onload(){
if(++loaded === 2){
canvas.width = this.width;
canvas.height = this.height;
ctx.font = "40px sans-serif";
draw();
}
}
var original = new Image();
var overlay = new Image();
original.onload = overlay.onload = onload;
original.src = 'https://i.stack.imgur.com/vIKpI.png';
overlay.src = 'https://i.stack.imgur.com/10Tre.png';
// list of blending modes.
// Note that destination-over is a composite mode,
// which place the new drawings behind the already-there ones
var currentMode = 0;
var modes = ['destination-over', 'lighter', 'multiply', 'screen', 'overlay', 'darken',
'lighten', 'color-dodge', 'color-burn', 'hard-light', 'soft-light',
'exclusion', 'hue', 'saturation', 'color', 'luminosity' ];
function draw(){
// switch between different Blending modes
var mode = modes[currentMode];
currentMode = (currentMode+1)%(modes.length);
// clear previous
ctx.clearRect(0,0,canvas.width, canvas.height);
// draw our overlay
ctx.drawImage(overlay, 0,0);
// this will keep new drawings only where we already have existing pixels
ctx.globalCompositeOperation = 'source-atop';
ctx.fillStyle = 'red';
ctx.fillRect(0,0,canvas.width, canvas.height);
// now choose between the list of blending modes
ctx.globalCompositeOperation = mode;
// draw our original image
ctx.drawImage(original, 0,0);
// go back to default
ctx.globalCompositeOperation = 'source-over';
// just so we can know which one is shown
ctx.fillStyle = 'black';
ctx.fillText(mode, 40,40)
// do it again
setTimeout(draw, 1000)
}
canvas{
width: 100%;
}
<canvas id="canvas"></canvas>

How to draw on canvas on mousedown?

I am looking to simply add a dot to the canvas.
I have the following code:
var canv = document.getElementById("myCanvas");
var context = canv.getContext("2d");
var radius = 5;
var putPoint = function(e){
context.beginPath();
context.arc(e.clientX, e.clientY, radius, 0, Math.PI*2);
context.fill();
}
canv.addEventListener('mousedown', putPoint);
I was learning how to do this with a video tutorial. However they were setting the canvas
as the full width/height of the browser window, whereas my canvas is on 400px * 400px and is contained within a div. I think this is the problem.
So my question is are the "e.client" parameters not working because of my canvas being only
a small part of the window?
If so, how can I track the mouse co-ordinates on my canvas?
You must adjust e.clientX/e.clientY by the offset of the canvas element.
Otherwise you're miscalculating the position of your mouse and your dot is probably being drawn outside the bounds of your canvas.
Here's your code modified to take the canvas offset into account.
var putPoint = function(e){
var BB=canvas.getBoundingClientRect();
var offsetX=BB.left;
var offsetY=BB.top;
var mouseX=e.clientX-BB.left;
var mouseY=e.clientY-BB.top;
context.beginPath();
context.arc(mouseX,mouseY,radius,0,Math.PI*2);
context.fill();
}

html5 canvas background image blur and resize

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.

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.

Frame by frame animation in HTML5 with canvas

I have a flash animation I am trying to convert to HTML5. Now I have taken out all the images. For example in the hand animation, I have taken images of all hand images. I have made the canvas with the base drawing but I don't know how to replace those images frame by frame.
function draw(){
var canvas = document.getElementById('canvas');
if(canvas.getContext){
// canvas animation code here:
var ctx = canvas.getContext('2d');
var lhs = new Image();
lhs.src = "images/left_hnd_1.png";
lhs.onload = function(){
ctx.drawImage(lhs, 293, 137);
}
} else {
// canvas unsupported code here:
document.getElementById('girl').style.display = "block";
}
}
Now I have three more frame for this image. left_hnd_2.png, left_hnd_3.png & left_hnd_4.png. I would've used one image but the difference in frames is way too much for it to be done with one image. How can I animate this with the time differences I want.
Any ideas would be greatly appreciated. Thanks!
Try this:
var imgNumber = 1;
var lastImgNumber = 4;
var ctx = canvas.getContext('2d');
var img = new Image;
img.onload = function(){
ctx.clearRect( 0, 0, ctx.canvas.width, ctx.canvas.height );
ctx.drawImage( img, 0, 0 );
};
var timer = setInterval( function(){
if (imgNumber>lastImgNumber){
clearInterval( timer );
}else{
img.src = "images/left_hnd_"+( imgNumber++ )+".png";
}
}, 1000/15 ); //Draw at 15 frames per second
An alternative, if you only have 4 images, would be to create a single huge image with all four in a 'texture atlas', and then use setTimeout or setInterval to call drawImage() with different parameters to draw different subsets of the image to the canvas.
This worked for me as well! For some reason, it didn't work when I had used the OP's opening code: function draw(){
However when I used: window.onload = function draw() { the animation plays on the canvas. I'm also using about 150 PNG images with an Alpha channel so this is a great way to bring 'video' or create composites to the iPad/iPhone. I confirm that it does work on iPad iOS 4.3.