Hi i have problem with the tag Canvas.
I'm using bootstrap and i want create a canvas with an image where i can draw a dots after click with the mouse but because i'm using bootstrap the canvas area stretch and the dots are not in the same place i have click with the mouse
$().ready(function() {
showImage();
$("#image").click(function(e) {
getMousePositionAtClick(e);
});
function showImage() {
var canvas = document.getElementById('image');
var ctx = canvas.getContext('2d');
var img = new Image();
img.src = 'images/Piantina.jpg';
img.onload = function() {
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height);
};
}
function getMousePositionAtClick(e) {
var rect = image.getBoundingClientRect();
var x = e.clientX - rect.left;
var y = e.clientY - rect.top;
alert(rect.left);
alert(rect.top);
drawPoint(x, y);
}
function drawPoint(x, y) {
var ctx = document.getElementById("image").getContext("2d");
ctx.fillStyle = "#000";
ctx.beginPath();
ctx.arc(x, y, 3, 0, Math.PI * 2, true);
ctx.fill();
}
});
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col-lg-8" id="columnCanvas">
<div class="card card-body">
<canvas id="image"></canvas>
</div>
</div>
As mentioned in comments above, a Canvas element is not responsive. Bootstrap on the other hand is meant to be responsive,. So to stop the scaling we can set the size. Looking at the spec for Canvas, the default size if not specified is 300px / 150px.. So in theory if we just set the Canvas CSS size to 300px/150px, this will also prevent the scaling, below is an example.
$().ready(function() {
showImage();
$("#image").click(function(e) {
getMousePositionAtClick(e);
});
function showImage() {
var canvas = document.getElementById('image');
var ctx = canvas.getContext('2d');
var img = new Image();
img.src = 'images/Piantina.jpg';
img.onload = function() {
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height);
};
}
function getMousePositionAtClick(e) {
var rect = image.getBoundingClientRect();
var x = e.clientX - rect.left;
var y = e.clientY - rect.top;
alert(rect.left);
alert(rect.top);
drawPoint(x, y);
}
function drawPoint(x, y) {
var ctx = document.getElementById("image").getContext("2d");
ctx.fillStyle = "#000";
ctx.beginPath();
ctx.arc(x, y, 3, 0, Math.PI * 2, true);
ctx.fill();
}
});
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col-lg-8" id="columnCanvas">
<div class="card card-body">
<canvas id="image" style="width:300px;height:150px"></canvas>
</div>
</div>
Related
I'm programming a canvas image to be able to zoom in/out after the control button is clicked.
The red ball normal size is 128x128px. when Zooming in too much...the image is clipped by its own container...how do I fix this?
working fiddle https://jsfiddle.net/vf8gvq7m/27/
This is what I've tried...
I want the zoom in to be correct without clipped image...
let M_GlassesZoom=1;
let L_GlassesZoom=1;
$('.ZoomGlasses').on("click",function(event) {
if($(this).hasClass("ZoomGlassesPlus")){
M_GlassesZoom+=0.5;
}
else if($(this).hasClass("ZoomGlassesLess")){
L_GlassesZoom+=0.5;
}
drawMe();
});
var canvas = document.getElementById('cv');
ctx = canvas.getContext('2d');
// core drawing function
var drawMe = function() {
var ImgGlasses = document.getElementById('glasses');
canvas.width = 400;
canvas.height = 400;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'blue';
ctx.fillRect(0,0,canvas.width, canvas.height);
var GlassesWidth=128;
var GlassesHeight=128;
if(M_GlassesZoom!=1){
GlassesWidth=GlassesWidth/M_GlassesZoom;
GlassesHeight=GlassesHeight/M_GlassesZoom;
}
if(L_GlassesZoom!=1){
GlassesWidth=GlassesWidth*L_GlassesZoom;
GlassesHeight=GlassesHeight*L_GlassesZoom;
}
ctx.drawImage(ImgGlasses, 0, 0, GlassesWidth, GlassesHeight, 50, 50, 128,128);
}
drawMe();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<button class="ZoomGlasses ZoomGlassesPlus">zoom +</button>
<button class="ZoomGlasses ZoomGlassesLess">zoom -</button><br/>
<canvas id="cv"></canvas>
<img src="https://upload.wikimedia.org/wikipedia/commons/d/d5/Japan_small_icon.png" style="height:70px;width:70px;opacity:0" height=70 width=70 id="glasses" />
You have the destination width/height fixed to 128px so when the ball gets bigger than that it will get clipped. Naturally, the source width and height should be fixed and the destination calculated.
let M_GlassesZoom=1;
let L_GlassesZoom=1;
$('.ZoomGlasses').on("click",function(event) {
if($(this).hasClass("ZoomGlassesPlus")){
M_GlassesZoom+=0.5;
}
else if($(this).hasClass("ZoomGlassesLess")){
L_GlassesZoom+=0.5;
}
drawMe();
});
var canvas = document.getElementById('cv');
ctx = canvas.getContext('2d');
// core drawing function
var drawMe = function() {
var ImgGlasses = document.getElementById('glasses');
canvas.width = 400;
canvas.height = 400;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'blue';
ctx.fillRect(0,0,canvas.width, canvas.height);
var GlassesWidth=128;
var GlassesHeight=128;
if(M_GlassesZoom!=1){
GlassesWidth=GlassesWidth/M_GlassesZoom;
GlassesHeight=GlassesHeight/M_GlassesZoom;
}
if(L_GlassesZoom!=1){
GlassesWidth=GlassesWidth*L_GlassesZoom;
GlassesHeight=GlassesHeight*L_GlassesZoom;
}
ctx.drawImage(ImgGlasses, 0, 0, 128,128, 50, 50, GlassesWidth, GlassesHeight);
}
drawMe();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<button class="ZoomGlasses ZoomGlassesPlus">zoom +</button>
<button class="ZoomGlasses ZoomGlassesLess">zoom -</button><br/>
<canvas id="cv"></canvas>
<img src="https://upload.wikimedia.org/wikipedia/commons/d/d5/Japan_small_icon.png" style="height:70px;width:70px;opacity:0" height=70 width=70 id="glasses" />
I'm using the multiply value for the globalCompositeOperation property to apply a tint to a clipped region of an image. It works, but the bottom edge of the image sometimes gets a white border.
// Code goes here
document.addEventListener("DOMContentLoaded", function() {
var canvas = document.getElementById('myCanvas');
var img = new Image();
img.onload = function() {
render();
}
img.src = 'http://i.imgur.com/qiJkgK9.jpg';
function render() {
canvas.width = img.width * 2;
canvas.height = img.height * 2;
var ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
ctx.save();
ctx.beginPath();
ctx.rect(200, 200, 200, 200);
ctx.clip();
ctx.globalCompositeOperation = 'multiply';
ctx.fillStyle = 'red';
ctx.fill();
ctx.restore();
ctx.save();
ctx.beginPath();
ctx.rect(300, 100, 200, 200);
ctx.clip();
ctx.globalCompositeOperation = 'multiply';
ctx.fillStyle = 'red';
ctx.fill();
ctx.restore();
}
});
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<canvas id="myCanvas"></canvas>
</body>
</html>
How to prevent the border from appearing OR is there a better way to apply multiply tint to an image?
You can just use fillRect to the exact rectangle you're looking for instead of clip and fill, which is causing your clipping issue.
var canvas = document.getElementById('myCanvas');
function render() {
canvas.width = img.width * 2;
canvas.height = img.height * 2;
var ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
ctx.globalCompositeOperation = 'multiply';
ctx.fillStyle = 'red';
ctx.fillRect(200, 200, 200, 200);
ctx.fillRect(300, 100, 200, 200);
}
var img = new Image();
img.onload = render;
img.src = 'http://i.imgur.com/qiJkgK9.jpg';
<canvas id="myCanvas"></canvas>
I am making a canvas, where there is a large image and behind it there is another image. then by using mouse coordinate I made a circle around the cursor. This circle will work as a hole to reveal the hidden image under the background. I made it kinda but I cannot set the front image.
Have a look at my code please: JSFiddle
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = 0;
var y = 0;
var width = 578;
var height = 400;
var imageObj = new Image();
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
function writeMessage(canvas, message, x, y) {
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
var pattern = context.createPattern(imageObj, 'no-repeat');
context.fillStyle = pattern;
context.fill();
context.font = '28pt Calibri';
context.fillStyle = 'black';
//context.fillText(message, x, y);
context.beginPath();
context.arc(x, y, 50, 0, 2 * Math.PI);
context.stroke();
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
canvas.addEventListener('mousemove', function (evt) {
var mousePos = getMousePos(canvas, evt);
//var message = 'Mouse position: ' + mousePos.x + ',' + mousePos.y;
writeMessage(canvas, message, mousePos.x, mousePos.y);
}, false);
context.fillStyle = 'black';
context.fill();
Can someone tell me please how to have an image as big as the canvas to cover it?
Thanks
It looks like you are on the right track. The easiest way to have an image where the circle is not in your setup, would be to set a background image on the canvas element, and use background-size: cover to make it fill the canvas area.
Working Example (see CSS in second block):
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = 0;
var y = 0;
var width = 578;
var height = 400;
var imageObj = new Image();
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
function writeMessage(canvas, message, x, y) {
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
var pattern = context.createPattern(imageObj, 'no-repeat');
context.fillStyle = pattern;
context.fill();
context.font = '28pt Calibri';
context.fillStyle = 'black';
//context.fillText(message, x, y);
context.beginPath();
context.arc(x, y, 50, 0, 2 * Math.PI);
context.stroke();
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
canvas.addEventListener('mousemove', function (evt) {
var mousePos = getMousePos(canvas, evt);
var message = 'Mouse position: ' + mousePos.x + ',' + mousePos.y;
writeMessage(canvas, message, mousePos.x, mousePos.y);
}, false);
canvas, img {
display:block;
margin:1em auto;
border:1px solid black;
}
canvas {
background:url('http://img2.wikia.nocookie.net/__cb20090917002539/starwars/images/7/70/Vader_yelloweyes.jpg');
background-size: cover;
}
<canvas id="myCanvas" width="578" height="400"></canvas>
<p></p>
To get the foreground image to fill the canvas, and take care of the edge, you need to resize the image in another canvas.
Working Example:
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = 0;
var y = 0;
var width = 578;
var height = 400;
var imageObj = new Image();
//Create another canvas to darw a resized image to.
var imageResized = document.createElement('canvas');
imageResized.width = width;
imageResized.height = height;
//Wait for the original image to low to draw the resize.
imageObj.onload = function() {
//Find hoe mauch to scale the image up to cover.
var scaleX = width / imageObj.width;
var scaleY = height / imageObj.height;
var scaleMax = Math.max(scaleX, scaleY);
var ctx = imageResized.getContext('2d');
ctx.scale(scaleMax, scaleMax);
ctx.drawImage(imageObj, 0, 0);
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
function writeMessage(canvas, message, x, y) {
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
var pattern = context.createPattern(imageResized, 'no-repeat');//Use imageResized, not imageObj.
context.fillStyle = pattern;
context.fill();
context.font = '28pt Calibri';
context.fillStyle = 'black';
//context.fillText(message, x, y);
context.beginPath();
context.arc(x, y, 50, 0, 2 * Math.PI);
context.stroke();
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
canvas.addEventListener('mousemove', function (evt) {
var mousePos = getMousePos(canvas, evt);
var message = 'Mouse position: ' + mousePos.x + ',' + mousePos.y;
writeMessage(canvas, message, mousePos.x, mousePos.y);
}, false);
canvas, img {
display:block;
margin:1em auto;
border:1px solid black;
}
canvas {
background:url('http://img2.wikia.nocookie.net/__cb20090917002539/starwars/images/7/70/Vader_yelloweyes.jpg');
background-size: cover;
}
<canvas id="myCanvas" width="578" height="400"></canvas>
<p></p>
Is it possible to show / hide part of canvas image like Image Sprite ?
Example Case:
I have a canvas of 200 X 200 dimension.
On One button click i want to show part of canvas from point (100, 100) to (120, 120).
On another i want to show entire canvas.
Any help in how to do this?
As sprite are usually shown within another element as a background, perhaps hiding the parent element would take care of your problem?
<style>
#sprite {
width: 100px;
height: 100px;
background-image: src(sprite.png);
background-position: 100px 100px;
}
</style>
<script>
var hide = false;
function show() {
if(!hide) {
document.getElementById("sprite").style.width="200px";
hide = true;
}
else {
document.getElementById("sprite").style.width="100px";
hide = false;
}
}
</script>
<div id="button" onclick="show();">button</div>
<div id="sprite"></div>
This is if the sprite's position is 100px to the right. You could also use document.getElementById('#sprite').style.backgroundPosition="200px 200px"; to change position of the sprite background entirely.
You can use the clipping form of drawImage to display your desired portion of the full image:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var img=new Image();
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/cats.png";
function start(){
ctx.drawImage(img, 0,0,78,86, 0,0,78,86);
document.getElementById('partial').onclick=function(){
ctx.clearRect(0,0,cw,ch);
ctx.drawImage(img, 0,0,78,86, 0,0,78,86);
}
document.getElementById('full').onclick=function(){
ctx.clearRect(0,0,cw,ch);
ctx.drawImage(img, 0,0);
}
}
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<button id='partial'>Show partial canvas</button>
<button id='full'>Show full canvas</button>
<br><canvas id="canvas" width=300 height=300></canvas>
You can clip the image this way.
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var btn = document.getElementById('btn');
var c = 0;
var img = new Image();
img.src = 'http://placehold.it/200/200';
img.onload = function() {
canvas.width = img.width;
canvas.height = img.height;
context.drawImage(img, 0, 0)
}
btn.onclick = function() {
if (c++ % 2 == 0) {
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(img, 100, 100, 20, 20, 100, 100, 20, 20);
btn.value = 'Unclip';
}
else {
context.drawImage(img, 0, 0);
btn.value = 'Clip';
}
}
<input id="btn" type="button" value="Clip" /><br />
<canvas id="canvas"></canvas>
EDIT
When a user clicks on the canvas, you can get the exact co-ordinates of where the event happened and if the co-ordinates lies inside of the middle circle, you can toggle the whole image by using the same clipping method.
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var c = 0;
var img = new Image();
img.src = 'http://s25.postimg.org/cv29exevj/index.png';
img.onload = function() {
canvas.width = img.width;
canvas.height = img.height;
context.drawImage(img, 80, 80, 40, 40, 80, 80, 40, 40);
}
canvas.onclick = function(e) {
var x = e.clientX - canvas.getBoundingClientRect().left;
var y = e.clientY - canvas.getBoundingClientRect().top;
if (x >= 80 && x <= 120 && y >= 80 && y <= 120) {
if (c++ % 2 == 0) {
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(img, 0, 0);
} else {
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(img, 80, 80, 40, 40, 80, 80, 40, 40);
}
}
}
<canvas id="canvas"></canvas>
I am reading through "Making Isometric Social Real-Time Games with HTML5, CSS3 and Javascript."
I am not far into it, and I have run into a canvas problem that has ahd me stumped for most of the day.
drawImage() does not seem to be drawing. I have researched the issue and have tried many permutations of pre-loading the image, but so far nothing is working.
Here is my code:
HTML:
<canvas id="game" width="100" height="100">
Your browser doesn't include support for the canvas element.
</canvas>
CSS:
html {
height:100%;
overflow:hidden
}
body {
margin:0px;
padding:0px;
height:100%;
}
and js:
window.onload = function() {
var canvas = document.getElementById('game');
canvas.width=document.body.clientWidth;
canvas.height=document.body.clientHeight;
var c = canvas.getContext('2d');
function showIntro() {
var phrase = "Click or tap screen to start";
c.clearRect (0, 0, canvas.width, canvas.height);
var grd = c.createLinearGradient(0, 0, canvas.width, canvas.height);
grd.addColorStop(0, "#9db7a0");
grd.addColorStop(1, "#e6e6e6");
c.fillStyle = grd;
c.fillRect (0, 0, canvas.width, canvas.height);
var logoImg = new Image();
logoImg.src = '../img/logo.png';
var originalWidth = logoImg.width;
logoImg.width = Math.round((50 * document.body.clientWidth) / 100);
logoImg.height = Math.round((logoImg.width * logoImg.height) / originalWidth);
var logo = {
img: logoImg,
x: (canvas.width/2) - (logoImg.width/2),
y: (canvas.height/2) - (logoImg.height/2)
}
c.drawImage(logo.img, logo.x, logo.y, logo.img.width, logo.img.height);
c.font = "bold 16px sans-serif";
var mt = c.measureText(phrase);
var xcoord = (canvas.width / 2 ) - (mt.width / 2);
c.fillStyle = '#656565'
c.fillText (phrase, xcoord, 30);
}
showIntro();
}
Any help would be appreciated!
You almost have it...
You just have to give the image time to load before drawing it.
You give an image time to load with this code:
var logoImg = new Image();
logoImg.onload = function() {
// At this point, the image is fully loaded
// So do your thing!
};
logoImg.src = "myPic.png";
Here is complete code and a Fiddle: http://jsfiddle.net/m1erickson/GKK39/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var c=canvas.getContext("2d");
function showIntro() {
var phrase = "Click or tap screen to start";
var logoImg=new Image();
logoImg.onload=function(){
c.clearRect (0, 0, canvas.width, canvas.height);
var grd = c.createLinearGradient(0, 0, canvas.width, canvas.height);
grd.addColorStop(0, "#9db7a0");
grd.addColorStop(1, "#e6e6e6");
c.fillStyle = grd;
c.fillRect (0, 0, canvas.width, canvas.height);
var originalWidth = logoImg.width;
logoImg.width = Math.round((50 * document.body.clientWidth) / 100);
logoImg.height = Math.round((logoImg.width * logoImg.height) / originalWidth);
var logo = {
img: logoImg,
x: (canvas.width/2) - (logoImg.width/2),
y: (canvas.height/2) - (logoImg.height/2)
}
c.drawImage(logo.img, logo.x, logo.y, logo.img.width, logo.img.height);
c.font = "bold 16px sans-serif";
var mt = c.measureText(phrase);
var xcoord = (canvas.width / 2 ) - (mt.width / 2);
c.fillStyle = '#656565'
c.fillText (phrase, xcoord, 30);
}
logoImg.src="http://dl.dropbox.com/u/139992952/car.png";
}
showIntro();
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
A simplified version of the above answer.
//Create Canvas
var canvas = document.createElement("canvas");
canvas.width = 720
canvas.height = 500;
//Get Context
var ctx = canvas.getContext("2d");
ctx .fillStyle = "black";
ctx .fillRect(0, 0, canvas.width, canvas.height);
//Load Image
var img = new Image();
img.src = "https://images.pexels.com/photos/3722151/pexels-photo-3722151.jpeg";
img.onload = function() {
ctx .drawImage(
img,
0,
0,
canvas.width,
canvas.height
);
};
//Add Canvas
canvas.id = "fatLady";
document.body.appendChild(canvas);
Try it on CodePen
https://codepen.io/hiteshsahu/pen/QWjrygb?editors=1111