Canvas zoom with stroke and text - javascript

I want zoom images, lines, and text drawn on a canvas
Click plus button > zoom in
Click minus button > zoom out
I tried scale but only the image got bigger.
test.html
<canvas id="img"></canvas>
<input type="button" id="plus" value="plus">
<input type="button" id="minus" value="minus">
<script>
const canvas = document.getElementById('img');
const ctx = canvas.getContext('2d');
const img = new Image();
img.src = 'test.PNG';
img.onload = function() {
canvas.height = img.height;
canvas.width = img.width;
ctx.drawImage(img, 0, 0);
ctx.lineWidth = 3;
ctx.strokeStyle = 'red';
ctx.strokeRect(28, 26, 50, 50);
ctx.textBaseline = 'top';
ctx.font="15px Verdana";
ctx.fillStyle = 'red';
ctx.fillText("TEXT", 28, 25 + 50 + 5);
ctx.fill();
ctx.scale(2,2);
ctx.restore();
};
</script>
<script>
const plus = document.getElementById('plus');
const minus = document.getElementById('minus');
</script>

The problem is - as Kaiido implied in his comment - that the scale() method doesn't affect anything thas has been drawn onto the canvas prior the call to scale.
If you really want a context.scale driven zoom function you will have to redraw anything after calling scale.
Here's an example:
const canvas = document.getElementById('img');
const ctx = canvas.getContext('2d');
function zoomIn() {
myScale = myScale < 2.5 ? myScale += 0.5 : 2.5;
draw();
}
function zoomOut() {
myScale = myScale > 0.5 ? myScale -= 0.5 : 0.5;
draw();
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.save();
ctx.translate(canvas.width / 2 - canvas.width / 2 * myScale, canvas.height / 2 - canvas.height / 2 * myScale);
ctx.scale(myScale, myScale);
ctx.drawImage(img, 0, 0);
ctx.lineWidth = 3;
ctx.strokeStyle = 'red';
ctx.strokeRect(28, 26, 50, 50);
ctx.textBaseline = 'top';
ctx.font = "15px Verdana";
ctx.fillStyle = 'red';
ctx.fillText("TEXT", 28, 25 + 50 + 5);
ctx.fill();
ctx.restore();
}
var img = new Image();
var myScale = 1;
img.onload = function() {
canvas.height = img.height;
canvas.width = img.width;
draw();
};
img.src = 'https://picsum.photos/id/1/200/300';
const plus = document.getElementById('plus');
const minus = document.getElementById('minus');
plus.addEventListener("click", zoomIn);
minus.addEventListener("click", zoomOut);
<canvas id="img"></canvas>
<input type="button" id="plus" value="plus">
<input type="button" id="minus" value="minus">

Related

Why do I have to click the button twice to have the image loaded?

I am new to programming. I have an issue with the submit button. The first time I click it the image doesn't show up on the canvas. Below is my code. I have used onload method to load the image. I'm using Chrome.
generateBtn = document.getElementById('button1');
canvas = document.getElementById('meme-canvas');
ctx = canvas.getContext('2d');
canvas.width = canvas.height = 0;
let button1 = document.getElementById('button1');
button1.addEventListener('click', function(e) {
console.log("clicked", this);
e.preventDefault();
let imageurl = document.getElementById('text1').value;
let img = document.createElement('img');
img.addEventListener('error', imageNotFound);
img.crossOrigin = "anonymous";
img.src = imageurl;
generateMeme(img, topTextInput.value, bottomTextInput.value);
})
function imageNotFound() {
alert('That image was not found.');
}
}
function generateMeme(img, topText, bottomText) {
// Size canvas to image
canvas.width = img.width;
canvas.height = img.height;
// Clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw main image
img.onload = function() {
ctx.drawImage(img, 0, 0);
}
}
The problem is that you're using img.width and img.height before the image is loaded, so it doesn't know the dimensions yet. Put those lines inside the onload function.
function generateMeme(img, topText, bottomText) {
img.onload = function() {
// Size canvas to image
canvas.width = img.width;
canvas.height = img.height;
// Clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw main image
ctx.drawImage(img, 0, 0);
let fontSize = canvas.width / 15;
ctx.font = fontSize + 'px Impact';
ctx.fillStyle = 'white';
ctx.strokeStyle = 'black';
ctx.lineWidth = fontSize / 15;
ctx.textAlign = 'center';
ctx.textBaseline = 'top';
topText.split('\n').forEach(function(t, i) {
ctx.fillText(t, canvas.width / 2, i * fontSize, canvas.width);
ctx.strokeText(t, canvas.width / 2, i * fontSize, canvas.width);
})
ctx.textBaseline = 'bottom';
bottomText.split('\n').reverse().forEach(function(t, i) {
ctx.fillText(t, canvas.width / 2, canvas.height - i * fontSize, canvas.width);
ctx.strokeText(t, canvas.width / 2, canvas.height - i * fontSize, canvas.width);
})
}
}

Unable to draw on the image after rotation it is drawing on the original canvas orientation

var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
var rw = 1560;
var rh = 2080;
var cw = "null";
var lw = "null";
var lh = "null";
var fh = "null";
var drag = false;
var last_mousex = last_mousey = 0;
var mousex = mousey = 0;
var mousedown = false;
var image = new Image();
image.src = "https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/darwin300.jpg"
image.onload = function(e) {
ctx.canvas.width = image.width;
ctx.canvas.height = image.height;
c.width = image.width;
c.height = image.height;
ctx.save();
if(rw) {
c.width = rh;
c.height = rw;
ctx.canvas.width = rh;
ctx.canvas.height = rw;
ctx.translate(rh, 0);
ctx.rotate((90 * Math.PI) / 180);
ctx.drawImage(image,0,0,rw,rh);
ctx.save();
}
else if(lw) {
c.width = lh;
c.height = lw;
ctx.canvas.width = lh;
ctx.canvas.height = lw;
ctx.translate(lw-lh, lw);
ctx.rotate((-90 * Math.PI) / 180);
ctx.translate(0,-(lw-lh));
ctx.drawImage(image,0,0,lw,lh);
ctx.save();
}
else if(fh) {
var maxsize = image.width;
var w = maxsize;
var ratio = (image.width / w);
var h = (image.height / ratio);
c.width = w;
c.height = h;
ctx.canvas.width = w;
ctx.canvas.height = h;
ctx.translate(w, h);
ctx.rotate(Math.PI);
ctx.drawImage(image,0,0,w,h);
ctx.save();
}
else {
ctx.canvas.width = image.width;
ctx.canvas.height = image.height;
c.width = image.width;
c.height = image.height;
ctx.drawImage(image, 0, 0);
ctx.save();
}
ctx.rect(200, 200, 550, 500);
ctx.strokeStyle = "green";
ctx.lineWidth = "5";
ctx.stroke();
};
function drawrect() {
$(c).on('mousedown', function(e) {
last_mousex = parseInt((image.width / c.scrollWidth) * e.offsetX);
last_mousey = parseInt((image.height / c.scrollHeight) * e.offsetY);
rx = last_mousex;
ry = last_mousey;
mousedown = true;
});
$(c).on('mouseup', function(e) {
last_mousex = parseInt((image.width / c.scrollWidth) * e.offsetX);
last_mousey = parseInt((image.height / c.scrollHeight) * e.offsetY);
mousedown = false;
if(!mousedown) {
redraw(last_mousex, last_mousey, ctx);
}
});
$(c).on('mousemove', function(e) {
mousex = parseInt((image.width / c.scrollWidth) * e.offsetX);
mousey = parseInt((image.height / c.scrollHeight) * e.offsetY);
if(mousedown) {
var width = mousex-last_mousex;
var height = mousey-last_mousey;
}
});
}
function redraw(tox, toy, ctx) {
ctx.beginPath();
ctx.restore();
ctx.rect(rx, ry, tox - rx, toy - ry);
ctx.strokeStyle = "black";
ctx.lineWidth = "3";
ctx.stroke();
ctx.closePath();
xMi = rx;
yMi = ry;
xMa = tox - rx;
yMa = toy - ry;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="canvas" style="width:100%; height:80%; margin: 0; padding: 0;"></canvas>
<button type="button" id="drawrect" onclick="drawrect()" class="btn btn-default" style="float:left; margin-top: 20px;">Draw
<span class="glyphicon glyphicon-edit"> </span></button>
Rotation: 90 (right rotation), 180 (vertical rotation), -90 (left rotation).
Using canvas, added draw rectangle function which on using mouse event x and y coordinated draws rectangle on the canvas but it is unable to draw on the rotated canvas, it is able to correctly draw on the original image orientation.
The problem is that you transformed the canvas using the .translate() and .rotate() methods. The drawing still works though - it's just outside of the visible area.
To work around that you need to reset the transformation to the identity matrix.
Simply insert:
ctx.setTransform(1, 0, 0, 1, 0, 0);
at the end of your onload callback function.

Interact with rect to take me to another page HTML JS Canvas

The Menu
I want to make it so when the user clicks play it takes you to another HTML page. I have placed a rect over the play area and want to make it so the rect is what the user is clicking as the play text is part of a single image.
This is the JS for my rect:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
// Red rectangle
ctx.beginPath();
ctx.lineWidth = "6";
ctx.strokeStyle = "red";
ctx.rect(125, 140, 230, 90);
ctx.stroke();
You can achieve it like this
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var img = new Image();
img.onload = draw;
function draw() {
canvas.width = this.width;
canvas.height = this.height;
ctx.drawImage(this, 0, 0);
ctx.beginPath();
ctx.lineWidth = "6";
ctx.strokeStyle = "red";
ctx.rect(101, 114, 184, 71);
ctx.stroke();
}
img.src = 'https://i.stack.imgur.com/M3x29.jpg';
canvas.onclick = function(e) {
if (e.offsetX > 102 && e.offsetX < 286 && e.offsetY > 110 && e.offsetY < 182) {
window.location = 'http://stackoverflow.com'; // another html page location
}
};
<canvas id="canvas"></canvas>

Image not appearing in canvas - sometimes

This works great on all of my tests, but on the live system, I have a problem.
There are three separate but identical canvases. They are all initially painted with 640x480 jpg images. The third is then updated every second with a new 640x480 jpg image.
For some reason, the original static image for the third canvas - and that canvas only - doesn't load from the live server, only on the tests.
Here's the html:
<div style="padding: 1vw;">
<a href="/virtualscribe" class="camLink">
<div class="camDiv">
<div class="camBox" id="picBoxLeft">
<canvas id="canvasLeft" class="camBorder"></canvas>
</div>
</div>
</a>
<a href="/videos" class="camLink">
<div class="camDiv">
<div class="camBox" id="picBoxCenter">
<canvas id="canvasCenter" class="camBorder"></canvas>
</div>
</div>
</a>
<div class="camDiv">
<div class="camBox" id="picBoxRight">
<canvas id="canvasRight" class="camBorder"></canvas>
</div>
</div>
</div>
Here's the CSS:
<style>
.camBox {
max-width: 28vw;
width: 28vw;
height: 21vw;
max-height: 21vw;
display: inline-block;
}
.camDiv {
padding: 1.5vw;
display: inline-block;
}
.camBorder {
border: 0.6vw solid #fe890f;
border-top-left-radius: 3.3vw;
border-bottom-right-radius: 3.3vw;
}
.camLink {
color: transparent;
}
</style>
And here's the JavaScript:
var refreshTimer;
var imgLiveCam;
function drawPictureBox(img, canvas, text) {
var context = canvas.getContext("2d");
context.drawImage(img, 0, 0, canvas.width, canvas.height);
context.globalAlpha = 0.6;
context.fillStyle = "rgb(244,121,32)";
context.fillRect(0, canvas.height * 0.67, canvas.width, canvas.height * 0.33);
context.globalAlpha = 1;
var maxWidth = canvas.width;
var x = canvas.width / 2;
var y = canvas.height * 0.85;
context.font = canvas.width / 12 + 'px Oswald';
context.strokeStyle = 'black';
context.lineWidth = 2;
context.textAlign = "center";
context.strokeText(text, x, y, maxWidth);
context.fillStyle = 'white';
context.fillText(text, x, y, maxWidth);
};
function drawCamBox(img, logo, canvas) {
var context = canvas.getContext("2d");
context.drawImage(img, 0, 0, canvas.width, canvas.height);
context.globalAlpha = 0.6;
context.fillStyle = "rgb(244,121,32)";
context.fillRect(0, canvas.height * 0.67, canvas.width, canvas.height * 0.33);
var eSize = canvas.height / 10;
context.globalAlpha = 1;
context.drawImage(logo, 2, canvas.height * 0.67 - eSize, eSize, eSize);
var now = new Date();
var text = now.toLocaleDateString() + " " + now.toLocaleTimeString();
var maxWidth = canvas.width * 0.33;
var x = canvas.width - 10 - maxWidth;
var y = canvas.height * 0.67 - 10;
context.font = maxWidth / 10 + "px Arial";
context.strokeStyle = 'black';
context.lineWidth = 2;
context.strokeText(text, x, y, maxWidth);
context.fillStyle = 'white';
context.fillText(text, x, y, maxWidth);
text = 'View Our Production Floor';
context.textAlign = "center";
maxWidth = canvas.width;
x = canvas.width / 2;
y = canvas.height * 0.85;
context.font = canvas.width / 12 + 'px Oswald';
context.strokeText(text, x, y, maxWidth);
context.fillText(text, x, y, maxWidth);
}
function addResizeListener(fn) {
if (window.attachEvent) {
window.attachEvent('onresize', fn)
} else if (window.addEventListener) {
window.addEventListener('resize', fn, true);
};
}
function initCam() {
var imgLeft = new Image();
imgLeft.onload = function () {
var canvas = document.getElementById("canvasLeft");
var picBox = document.getElementById("picBoxLeft");
var drawFn = function () {
canvas.height = picBox.clientHeight;
canvas.width = picBox.clientWidth;
drawPictureBox(imgLeft, canvas, 'Looking for a Scribe?');
};
drawFn();
addResizeListener(drawFn);
}
var imgCenter = new Image();
imgCenter.onload = function () {
var canvas = document.getElementById("canvasCenter");
var picBox = document.getElementById("picBoxCenter");
var drawFn = function () {
canvas.height = picBox.clientHeight;
canvas.width = picBox.clientWidth;
drawPictureBox(imgCenter, canvas, 'Watch In-Depth Videos');
};
drawFn();
addResizeListener(drawFn);
}
imgLiveCam = new Image();
var logo = new Image();
logo.src = "e.png";
imgLiveCam.onload = function () {
var canvas = document.getElementById("canvasRight");
var picBox = document.getElementById("picBoxRight");
var drawFn = function () {
canvas.height = picBox.clientHeight;
canvas.width = picBox.clientWidth;
drawCamBox(imgLiveCam, logo, canvas);
};
drawFn();
imgLiveCam.onload = drawFn;
addResizeListener(drawFn);
}
imgLeft.src = "scribe.jpg";
imgCenter.src = "doc-with-spine.jpg";
imgLiveCam.src = "camloading.jpg";
refreshTimer = setTimeout(refresh, 499);
}
function refresh() {
clearTimeout(refreshTimer);
imgLiveCam.src = "http://cams.edataservices.com/17fcam.jpg?t=" + new Date().getTime();
refreshTimer = setTimeout(refresh, 1009);
}
Any idea why the third canvas starts out blank most of the time?
By adding a longer delay before starting the refresh cycle, the browsers had more time to load the initial, "default" image. I set it at 1500ms, and now it is pretty reliable.
(Thanks for the help...)

Moving and rotating with HTML5

What needs to be done:
The pink object should move from the left to the right (by itself). And then when it's 5px from the edge it should rotate 90 degrees.
Does anyone know how to do this?
I haven't been learning javascript for a long time, and it's the first time I'm creating something using HTML5. So it's all new. I really hope you can help me understand the code better and how I can make it move and rotate.
<!DOCTYPE html>
<html>
<head>
<script>
var canvas, ctx;
window.onload = function draw() {
canvas = document.getElementById("myCanvas");
ctx = canvas.getContext("2d");
var height = 90;
var width = 40;
var radius = width / 2;
ctx.clearRect(0,0, canvas.width, canvas.height);
ctx.fillStyle = "#FFE2E8";
ctx.strokeStyle = "black";
ctx.beginPath();
ctx.moveTo(20,20);
ctx.lineTo(70,20);
ctx.arc(70,40,20, -Math.PI/2, Math.PI/2);
ctx.lineTo(20,60);
ctx.lineTo(20,20);
ctx.closePath;
ctx.fill();
ctx.stroke();
requestAnimationFrame(draw);
}
function init() {
canvas = document.getElementById("myCanvas");
ctx = canvas.getContext("2d");
draw();
}
</script>
</head>
<body>
<canvas id="myCanvas" width="400" height="300" style="background:#00CC66">
</canvas>
</body>
</html>
var canvas, ctx;
canvas = document.getElementById("myCanvas");
ctx = canvas.getContext("2d");
var radius = 20;
var width = 70;
var margin = 5;
var offsetx = -20
var translate = {
x: 0,
y: 0,
xmax: canvas.width - margin - width + offsetx,
ymax: canvas.height - margin - width
};
var rotate = 0;
var to_radians = Math.PI / 180;
function draw() {
ctx.save();
ctx.translate(translate.x, translate.y);
if (translate.x >= translate.xmax) {
translate.x = translate.xmax;
if (rotate >= 90) {
rotate = 90;
} else {
rotate++;
}
ctx.rotate(rotate * to_radians);
} else {
translate.x++;
}
var height = 90;
var width = 40;
var radius = width / 2;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "#FFE2E8";
ctx.strokeStyle = "black";
ctx.beginPath();
ctx.moveTo(20, 20);
ctx.lineTo(70, 20);
ctx.arc(70, 40, 20, -Math.PI / 2, Math.PI / 2);
ctx.lineTo(20, 60);
ctx.lineTo(20, 20);
ctx.closePath;
ctx.fill();
ctx.stroke();
ctx.restore();
requestAnimationFrame(draw);
}
function init() {
canvas = document.getElementById("myCanvas");
ctx = canvas.getContext("2d");
draw();
}
init();
<canvas id="myCanvas" width="400" height="300" style="background:#00CC66">
</canvas>

Categories

Resources