HTML Canvas w/ Image Cloning Issues - javascript

I used tips + code from this post to try to clone my original canvas - it contains an image with text overlaid on it. However, every time I run it, neither the image nor the text get copied, though the original works fine. Here is the javascript:
<script>
function CardText() {
var title = document.calform.titleText.value;
var badge = document.calform.badge.value;
var encourage = document.calform.encourage.value;
var description = document.calform.description.value;
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = canvas.width / 2;
var y = canvas.height / 2;
var imageObj = new Image();
imageObj.onload = function() {
context.drawImage(imageObj, 0, 0);
context.font = "25pt Helvetica";
context.fillStyle = "white";
context.textAlign = "center";
context.fillText(title, x, 76);
context.font = "18pt Arial";
context.fillStyle = "white";
context.textAlign = "center";
context.fillText(badge, x-10, 311);
context.font = "18pt Arial";
context.fillStyle = "black";
context.textAlign = "center";
context.fillText(encourage, x, 380);
context.font = "12pt Arial";
context.fillStyle = "black";
wrapText(context, description, x, 440, 280, 18);
};
imageObj.src = 'https://i.imgur.com/7wqLgSd.jpg';
}
function cloneCanvas(oldCanvas) {
//create a new canvas
var newCanvas = document.createElement('canvas');
var context = newCanvas.getContext('2d');
//set dimensions
newCanvas.width = oldCanvas.width;
newCanvas.height = oldCanvas.height;
//apply the old canvas to the new one
context.drawImage(oldCanvas, 100, 300);
//return the new canvas
return newCanvas;
}
</script>
And I run it with an html button:
<input class="btn btn-lg btn-primary" align = 'center' type=button name=button1 value="COPY" onClick="cloneCanvas(canvas)">
Any help would be much appreciated!
Edit: markE was kind enough to fix my problem, however it's not coming up within the full HTML document. Here's the full HTML:
<!DOCTYPE html>
<html>
<head>
<style>
body {
background-color:ivory;
padding:10px;
}
#fills {
position: relative;
margin-left: 100px;
}
canvas{
border:1px solid red;
}
</style>
<link href="bootstrap.min.css" rel="stylesheet">
</head>
<body>
<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var imageObj = new Image();
imageObj.onload = function() {
// create the original card canvas
// after the image has loaded
CardText();
// next clone the original card canvas
// to a new canvas
var myNewCanvas=cloneCanvas(canvas);
document.body.appendChild(myNewCanvas);
};
imageObj.src = 'https://i.imgur.com/7wqLgSd.jpg';
function CardText() {
var title ="Title";// document.calform.titleText.value;
var badge ="Badge";// document.calform.badge.value;
var encourage ="Encourage";// document.calform.encourage.value;
var description ="Description";// document.calform.description.value;
var x = canvas.width / 2;
var y = canvas.height / 2;
context.drawImage(imageObj, 0, 0);
context.font = "25pt Helvetica";
context.fillStyle = "white";
context.textAlign = "center";
context.fillText(title, x, 76);
context.font = "18pt Arial";
context.fillStyle = "white";
context.textAlign = "center";
context.fillText(badge, x-10, 311);
context.font = "18pt Arial";
context.fillStyle = "black";
context.textAlign = "center";
context.fillText(encourage, x, 380);
context.font = "12pt Arial";
context.fillStyle = "black";
context.fillText(description, x, 440);
// wrapText(context, description, x, 440, 280, 18);
}
function cloneCanvas(oldCanvas) {
//create a new canvas
var newCanvas = document.createElement('canvas');
var context = newCanvas.getContext('2d');
//set dimensions
newCanvas.width = oldCanvas.width;
newCanvas.height = oldCanvas.height;
//apply the old canvas to the new one
context.drawImage(oldCanvas, 100, 300);
//return the new canvas
return newCanvas;
}
</script>
<div id="fills" >
<td align=right width=200>Title:</td>
<td><input type=text name=titleText size=10 maxlength=10></td>
<td align=right width=200>Badge Name:</td>
<td><input type=text name=badge size=10 maxlength=10></td>
<td align=right width=200>Encouraging Words:</td>
<td><input type=text name=encourage size=10 maxlength=14></td>
<td align=right width=200>Description:</td>
<td><input type=text name=description size=50 maxlength=120></td>
<input class="btn btn-lg btn-primary" align = 'center' type=button name=button1 value="Submit" onClick="CardText()">
</div>
<canvas id="myCanvas" width="390" height="540"></canvas>
</body>
</html>

It looks like you might be calling cloneCanvas before CardText has a chance to fully load the image and draw the text on the image.
Try this refactoring which fully loads the image+text before trying to cloneCanvas.
Example Code and a Demo:
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var imageObj = new Image();
imageObj.onload = function() {
// create the original card canvas
// after the image has loaded
CardText();
// next clone the original card canvas
// to a new canvas
var myNewCanvas=cloneCanvas(canvas);
document.body.appendChild(myNewCanvas);
};
imageObj.src = 'https://i.imgur.com/7wqLgSd.jpg';
function CardText() {
var title ="Title";// document.calform.titleText.value;
var badge ="Badge";// document.calform.badge.value;
var encourage ="Encourage";// document.calform.encourage.value;
var description ="Description";// document.calform.description.value;
var x = canvas.width / 2;
var y = canvas.height / 2;
context.drawImage(imageObj, 0, 0);
context.font = "25pt Helvetica";
context.fillStyle = "white";
context.textAlign = "center";
context.fillText(title, x, 76);
context.font = "18pt Arial";
context.fillStyle = "white";
context.textAlign = "center";
context.fillText(badge, x-10, 311);
context.font = "18pt Arial";
context.fillStyle = "black";
context.textAlign = "center";
context.fillText(encourage, x, 380);
context.font = "12pt Arial";
context.fillStyle = "black";
context.fillText(description, x, 440);
// wrapText(context, description, x, 440, 280, 18);
}
function cloneCanvas(oldCanvas) {
//create a new canvas
var newCanvas = document.createElement('canvas');
var context = newCanvas.getContext('2d');
//set dimensions
newCanvas.width = oldCanvas.width;
newCanvas.height = oldCanvas.height;
//apply the old canvas to the new one
context.drawImage(oldCanvas, 100, 300);
//return the new canvas
return newCanvas;
}
body{ background-color: ivory; padding:10px; }
canvas{border:1px solid red;}
<canvas id="myCanvas" width=390 height=540></canvas>
[ Addition: plugged my answer above into Allen Rabinovich's code. ]
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var imageObj = new Image();
imageObj.onload = function() {
// create the original card canvas
// after the image has loaded
CardText();
};
imageObj.src = 'https://i.imgur.com/7wqLgSd.jpg';
document.getElementById('drawAll').onclick=function(){
CardText();
// next clone the original card canvas
// to a new canvas
var myNewCanvas=cloneCanvas(canvas);
document.body.appendChild(myNewCanvas);
}
function CardText() {
var title=document.getElementsByName('titleText')[0].value;
var badge=document.getElementsByName('badge')[0].value;
var encourage=document.getElementsByName('encourage')[0].value;
var description=document.getElementsByName('description')[0].value;
var x = canvas.width / 2;
var y = canvas.height / 2;
context.drawImage(imageObj, 0, 0);
context.font = "25pt Helvetica";
context.fillStyle = "white";
context.textAlign = "center";
context.fillText(title, x, 76);
context.font = "18pt Arial";
context.fillStyle = "white";
context.textAlign = "center";
context.fillText(badge, x-10, 311);
context.font = "18pt Arial";
context.fillStyle = "black";
context.textAlign = "center";
context.fillText(encourage, x, 380);
context.font = "12pt Arial";
context.fillStyle = "black";
context.fillText(description, x, 440);
// wrapText(context, description, x, 440, 280, 18);
}
function cloneCanvas(oldCanvas) {
//create a new canvas
var newCanvas = document.createElement('canvas');
var context = newCanvas.getContext('2d');
//set dimensions
newCanvas.width = oldCanvas.width;
newCanvas.height = oldCanvas.height;
//apply the old canvas to the new one
context.drawImage(oldCanvas,0,0);
//return the new canvas
return newCanvas;
}
body{ background-color: ivory; padding:10px; }
#canvas{border:1px solid red;}
#fills{ position: relative; margin-left: 100px; }
Title:<input type=text name=titleText size=10 maxlength=10><br>
Badge:<input type=text name=badge size=10 maxlength=10><br>
Encourage:<input type=text name=encourage size=10 maxlength=14><br>
Description:<input type=text name=description size=50 maxlength=120><br>
<input id=drawAll class="btn btn-lg btn-primary" align = 'center' type=button name=button1 value="Submit">
<canvas id="myCanvas" width="390" height="540"></canvas>

Related

Failed to execute 'drawImage' on 'CanvasRenderingContext2D Trying to convert a canvas into image

I am having an issue creating an image of a canvas and translating it onto another canvas. The end goal is to create a loupe magnifier for a cgm viewer/editor, but I'm stuck on this issue. Here is an example.
HTML:
<canvas id="canvas" width=240 height=240 style="background-color: aqua;
left:0;right:0;margin:auto;z-index:1;margin-top:0px;">
</canvas>
<canvas id="canvas1" width=240 height=240 style="background-color:#808080;">
</canvas>
<p></p>
<a id="download" href="" onclick="draw_image();">Download to myImage.jpg</a>
JS:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var ox = canvas.width / 2;
var oy = canvas.height / 2;
ctx.font = "42px serif";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillStyle = "#800";
ctx.fillRect(ox / 2, oy / 2, ox, oy);
draw_image = function() {
let canvas1 = document.getElementById('canvas1')
var image = canvas1.toDataURL("image/png")
let ctx1 = canvas1.getContext("2d");
ctx.drawImage(image, 0, 0)
};
You probably wanted to just draw a canvas, no some url
And you wanted to type ctx1 and not ctx
draw_image = function() {
let canvas1 = document.getElementById('canvas1')
let ctx1 = canvas1.getContext("2d");
// just draw the original canvas
ctx1.drawImage(canvas, 0, 0)
};

Canvas zoom with stroke and text

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">

Canvas. Align text

This code would satisfy me but for the text alignment. Both the top line and bottom line are not aligned in the center of the lines. Could you help me here?
function redrawMeme(image, topLine, bottomLine) {
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext("2d");
ctx.textAlign = "center";
var height = Math.min(image.height, canvas.height);
var width = Math.min(image.width, canvas.width);
ctx.drawImage(image, 0, 0, width, height);
var font = "bold 24px verdana, sans-serif ";
ctx.font = font;
var fillStyle = "white";
ctx.fillStyle = fillStyle;
var strokeStyle = "black";
if (topLine) {
ctx.fillText(topLine, 50, 50);
ctx.strokeText(topLine, 50, 50);
};
if (bottomLine) {
ctx.fillText(bottomLine, 50, 350);
ctx.strokeText(bottomLine, 50, 350);
};
}
// The following code is just for the example:
const img = new Image(500, 500);
img.src = 'https://api.adorable.io/avatars/500/abott#adorable.png';
img.onload = function() {
redrawMeme(img, 'Top', 'Bottom');
}
<canvas id="canvas" width="500" height="500"></canvas>
It is because canvas text is center-aligned, so the left and right ends of each line depends on the text length. You can align them by setting their x coordinates to the center of the width, like this:
function redrawMeme(image, topLine, bottomLine) {
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext("2d");
ctx.textAlign = "center";
var height = Math.min(image.height, canvas.height);
var width = Math.min(image.width, canvas.width);
ctx.drawImage(image, 0, 0, width, height);
var font = "bold 24px verdana, sans-serif ";
ctx.font = font;
var fillStyle = "white";
ctx.fillStyle = fillStyle;
var strokeStyle = "black";
var centerX = width / 2
if (topLine) {
ctx.fillText(topLine, centerX, 50);
ctx.strokeText(topLine, centerX, 50);
};
if (bottomLine) {
ctx.fillText(bottomLine, centerX, 350);
ctx.strokeText(bottomLine, centerX, 350);
};
}
// The following code is just for the example:
const img = new Image(500, 500);
img.src = 'https://api.adorable.io/avatars/500/abott#adorable.png';
img.onload = function() {
redrawMeme(img, 'Top', 'Bottom');
}
<canvas id="canvas" width="500" height="500"></canvas>

Change text in canvas object using Javascript

In below example, lets say json.mes is the received message from Ajax; A button is designed which must display the message in a canvas box. I have tried to read the message using getElementById (as below); however, it does not work. Any solution?
<div> <button id="submit" type="button" class="btn btn-success" style="float: right;">Populate</button></div>
<script>
var canvas = document.getElementById("myCanvas3");
var ctx = canvas.getContext("2d");
ctx.fillRect(0, 0, 150, 150);
ctx.fillStyle = "#dbbd7a";
ctx.font = "10px Comic Sans MS";
ctx.fillStyle = "red";
ctx.textAlign = "center";
ctx.fillStyle = "#ff0000";
ctx.fillText(document.getElementById("picoutput0"), 74, 74);
</script>
<script>
...
$("#submit").click(function(e) {
...
var text0=json.mes
$('#picoutput0').html(text0);
</script>
try this code
var canvas = document.getElementById('myCanvas'),
ctx = canvas.getContext('2d');
ctx.fillStyle = '#0e70d1';
ctx.fillRect(0, 0, canvas.width, canvas.height);
var stringTitle = document.getElementById('title').textContent;
console.log(stringTitle);
ctx.fillStyle = '#fff';
ctx.font = '60px sans-serif';
ctx.fillText(stringTitle, 15, canvas.height / 2 + 35);
DEMO

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>

Categories

Resources