I want to download canvas with border. On screen Canvas has border but when I download canvas, its border doesnt appear
let canvas=qrRef.current.querySelector("canvas")
canvas.style.border="black 30px solid"
if(type=="PNG"){
let image=canvas.toDataURL("image/png")
let anchor=document.createElement("a");
anchor.href=image;
anchor.download=`qr-pollective.png`
document.body.appendChild(anchor);
anchor.click()
document.body.removeChild(anchor)
}
console.log(canvas)
<canvas height="400" width="400" style="border: 30px solid black; border-radius: 5px; border-collapse: collapse;">
What you can do is create a bigger canvas which has space for the black border.
Then copy the canvas you have created onto this bigger one, offset by 30px to make room for the border.
Then draw the 4 black rectangles that make up the border. This bigger canvas is then the one that you want to download.
const canvas = document.querySelector('canvas');
const biggerCanvas = document.createElement('canvas');
const w = canvas.width + 60;
const h = canvas.height + 60;
biggerCanvas.width = w;
biggerCanvas.height = h;
const ctx = biggerCanvas.getContext('2d');
ctx.drawImage(canvas, 30, 30);
ctx.beginPath();
ctx.rect(0, 0, w, 30);
ctx.fillStyle = "black";
ctx.fill();
ctx.rect(0, 0, 30, h);
ctx.fill();
ctx.rect(w - 30, 0, w - 30, h);
ctx.fill();
ctx.rect(0, h - 30, w, h);
ctx.fill();
document.body.append(biggerCanvas); //just to show it has drawn the border
<canvas height="400" width="400" style="border: 30px solid black; border-radius: 5px; border-collapse: collapse;">
I solved my problem with html2canvas here is my code
html2canvas(canvas,{backgroundColor: "transparent"}).then(function (canvas) {
var myImage = canvas.toDataURL();
downloadURI(myImage, `qr-pollective.png`);
});
function downloadURI(uri, name) {
var link = document.createElement("a");
link.download = name;
link.href = uri;
document.body.appendChild(link);
link.click();
}
Related
I'm working on an app that allows the user to select an image and define a custom clipping region for that image. The user can place blue dots on the canvas containing the image, which will represent the clipping path. These points are stored in the coordinates array. This is the function that clips the image to the selected area:
function crop()
{
ctx.beginPath();
ctx.moveTo(coordinates[0].x, coordinates[0].y);
for(let i=1; i<coordinates.length; i++)
{
ctx.lineTo(coordinates[i].x, coordinates[i].y);
}
ctx.lineTo(coordinates[0].x, coordinates[0].y);
ctx.stroke();
ctx.save();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.restore();
ctx.clip();
//redraw the image in the cropped area
let pattern = ctx.createPattern(image, "repeat");
ctx.fillStyle = pattern;
ctx.fill();
ctx.closePath();
}
This works perfectly fine when I let the image keep its natural dimensions (in this case 1200x600):
But if I give the image max-height and max-width properties, each set to 80vmin, the cropping stops working correctly:
Instead of cropping the image around the eye area, like in the previous image, it clips a different part of the image to the selected area.
I suspect createPattern is for some reason not loading the image properly, with its updated dimensions. So I tried passing it a new canvas object (which is basically a copy of the canvas I'm working on in its original form, with the resized image painted on and nothing else) instead of the image itself, but that didn't seem to work either, I was getting the same result. Is there anything else I could try?
Update: here is a JSFiddle containing the whole code
const image = document.getElementById("pic");
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
//draw the image on the canvas
canvas.width = image.width;
canvas.height = image.height;
ctx.drawImage(image, 0, 0, image.width, image.height);
//get mouse coordinates
let coordinates = [];
canvas.onclick = function clickEvent(e)
{
let rect = e.target.getBoundingClientRect();
let x = e.clientX - rect.left;
let y = e.clientY - rect.top;
let point = {
"x": x,
"y": y
};
coordinates.push(point);
ctx.fillStyle = "blue";
ctx.fillRect(x, y, 10, 10);
}
//debugging
console.log(coordinates);
//crop the image
function crop()
{
ctx.beginPath();
ctx.moveTo(coordinates[0].x, coordinates[0].y);
for(let i=1; i<coordinates.length; i++)
{
ctx.lineTo(coordinates[i].x, coordinates[i].y);
}
ctx.lineTo(coordinates[0].x, coordinates[0].y);
ctx.stroke();
ctx.save();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.restore();
ctx.clip();
//redraw the image in the cropped area
let pattern = ctx.createPattern(image, "repeat");
ctx.fillStyle = pattern;
ctx.fill();
ctx.closePath();
}
function save()
{
let newCanvas = document.getElementById('canvas2');
//get new dimensions
let top = canvas.height;
let left = canvas.width;
let right = -canvas.width;
let bottom = -canvas.height;
for(let i=0; i<coordinates.length; i++)
{
if(coordinates[i].y < top)
top = coordinates[i].y;
if(coordinates[i].x < left)
left = coordinates[i].x;
if(coordinates[i].x > right)
right = coordinates[i].x;
if(coordinates[i].y > bottom)
bottom = coordinates[i].y;
}
newCanvas.width = right-left;
newCanvas.height = bottom-top;
//save the new image
newCanvas.getContext("2d").drawImage(canvas, left, top, newCanvas.width, newCanvas.height, 0, 0, newCanvas.width, newCanvas.height);
let downloadLink = document.createElement("a");
downloadLink.download = "crop.png";
downloadLink.href = newCanvas.toDataURL("image/png");
downloadLink.click();
}
h1 {
color: blue;
margin-bottom: 0px;
margin-top: 0px;
}
.image-div img {
max-width: 80vmin;
max-height: 80vmin;
border: 1px solid black;
}
.canvas-div {
margin-top: 240px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Test</title>
</head>
<body>
<h1>Image:</h1>
<div class="image-div">
<img id="pic" src="https://icatcare.org/app/uploads/2018/07/Helping-your-new-cat-or-kitten-settle-in-1.png">
</div>
<div class="canvas-div">
<h1>Canvas:</h1>
<canvas id="canvas" style="border: 1px solid blue;"></canvas>
</div>
<!-- for exporting the final result -->
<canvas id="canvas2" style="display: none;"></canvas>
<button onclick="crop()">Crop</button>
<button onclick="save()">Save</button>
<br><br><br>
<!-- script -->
<script src="script.js"></script>
</body>
</html>
Before reading the explanation try the following:
ctx.beginPath();
ctx.moveTo(coordinates[0].x, coordinates[0].y);
for(let i=1; i<coordinates.length; i++)
{
ctx.lineTo(coordinates[i].x, coordinates[i].y);
}
ctx.lineTo(coordinates[0].x, coordinates[0].y);
ctx.stroke();
ctx.closePath();
ctx.clip();
ctx.save();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.restore();
You will see that it does an invert cropping, that is, it clears the points you want to not clear and preserves the points you wanted to clear. So, to solve your problem, assuming that the crop will be a convex shape, you need the following:
get all the lines involved
create a polygon of the "outside" of the polygons
clear
Since you can have many different types of shapes and they can be convex or concave alike, it would be far-fetched for the purpose of a stackoverflow answer to implement the full logic, but this is how you can do it relatively easily:
Make sure that the lines are continuous, so if you draw the lines by hand from coordinates[0] to coordinates1 and then coordinates1 to coordinates[2], etc. then you will end up drawing the correct polygon (so each line between coordinates[i-1] and coordinates[i]) is a side of your polygon rather than a diagonal.
moveTo coordinates[0] and have a lineto for all coordinates, almost like you did, except for the very last one. So, you are effectively almost drawing the polygon except the very last line.
continue with lineto to a side of the canvas (careful though, not to cross the internal of the polygon) and then to all the edges of the canvas (the corners), so you are effectively defining a polygon that's a. outside your polygon b. ends at your last coordinate c. does not include your last line
clear
moveTo your penultimate coordinate, lineTo your last coordinate and then proceed with lineTo calls to draw the
The snippet below is a proof-of-concept that is a good starting point, but it is not a proper solution yet.
const image = document.getElementById("pic");
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
//draw the image on the canvas
canvas.width = image.width;
canvas.height = image.height;
ctx.drawImage(image, 0, 0, image.width, image.height);
//get mouse coordinates
let coordinates = [];
canvas.onclick = function clickEvent(e)
{
let rect = e.target.getBoundingClientRect();
let x = e.clientX - rect.left;
let y = e.clientY - rect.top;
let point = {
"x": x,
"y": y
};
coordinates.push(point);
ctx.fillStyle = "blue";
ctx.fillRect(x, y, 10, 10);
}
//debugging
console.log(coordinates);
//crop the image
function crop()
{
ctx.beginPath();
for(let i=0; i<coordinates.length - 1; i++)
{
ctx.lineTo(coordinates[i].x, coordinates[i].y);
}
ctx.lineTo(canvas.width, canvas.height);
ctx.lineTo(canvas.width, 0);
ctx.lineTo(0, 0);
ctx.lineTo(0, canvas.height);
ctx.lineTo(coordinates[0].x, coordinates[0].y);
ctx.stroke();
ctx.closePath();
ctx.clip();
ctx.save();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.restore();
}
function save()
{
let newCanvas = document.getElementById('canvas2');
//get new dimensions
let top = canvas.height;
let left = canvas.width;
let right = -canvas.width;
let bottom = -canvas.height;
for(let i=0; i<coordinates.length; i++)
{
if(coordinates[i].y < top)
top = coordinates[i].y;
if(coordinates[i].x < left)
left = coordinates[i].x;
if(coordinates[i].x > right)
right = coordinates[i].x;
if(coordinates[i].y > bottom)
bottom = coordinates[i].y;
}
newCanvas.width = right-left;
newCanvas.height = bottom-top;
//save the new image
newCanvas.getContext("2d").drawImage(canvas, left, top, newCanvas.width, newCanvas.height, 0, 0, newCanvas.width, newCanvas.height);
let downloadLink = document.createElement("a");
downloadLink.download = "crop.png";
downloadLink.href = newCanvas.toDataURL("image/png");
downloadLink.click();
}
h1 {
color: blue;
margin-bottom: 0px;
margin-top: 0px;
}
.image-div img {
max-width: 80vmin;
max-height: 80vmin;
border: 1px solid black;
}
.canvas-div {
margin-top: 240px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Test</title>
</head>
<body>
<h1>Image:</h1>
<div class="image-div">
<img id="pic" src="https://icatcare.org/app/uploads/2018/07/Helping-your-new-cat-or-kitten-settle-in-1.png">
</div>
<div class="canvas-div">
<h1>Canvas:</h1>
<canvas id="canvas" style="border: 1px solid blue;"></canvas>
</div>
<!-- for exporting the final result -->
<canvas id="canvas2" style="display: none;"></canvas>
<button onclick="crop()">Crop</button>
<button onclick="save()">Save</button>
<br><br><br>
<!-- script -->
<script src="script.js"></script>
</body>
</html>
I have a canvas and I want to print words on it in horizontal and vertical orientation. The printing itself works fine but I have a somewhat annoying spacing at the beginning of the words, which becomes extremely visible on the vertical text like the EX on the example image.
I just created a little example which shows what I mean
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
// Create a red line in position 150
ctx.strokeStyle = "red";
ctx.moveTo(150, 20);
ctx.lineTo(150, 170);
ctx.stroke();
ctx.font = "50px Arial";
// Show the different textAlign values
ctx.textAlign = "start";
ctx.fillText("EX", 150, 50);
ctx.textAlign = "end";
ctx.fillText("EX", 150, 100);
ctx.textAlign = "center";
ctx.fillText("EX", 150, 150);
<canvas id="myCanvas" width="300" height="200" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
Is there a way to place the beginning of the word at the point I am drawing to or is there a way to calculate the spacing at the beginning and then just subtract it from the starting point of the text?
The TextMetrics interface has actualBoundingBox[...] information that you can use to know by how much the actual bounding box is offset relatively to the textAlign and textBaseline lines.
So adding the measured actualBoundingBoxLeft to your horizontal position when writing LTR text with the "start" text-align will remove this gap.
const c = document.getElementById("myCanvas");
const ctx = c.getContext("2d");
const input = document.querySelector("input");
input.oninput = draw;
draw();
function draw() {
const txt = input.value;
ctx.clearRect(0, 0, c.width, c.height);
ctx.fillStyle = "black";
// Create a red line in position 150
ctx.strokeStyle = "red";
ctx.moveTo(150, 20);
ctx.lineTo(150, 180);
ctx.stroke();
ctx.font = "50px Arial";
ctx.textBaseline = "top"; // needed for the ascent and decsent measurements
// Show the original textAlign
ctx.textAlign = "start";
ctx.fillText(txt, 150, 30);
// fixed
ctx.fillStyle = "green";
const metrics = ctx.measureText(txt);
ctx.fillText(txt, 150 + metrics.actualBoundingBoxLeft, 110);
// Draw the box around our text
ctx.translate( 150, 110 );
const x = 0; // we already did offset by actualBoundingBoxLeft
const y = metrics.actualBoundingBoxAscent * -1;
const width = metrics.actualBoundingBoxRight + metrics.actualBoundingBoxLeft;
const height = metrics.actualBoundingBoxDescent + metrics.actualBoundingBoxAscent;
ctx.strokeRect(x, y, width, height);
ctx.setTransform(1, 0, 0, 1, 0, 0);
}
<input value="Éxy"><br>
<canvas id="myCanvas" width="300" height="200" style="border:1px solid #d3d3d3;"></canvas>
I am trying to create and fill a canvas as blue without using any html. I have been successful in rendering an empty canvas. The issue occurs when I try to fill the canvas with a color as seen below in the second code snippet. In the two snippets below, the only difference is which canvas is filled with blue (document.getElementsByClassName("blueCanvas")[0] in the first one, which works, and document.getElementsByClassName("blueCanvas")[2], which should fill the dynamically created canvas, and fails.
some things I have tried/noticed:
First I thought it was an issue with the order in the execution in the creation of the canvas and the js that tries to fill it, but the problem persists even when I create the canvas in the beginning of the <body>. I also thought it might be an issue of append the element to the DOM but it renders an empty canvas so I don't see how that's possible.
Thanks.
var newCanvas = document.createElement('canvas');
newCanvas.width = '300';
newCanvas.height = '150'
newCanvas.className = 'blueCanvas';
newCanvas.style = 'border:1px solid black'
newCanvas.innerHTML = '<canvas> </canvas>';
document.body.appendChild(newCanvas);
var canvas = document.getElementsByClassName("blueCanvas")[0];
var ctx = canvas.getContext("2d");
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
<canvas id="canvas" class='blueCanvas' width="300" height="150" style="border:1px solid black"></canvas>
<canvas id="canvas" class='blueCanvas' width="300" height="150" style="border:1px solid black"></canvas>
var newCanvas = document.createElement('canvas');
newCanvas.width = '300';
newCanvas.height = '150'
newCanvas.className='blueCanvas';
newCanvas.style= 'border:1px solid black'
newCanvas.innerHTML = '<canvas> </canvas>';
document.body.appendChild(newCanvas);
var canvas = document.getElementsByClassName("blueCanvas")[2];
var ctx = canvas.getContext("2d");
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
<canvas id="canvas" class='blueCanvas' width="300" height="150" style="border:1px solid black"></canvas>
<canvas id="canvas" class='blueCanvas' width="300" height="150" style="border:1px solid black"></canvas>
Since I know you read my comments:
function blueCanvas(){
let canvas = document.createElement('canvas'), style = canvas.style, ctx;
canvas.width = 300; canvas.height = 150; canvas.className = 'blueCanvas';
style.border = '1px solid black'; ctx = canvas.getContext('2d');
ctx.fillStyle = 'blue'; ctx.fillRect(0, 0, 300, 150);
document.body.appendChild(canvas);
}
blueCanvas();
Its not clear what you want.
Maybe this will help
const canvas = document.createElement('canvas');
canvas.width = 400; // size it
canvas.height = 300;
canvas.className = 'blueCanvas'; // assign class name
document.body.appendChild(canvas); // add to document
// get context
const ctx = canvas.getContext("2d");
// fill it with blue
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "black";
ctx.font = "32px Arial";
ctx.textAlign = "center";
ctx.fillText("Dynamically added canvas", 200, 100);
I am having trouble with blurry lines on the element.
ctx.moveTo(2,2);
ctx.lineTo(50,2);
ctx.arc(27,2,25,0,3.1415926);
ctx.stroke();
I tried making the linewidth 0.5 but that didn't fix it. Everything I try doesn't seem to do anything.
The result turns out very pixely.
See result on https://rawgit.com/Mythius/uploads/master/Platformer.html
If anyone knows how to fix this please let me know.
Do not set your canvas size in CSS alone.
The displayed size of the canvas can be changed using a stylesheet. The image is scaled during rendering to fit the styled size. If your renderings seem distorted, try specifying your width and height attributes explicitly in the attributes, and not using CSS.
Default canvas size
var canvas = document.getElementById('cnvs');
var ctx = canvas.getContext('2d');
ctx.lineWidth = 1;
ctx.translate(0.5, 0.5);
draw();
function draw() {
ctx.moveTo(0, 0);
ctx.lineTo(50, 0);
ctx.arc(25, 0, 25, 0, Math.PI);
ctx.stroke();
}
body {
background-color: #aaa;
}
#cnvs {
background-color: #fff;
border: 1px solid #000;
}
<canvas id="cnvs"></canvas>
With size specified on the canvas element attributes
var canvas = document.getElementById('cnvs');
var ctx = canvas.getContext('2d');
ctx.lineWidth = 1;
ctx.translate(0.5, 0.5);
draw();
function draw() {
ctx.moveTo(0, 0);
ctx.lineTo(50, 0);
ctx.arc(25, 0, 25, 0, Math.PI);
ctx.stroke();
}
body {
background-color: #aaa;
}
#cnvs {
width: 500px;
height: 500px;
background-color: #fff;
border: 1px solid #000;
}
<canvas id="cnvs" width="500" height="500"></canvas>
As an addendum to Sébastien's answer: The 'blockiness' of a canvas image sits at the confluence of screen resolution, canvas dimensions, and styling properties. Depending on these factors an image can appear more or less blocky/sharp - but there's only so much you can do.
Some people say that drawing to a larger canvas and styling it proportionally smaller improves the appearance of fine detail -- by the principle that small images made large look block so large images made small will look less blocky -- while others are not convinced.
Below is a snippet which draws the same content onto four canvases at two different sizes and resolutions, but all canvas are styled to the same on-screen dimensions. How blocky are they on your gear? To me they look pretty much the same, but when I save them I do notice a difference.
(function(doc) {
function $(a) {
switch (a.slice(0, 1)) {
case "#":
return doc.getElementById(a.slice(1));
case ".":
return [].slice.call(doc.getElementsByClassName(a.slice(1)));
}
}
function save(e) {
var cnv = $(e.target.getAttribute('data-canvas')),
lnx = $('#savelink');
lnx.href = cnv.toDataURL();
lnx.download = e.target.getAttribute('data-res') +
'_ ' + cnv.width + 'x' +
cnv.height + '.png';
lnx.click();
}
function lowRes(cnv, ctx) {
var img = new Image;
img.addEventListener('load', function() {
ctx.clearRect(0, 0, cnv.width, cnv.height);
ctx.drawImage(this, 0, 0);
});
img.src = cnv.toDataURL('image/jpeg', 0.64);
};
function draw(id, wh, lw, res) {
var cnv = $(id),
ctx = cnv.getContext('2d'),
xy = wh / 2,
fc = 8,
shrink = (xy * 0.9) / fc,
flag = !1;
cnv.width = wh,
cnv.height = wh,
ctx.lineWidth = lw;
ctx.fillStyle = '#eee';
ctx.fillRect(0,0,cnv.width,cnv.height);
ctx.beginPath();
ctx.moveTo(0, xy);
ctx.lineTo(cnv.width, xy);
while (--fc) {
ctx.arc(xy, xy, shrink * fc, 0, Math.PI, flag);
flag = !flag;
}
ctx.stroke();
ctx.fillStyle = '#777';
ctx.font = Math.round(cnv.height * 0.025) + 'px serif';
ctx.textAlign = 'right';
ctx.textBaseline = 'middle';
ctx.beginPath();
ctx.fillText(
('lineWidth = ' + lw +
', width/height = ' + wh + 'px, ' +
(res ? 'low-res' : 'hi-res')),
Math.round(cnv.width * 0.9),
Math.round(cnv.height * 0.96)
);
res && lowRes(cnv, ctx);
}
doc.addEventListener('DOMContentLoaded', function() {
[
['#c1', 500, 1, !1],
['#c2', 1500, 3, !1],
['#c3', 500, 1, !0],
['#c4', 1500, 3, !0]
].forEach(function(n) {
draw.apply(null, n);
});
$('.save').forEach(function(n) {
n.addEventListener('click', save, !1);
});
}, false);
}(document));
.ch {
position:relative;
width:500px;
height:500px;
border:1px solid #999;
margin:2rem auto;
}
.ch canvas {
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
display:block;
}
.ch .save {
position:absolute;
top:2%;
left:2%;
color:#aaa;
font-size:2rem;
font-weight:600;
cursor:pointer;
display:inline-block;
transition:color 333ms;
}
.ch .save:hover {
color:#000;
}
<div class="ch">
<canvas id="c1"></canvas>
<div class="save" title=" Save Image " data-canvas="#c1" data-res="hi">⇩</div>
</div>
<div class="ch">
<canvas id="c2"></canvas>
<div class="save" title=" Save Image " data-canvas="#c2" data-res="hi">⇩</div>
</div>
<div class="ch">
<canvas id="c3"></canvas>
<div class="save" title=" Save Image " data-canvas="#c3" data-res="lo">⇩</div>
</div>
<div class="ch">
<canvas id="c4"></canvas>
<div class="save" title=" Save Image " data-canvas="#c4" data-res="lo">⇩</div>
</div>
<a id="savelink" href="" download="" target="_blank"></a>
html code :
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript">
function start() {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var image = new Image();
image.onload = function () {
ctx.drawImage(image, 69, 50);
//draw a circle
ctx.beginPath();
ctx.arc(100, 75, 10, 0, Math.PI * 2, true);
ctx.stroke();
};
image.src = 'xy-coordinates.jpg';
}
</script>
</head>
<img id="myImgId" alt="" src="xy-coordinates.jpg" />
<input type="button" value="submit" onclick="start()">
<canvas id="myCanvas" width="700" height="393"></canvas>
</body>
</html>
I'm trying to draw a circle on an image dynamically once I click the button.
The problem is after clicking the button, I'm getting an extra image (with the circle drawn) displayed on the screen rather drawing on original image.
My requirement is to draw a circle on an image which is already displayed.
UPDATED
<script>
function Draw(){
var img = document.getElementById("theImg");
var cnvs = document.getElementById("myCanvas");
cnvs.style.position = "absolute";
cnvs.style.left = img.offsetLeft + "px";
cnvs.style.top = img.offsetTop + "px";
var ctx = cnvs.getContext("2d");
ctx.beginPath();
ctx.arc(250, 210, 10, 0, 2 * Math.PI, false);
ctx.lineWidth = 3;
ctx.stroke();
}
</script>
<img id='theImg' src='xy-coordinates.jpg'>
<input type='button' value='Draw' onclick='draw()' ><br>
<canvas id='myCanvas' width="700" height="393"></canvas>
when < br > is used in html tag befor or after canvas there comes a huge distance betweein image and button r any tags i place in there. how to rectify it ?
You don't need to create one more image because canvas in fact is an image by itself. Place your canvas on top of the source image by setting its position to absolute, left and top same as the source image:
var img = document.getElementById("myImgId");
var c = document.getElementById("myCanvas");
c.style.position = "absolute";
c.style.left = img.offsetLeft;
c.style.top = img.offsetTop;
Then just draw into canvas:
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.arc(100, 75, 10, 0, Math.PI * 2, true);
ctx.stroke();
UPDATE:
function Draw(){
var img = document.getElementById("theImg");
var cnvs = document.getElementById("myCanvas");
cnvs.style.position = "absolute";
cnvs.style.left = img.offsetLeft + "px";
cnvs.style.top = img.offsetTop + "px";
var ctx = cnvs.getContext("2d");
ctx.beginPath();
ctx.arc(250, 210, 200, 0, 2 * Math.PI, false);
ctx.lineWidth = 3;
ctx.strokeStyle = '#00ff00';
ctx.stroke();
}
#draw-btn {
font-size: 14px;
padding: 2px 16px 3px 16px;
margin-bottom: 8px;
}
<div>
<input id='draw-btn' type='button' value='Draw' onclick='Draw()' />
</div>
<img id='theImg' src='http://i.telegraph.co.uk/multimedia/archive/02351/cross-eyed-cat_2351472k.jpg'>
<canvas id='myCanvas' width='536px' height='536px'></canvas>
You are drawing one image on canvas, and second image with "img" tag (already displayed). you can't draw circle with canvas, on HTML tag.