How to remove thin border on 2 sides of canvas element? - html

UPDATE: Link to JSFiddle with workable code
I'm making a website and have created a stack of two canvas elements: the top canvas context is a white rectangle that "erases" to reveal an image loaded into the bottom canvas context. The functionality works properly. My issue is that a thin grey border appears on the right and bottom sides of the canvas stack when I include a setInterval line of code.
It disappears when I remove this timer variable (see code below) but reappears if I add any type of state check like onmouseout to the canvas elements. Here is a screenshot:
Any idea why this is happening? Similar SO questions/solutions have not solved my problem.
window.onload = function() {
var speaker = document.getElementById('speaker');
//speaker.onload = MoveElement(speaker, "right", 1000);
//Create canvases & contexts
var canvas = document.getElementById('canvas');
var ctxB = canvas.getContext('2d');
var canvas2 = document.getElementById('canvas2');
var ctxT = canvas2.getContext('2d');
//Get waterfall image object
var waterfall = document.getElementById('waterfall');
//Set canvas w&h properties
canvas.width = canvas2.width = .3*waterfall.width;
canvas.height = canvas2.height = .3*waterfall.height;
//Populate Bottom canvas with waterfall image
ctxB.drawImage(waterfall, 0, 0, canvas.width, canvas.height);
//Populate Top canvas with white rectangle
ctxT.fillStyle = "white";
ctxT.fillRect(0, 0, canvas2.width, canvas2.height);
//Make Top canvas "erasable"
canvas2.addEventListener('mousemove', event => {
var x = event.offsetX;
var y = event.offsetY;
const eraseSize = 15;
ctxT.clearRect(x-eraseSize/2, y-eraseSize/2, eraseSize, eraseSize);
});
}
//Set interval timer to repeatedly execute TransparencyCheck()
var timer = setInterval(TransparencyCheck, 500);
//Check that all pixel alpha values = 0
function TransparencyCheck() {
var canvas2 = document.getElementById('canvas2');
var ctxT = canvas2.getContext('2d');
var imageDataTop = ctxT.getImageData(0, 0, canvas2.width, canvas2.height);
var counter = 0;
for (var i = 3; i < imageDataTop.data.length; i += 4) {
if (imageDataTop.data[i] == 0) {
counter++;
}
if (counter == imageDataTop.data.length/4) {
canvas2.style.opacity = "0";
}
}
}
#stack {
position: relative;
}
#stack canvas {
position: absolute;
display: block;
left: 50%;
transform: translateX(-50%);
margin-top: 150px;
}
<img hidden src="https://sample-videos.com/img/Sample-jpg-image-50kb.jpg" alt="issue here" id="waterfall" />
<div id="stack">
<canvas id="canvas"></canvas>
<canvas id="canvas2" onmouseout="TransparencyCheck()"></canvas>
</div>

The problem is that the dimensions of the canvas are being calculated as a fraction (0.3) of the dimensions of the underlying image. This can result in a 'part pixel' problem. That is the system has to decide how to show a fraction of a CSS pixel, and on modern screens several screen pixels are used to show one CSS pixel. A screen pixwl can get 'left behind' (ie still showing) during this process.
A slightly hacky way of getting round this (but I know of no other) is to decrease the size of the bottom canvas by a few pixels so that we are absolutely sure any left overs are under the white of the top canvas at the start.
This snippet makes doubly sure by taking 2px off the width and height.
Incdentally, I copied the code from the codepen pointed at by the question and it worked as an SO snippet OK. Here it is:
window.onload = function() {
var speaker = document.getElementById('speaker');
//speaker.onload = MoveElement(speaker, "right", 1000);
//Create canvases & contexts
var canvas = document.getElementById('canvas');
var ctxB = canvas.getContext('2d');
var canvas2 = document.getElementById('canvas2');
var ctxT = canvas2.getContext('2d');
//Get waterfall image object
var waterfall = document.getElementById('waterfall');
//Set canvas w&h properties
canvas.width = canvas2.width = .3 * waterfall.width;
canvas.width = canvas.width - 2;
canvas.height = canvas2.height = .3 * waterfall.height;
canvas.height = canvas.height - 2;
//Populate Bottom canvas with waterfall image
ctxB.drawImage(waterfall, 0, 0, canvas.width, canvas.height);
//Populate Top canvas with white rectangle
ctxT.fillStyle = "white";
ctxT.fillRect(0, 0, canvas2.width, canvas2.height);
//Make Top canvas "erasable"
canvas2.addEventListener('mousemove', event => {
var x = event.offsetX;
var y = event.offsetY;
const eraseSize = 15;
ctxT.clearRect(x - eraseSize / 2, y - eraseSize / 2, eraseSize, eraseSize);
});
}
//Set interval timer to repeatedly execute TransparencyCheck()
var timer = setInterval(TransparencyCheck, 5000);
//Check that all pixel alpha values = 0
function TransparencyCheck() {
var canvas2 = document.getElementById('canvas2');
var ctxT = canvas2.getContext('2d');
var imageDataTop = ctxT.getImageData(0, 0, canvas2.width, canvas2.height);
var counter = 0;
for (var i = 3; i < imageDataTop.data.length; i += 4) {
if (imageDataTop.data[i] == 0) {
counter++;
}
if (counter >= imageDataTop.data.length / 4) {
canvas2.style.opacity = "0";
clearTimeout(timer);
alert('all top canvas erased');
}
}
}
#stack {
position: relative;
}
#stack canvas {
position: absolute;
display: block;
left: 50%;
transform: translateX(-50%);
margin-top: 150px;
}
<img hidden src="https://sample-videos.com/img/Sample-jpg-image-50kb.jpg" alt="issue here" id="waterfall" />
<div id="stack">
<canvas id="canvas"></canvas>
<canvas id="canvas2" onmouseout="TransparencyCheck()"></canvas>
</div>

Related

How to draw a square on canvas

I'm trying to draw squares at the corners of a canvas. The top ones work but I should be able to draw the third square which I have partially drawn.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<script type="application/javascript">
function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
var t = getRandomInt(10);
function draw() {
function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
var t = getRandomInt(10);
const canvas = document.getElementById('canvas');
if (canvas.getContext) {
const ctx = canvas.getContext('2d');
setInterval(myTimer, t*100);
function myTimer() {
var i = 0;
var x = window.innerWidth;
var y = window.innerHeight;
y = y + 100;
//draw crosshair
console.log("x = "+ x);
console.log("y = "+ y);
console.log("i = "+ i);
ctx.beginPath();
var crosshairlength = 20;
var lengthxminus = crosshairlength;
var lengthxplus = crosshairlength;
var lengthyminus = crosshairlength;
var lengthyplus = crosshairlength;
//horizontal line
ctx.moveTo((x/2)-lengthxminus, y/2);
ctx.lineTo((x/2)+lengthxplus, y/2);
//vertical line
ctx.moveTo(x/2, (y/2)-lengthyminus);
ctx.lineTo(x/2, (y/2)+lengthyplus);
var t = 10;
//top left
ctx.moveTo(0,0);
ctx.lineTo(t,0);
ctx.lineTo(t,t);
ctx.lineTo(0,t);
ctx.lineTo(0,0);
//top right
ctx.moveTo(x-t,0);
ctx.lineTo(x,0);
ctx.lineTo(x,t);
ctx.lineTo(x-t,t);
ctx.lineTo(x-t,0);
//bottom right
ctx.moveTo(x-t,y-t);
ctx.lineTo(x,y-t);
ctx.lineTo(x,y);
//bottom left
ctx.stroke();
}
i++;
}
}
</script>
</head>
<body onload="draw();">
<canvas id="canvas" width="1846" height="768"></canvas>
</body>
</html>
Either the canvas is the not the size of the viewport or I am misunderstanding the coordinate system which I believe has the positive y-axis going down and the origin is in the top left.
window.innerWidth and window.innerHeight represent the width and height of the viewport. Your <canvas> width and height are set by its width and height attributes.
If you want the canvas to be the size of the viewport, change these attributes, though changing these attributes come with great side-effects like reassigning a new pixel buffer, and clearing all the properties of the attached context, so it's better to do so only when really needed:
if (canvas.width !== x) {
canvas.width = x;
}
if (canvas.height !== y) {
canvas.height = y;
}
And if you wanted to use the size of the canvas rather than the one of the viewport, then you want
function myTimer() {
var i = 0;
var x = canvas.width;
var y = canvas.height;

HTML Canvas: Why image not getting drawn to canvas?

HTML:
<img src="http://lorempixel.com/100/100/">
<img src="http://lorempixel.com/100/100/">
<img src="http://lorempixel.com/100/100/">
<img src="http://lorempixel.com/100/100/">
<canvas id="canvas" width="0" height="0"></canvas>
Javascript:
var images = document.getElementsByTagName('img');
var canvas = document.getElementById('canvas');
for (var i = 0; i < images.length; i++) {
canvas.getContext('2d').drawImage(images[i], canvas.width, canvas.height);
canvas.height = canvas.height + images[i].height;
canvas.width = images[i].width;
}
Here's the fiddle:
https://jsfiddle.net/083bapwz/29/
Why is the canvas not visible or I guess, not even getting drawn? I want it to be drawn one after another, first on top, others followed in bottom.
A couple things.
First, changing the canvas width/height dimensions resets all existing canvas state. It is a hackier (and less supported) form of clearRect.
Take the following snippet for example:
var images = document.getElementsByTagName('img');
var canvas = document.getElementById('canvas');
var canvas2 = document.getElementById('canvas2');
var canvas3 = document.getElementById('canvas3');
var ctx1 = canvas.getContext('2d');
var ctx2 = canvas2.getContext('2d');
var ctx3 = canvas3.getContext('2d');
// wont draw
ctx1.moveTo(0, 0);
ctx1.lineTo(100, 100);
ctx1.stroke();
canvas.width = 300;
// wont draw
ctx2.moveTo(0, 0);
ctx2.lineTo(50, 50);
ctx2.stroke();
canvas2.height = 100;
// will draw
ctx3.moveTo(0, 0);
ctx3.lineTo(100, 100);
ctx3.stroke();
#canvas{border: 1px solid red;}
#canvas2{border: 1px solid blue;}
#canvas3{border: 1px solid green;}
<canvas id="canvas" width="200" height="200"></canvas>
<canvas id="canvas2" width="200" height="200"></canvas>
<canvas id="canvas3" width="200" height="200"></canvas>
In other words, don't resize the canvas since the last image would be the only one to draw.
Second, you are telling the image to draw at the (x, y) position of the canvas.width and canvas.height. This mean you will be drawing the image here:
You need to specify the (top, left) x/y values for the image drawing.
Hope this helps.
EDIT:
Possible solution could be the following demo:
var images = document.getElementsByTagName('img');
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var imageArray = Array.from(images);
// add all image heights together
var canvasHeight = imageArray.reduce(function (acc, img) {
acc += img.height;
return acc;
}, 0);
// just use first image as the width for this example
var canvasWidth = imageArray[0].width;
// set all canvas state prior to draws
canvas.height = canvasHeight;
canvas.width = canvasWidth;
var top = 0;
for (var i = 0; i < imageArray.length; i++) {
var image = imageArray[i];
// use x of 0 to draw on left most of canvas
canvas.getContext('2d').drawImage(image, 0, top);
top += image.height;
}

HTML5 Canvas background image

I'm trying to place a background image on the back of this canvas script I found. I know it's something to do with the context.fillstyle but not sure how to go about it. I'd like that line to read something like this:
context.fillStyle = "url('http://www.samskirrow.com/background.png')";
Here is my current code:
var waveform = (function() {
var req = new XMLHttpRequest();
req.open("GET", "js/jquery-1.6.4.min.js", false);
req.send();
eval(req.responseText);
req.open("GET", "js/soundmanager2.js", false);
req.send();
eval(req.responseText);
req.open("GET", "js/soundcloudplayer.js", false);
req.send();
eval(req.responseText);
req.open("GET", "js/raf.js", false);
req.send();
eval(req.responseText);
// soundcloud player setup
soundManager.usePolicyFile = true;
soundManager.url = 'http://www.samskirrow.com/client-kyra/js/';
soundManager.flashVersion = 9;
soundManager.useFlashBlock = false;
soundManager.debugFlash = false;
soundManager.debugMode = false;
soundManager.useHighPerformance = true;
soundManager.wmode = 'transparent';
soundManager.useFastPolling = true;
soundManager.usePeakData = true;
soundManager.useWaveformData = true;
soundManager.useEqData = true;
var clientID = "345ae40b30261fe4d9e6719f6e838dac";
var playlistUrl = "https://soundcloud.com/kyraofficial/sets/kyra-ft-cashtastic-good-love";
var waveLeft = [];
var waveRight = [];
// canvas animation setup
var canvas;
var context;
function init(c) {
canvas = document.getElementById(c);
context = canvas.getContext("2d");
soundManager.onready(function() {
initSound(clientID, playlistUrl);
});
aniloop();
}
function aniloop() {
requestAnimFrame(aniloop);
drawWave();
}
function drawWave() {
var step = 10;
var scale = 60;
// clear
context.fillStyle = "#ff19a7";
context.fillRect(0, 0, canvas.width, canvas.height);
// left wave
context.beginPath();
for ( var i = 0; i < 256; i++) {
var l = (i/(256-step)) * 1000;
var t = (scale + waveLeft[i] * -scale);
if (i == 0) {
context.moveTo(l,t);
} else {
context.lineTo(l,t); //change '128' to vary height of wave, change '256' to move wave up or down.
}
}
context.stroke();
// right wave
context.beginPath();
context.moveTo(0, 256);
for ( var i = 0; i < 256; i++) {
context.lineTo(4 * i, 255 + waveRight[i] * 128.);
}
context.lineWidth = 0.5;
context.strokeStyle = "#000";
context.stroke();
}
function updateWave(sound) {
waveLeft = sound.waveformData.left;
}
return {
init : init
};
})();
Revised code - currently just showing black as the background, not an image:
// canvas animation setup
var backgroundImage = new Image();
backgroundImage.src = 'http://www.samskirrow.com/images/main-bg.jpg';
var canvas;
var context;
function init(c) {
canvas = document.getElementById(c);
context = canvas.getContext("2d");
soundManager.onready(function() {
initSound(clientID, playlistUrl);
});
aniloop();
}
function aniloop() {
requestAnimFrame(aniloop);
drawWave();
}
function drawWave() {
var step = 10;
var scale = 60;
// clear
context.drawImage(backgroundImage, 0, 0);
context.fillRect(0, 0, canvas.width, canvas.height);
// left wave
context.beginPath();
for ( var i = 0; i < 256; i++) {
var l = (i/(256-step)) * 1000;
var t = (scale + waveLeft[i] * -scale);
if (i == 0) {
context.moveTo(l,t);
} else {
context.lineTo(l,t); //change '128' to vary height of wave, change '256' to move wave up or down.
}
}
context.stroke();
// right wave
context.beginPath();
context.moveTo(0, 256);
for ( var i = 0; i < 256; i++) {
context.lineTo(4 * i, 255 + waveRight[i] * 128.);
}
context.lineWidth = 0.5;
context.strokeStyle = "#ff19a7";
context.stroke();
}
function updateWave(sound) {
waveLeft = sound.waveformData.left;
}
return {
init : init
};
})();
Theres a few ways you can do this. You can either add a background to the canvas you are currently working on, which if the canvas isn't going to be redrawn every loop is fine. Otherwise you can make a second canvas underneath your main canvas and draw the background to it. The final way is to just use a standard <img> element placed under the canvas. To draw a background onto the canvas element you can do something like the following:
Live Demo
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
canvas.width = 903;
canvas.height = 657;
var background = new Image();
background.src = "http://www.samskirrow.com/background.png";
// Make sure the image is loaded first otherwise nothing will draw.
background.onload = function(){
ctx.drawImage(background,0,0);
}
// Draw whatever else over top of it on the canvas.
Why don't you style it out:
<canvas id="canvas" width="800" height="600" style="background: url('./images/image.jpg')">
Your browser does not support the canvas element.
</canvas>
Make sure that in case your image is not in the dom, and you get it from local directory or server, you should wait for the image to load and just after that to draw it on the canvas.
something like that:
function drawBgImg() {
let bgImg = new Image();
bgImg.src = '/images/1.jpg';
bgImg.onload = () => {
gCtx.drawImage(bgImg, 0, 0, gElCanvas.width, gElCanvas.height);
}
}
Canvas does not using .png file as background image. changing to other file extensions like gif or jpg works fine.

Create links in HTML canvas

Is it possible to create html links out of text that is rendered in a canvas element?
There is no easy way. You will have to draw the link text onto the canvas and then check for mouseclicks. Here is a demo html page:
<html>
<head>
<script type="text/javascript">
var canvas = document.getElementById("myCanvas");
var ctx;
var linkText="https://stackoverflow.com";
var linkX=5;
var linkY=15;
var linkHeight=10;
var linkWidth;
var inLink = false;
// draw the balls on the canvas
function draw(){
canvas = document.getElementById("myCanvas");
// check if supported
if(canvas.getContext){
ctx=canvas.getContext("2d");
//clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
//draw the link
ctx.font='10px sans-serif';
ctx.fillStyle = "#0000ff";
ctx.fillText(linkText,linkX,linkY);
linkWidth=ctx.measureText(linkText).width;
//add mouse listeners
canvas.addEventListener("mousemove", on_mousemove, false);
canvas.addEventListener("click", on_click, false);
}
}
//check if the mouse is over the link and change cursor style
function on_mousemove (ev) {
var x, y;
// Get the mouse position relative to the canvas element.
if (ev.layerX || ev.layerX == 0) { //for firefox
x = ev.layerX;
y = ev.layerY;
}
x-=canvas.offsetLeft;
y-=canvas.offsetTop;
//is the mouse over the link?
if(x>=linkX && x <= (linkX + linkWidth) && y<=linkY && y>= (linkY-linkHeight)){
document.body.style.cursor = "pointer";
inLink=true;
}
else{
document.body.style.cursor = "";
inLink=false;
}
}
//if the link has been clicked, go to link
function on_click(e) {
if (inLink) {
window.location = linkText;
}
}
</script>
</head>
<body onload="draw()">
<center>
<canvas id="myCanvas" width="200" height="200" style="border-style:solid;border-width:1px">Canvas not supported.</canvas>
</center>
</body>
</html>
This example shows how you can add multiple links to your HTML canvas:
<!DOCTYPE html>
<!-- This page shows how to add multiple links to <canvas> (by Yakovenko Max) -->
<html>
<head>
<title>Canvas Links Example</title>
<script>
function OnLoad(){
// Get canvas
var canvas = document.getElementById("myCanvas");
// 2d context
var ctx = canvas.getContext("2d");
ctx.translate(0.5, 0.5); // * Move the canvas by 0.5px to fix blurring
// Block border
ctx.strokeStyle = "#5F7FA2";
ctx.strokeRect(50, 50, 185, 90);
// Photo
var img = new Image();
img.src = "http://www.cs.washington.edu/education/courses/csep576/05wi/projects/project4/web/artifact/liebling/average_face.gif";
img.onload = function(){
ctx.drawImage(img, 59.5, 59.5); // Use -0.5px on photos to prevent blurring caused by * fix
}
// Text
ctx.fillStyle = "#000000";
ctx.font = "15px Tahoma";
ctx.textBaseline = "top";
ctx.fillText("Username", 95, 65);
// ***** Magic starts here *****
// Links
var Links = new Array(); // Links information
var hoverLink = ""; // Href of the link which cursor points at
ctx.fillStyle = "#0000ff"; // Default blue link color
ctx.font = "15px Courier New"; // Monospace font for links
ctx.textBaseline = "top"; // Makes left top point a start point for rendering text
// Draw the link
function drawLink(x,y,href,title){
var linkTitle = title,
linkX = x,
linkY = y,
linkWidth = ctx.measureText(linkTitle).width,
linkHeight = parseInt(ctx.font); // Get lineheight out of fontsize
// Draw the link
ctx.fillText(linkTitle, linkX, linkY);
// Underline the link (you can delete this block)
ctx.beginPath();
ctx.moveTo(linkX, linkY + linkHeight);
ctx.lineTo(linkX + linkWidth, linkY + linkHeight);
ctx.lineWidth = 1;
ctx.strokeStyle = "#0000ff";
ctx.stroke();
// Add mouse listeners
canvas.addEventListener("mousemove", on_mousemove, false);
canvas.addEventListener("click", on_click, false);
// Add link params to array
Links.push(x + ";" + y + ";" + linkWidth + ";" + linkHeight + ";" + href);
}
// Link hover
function on_mousemove (ev) {
var x, y;
// Get the mouse position relative to the canvas element
if (ev.layerX || ev.layerX == 0) { // For Firefox
x = ev.layerX;
y = ev.layerY;
}
// Link hover
for (var i = Links.length - 1; i >= 0; i--) {
var params = new Array();
// Get link params back from array
params = Links[i].split(";");
var linkX = parseInt(params[0]),
linkY = parseInt(params[1]),
linkWidth = parseInt(params[2]),
linkHeight = parseInt(params[3]),
linkHref = params[4];
// Check if cursor is in the link area
if (x >= linkX && x <= (linkX + linkWidth) && y >= linkY && y <= (linkY + linkHeight)){
document.body.style.cursor = "pointer";
hoverLink = linkHref;
break;
}
else {
document.body.style.cursor = "";
hoverLink = "";
}
};
}
// Link click
function on_click(e) {
if (hoverLink){
window.open(hoverLink); // Use this to open in new tab
//window.location = hoverLink; // Use this to open in current window
}
}
// Ready for use ! You are welcome !
drawLink(95,93,"http://www.facebook.com/","Me at facebook");
drawLink(95,110,"http://plus.google.com/","Me at G+");
}
</script>
</head>
<body onload="OnLoad();">
<canvas id="myCanvas" width="450" height="250" style="border:1px solid #eee;">
Canvas is not supported in your browser ! :(
</canvas>
</body>
</html>
There is nothing built in to do it, but you can emulate the function of links if you wanted to. You can remember where the text is, color it differently, give it a different cursor when the user mouses-over that area, and redirect the user to another page when he or she clicks on it.
I think another easy idea is to put a div at the position where you want the link to appear on the canvas and put your link at the div. All you will have to do is to position and style the div correctly.
"I think another easy idea is to put a div at the position where you want the link to appear on the canvas and put your link at the div. All you will have to do is to position and style the div correctly." -Shamaila Tahir
I personally like the idea of using links on top of the canvas and here is a full page sized canvas example. You could use this example for many things, and not just the canvas, so why not get comfortable with it. `
<!DOCTYPE html>
<HEAD>
<style type="text/css">
html { height: 100%; width: 100%; overflow: hidden; }
body {
position: absolute;
height: 100%;
width: 100%;
overflow:hidden;
}
#contactBackground{
position: absolute;
height:100%;
width: 100%;
border: 2px solid green;
}
#contactBackground:hover{
border: 2px solid red;}
#contact{
position: absolute;
height:15%;
top: 52%;
left:70%;
width: 10%;
background-size:20%,20%;
}
#onOff{
position: absolute;
height:15%;
top: 52%;
left:20%;
width: 10%;
background-size:20%,20%;
}
#onOff:hover{border: 2px solid red;}
</style><TITLE>Kewl!! Buttons and Links with Canvas</TITLE></HEAD>
<script type="text/javascript">
window.addEventListener('load', canvas, false);
function canvas(){
var link="contact";
var canvas = document.getElementById("canvas");
var context = canvas.getContext('2d');
canvas.width = document.body.clientWidth;
canvas.height = document.body.clientHeight;
contact = document.getElementById("contact");
onOff = document.getElementById("onOff");
document.getElementById("onOff").style.visibility="visible";
switchLinks(link);
function switchLinks(isLink){
if(isLink!="contact"){
document.getElementById("contact").style.visibility="hidden";
}
if(isLink=="contact"){
document.getElementById("contact").style.visibility="visible";
}
}
onOff.addEventListener("mousedown",contactFunction, false);
function contactFunction(){
if(link=="contact"){link="";}else{link="contact";}
switchLinks(link);
}
}
</script><body>
<canvas id="canvas" width="0" height="0">Your browser does not support the HTML 5 Canvas.
</canvas>
<span id="contact" style="display:hidden">
<img id="contactBackground" src="https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcQP5qi1TPhjAPOfbogNgppFdc4r1LoNmr5D1n-NBfr7ll3x9VlY9w" alt="Send a message" title="Email" />
</span>
<img id="onOff" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRXvh9Fej5ZhBQstjlSpQbRLx46h47KS2IO_WIfoyyrHk_essLU" style="display:hidden" />
</body></HTML>``
A simpler solution can be implemented by using a mousedown event listener. First create two arrays for the x and y coordinates of your links on the canvas. Then test if a click was within a range of a link on a mouseup. It it was, use a window.open('http://myurl.com') method to open the link.
var links = ['Google','Yahoo','Bing','Baidu','DuckDuckGo'];
var coordx = [425,332,251,306,458];
var coordy = [267,402,335,304,438];
myCanvas.mousedown(function(e){
lastEvent = e;
mouseDown = true;
}).mouseup(function(){
if((lastEvent.offsetX) > (coordx[0] - 5) &&
(lastEvent.offsetX) <= (coordx[0] + 5) &&
(lastEvent.offsetY) > (coordy[0] - 5) &&
(lastEvent.offsetY) < (coordy[0] + 5)){
// use a console.log('x = "+lastEvent.offsetX) first to find the coordinates and ranges for the links.
// link to 1st url in myArray
window.open('http://myFirstURL.com');
} `
});
You will need tests for each set of coordinates, or you can specify a variable for a current active link.
This is my first stackoverflow post. Thanks to all you guys who have helped me over the years.

moving an image across a html canvas

I am trying to move an image from the right to the center and I am not sure if this is the best way.
var imgTag = null;
var x = 0;
var y = 0;
var id;
function doCanvas()
{
var canvas = document.getElementById('icanvas');
var ctx = canvas.getContext("2d");
var imgBkg = document.getElementById('imgBkg');
imgTag = document.getElementById('imgTag');
ctx.drawImage(imgBkg, 0, 0);
x = canvas.width;
y = 40;
id = setInterval(moveImg, 0.25);
}
function moveImg()
{
if(x <= 250)
clearInterval(id);
var canvas = document.getElementById('icanvas');
var ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
var imgBkg = document.getElementById('imgBkg');
ctx.drawImage(imgBkg, 0, 0);
ctx.drawImage(imgTag, x, y);
x = x - 1;
}
Any advice?
This question is 5 years old, but since we now have requestAnimationFrame() method, here's an approach for that using vanilla JavaScript:
var imgTag = new Image(),
canvas = document.getElementById('icanvas'),
ctx = canvas.getContext("2d"),
x = canvas.width,
y = 0;
imgTag.onload = animate;
imgTag.src = "http://i.stack.imgur.com/Rk0DW.png"; // load image
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height); // clear canvas
ctx.drawImage(imgTag, x, y); // draw image at current position
x -= 4;
if (x > 250) requestAnimationFrame(animate) // loop
}
<canvas id="icanvas" width=640 height=180></canvas>
drawImage() enables to define which part of the source image to draw on target canvas. I would suggest for each moveImg() calculate the previous image position, overwrite the previous image with that part of imgBkg, then draw the new image. Supposedly this will save some computing power.
Here's my answer.
var canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
var myImg = new Image();
var myImgPos = {
x: 250,
y: 125,
width: 50,
height: 25
}
function draw() {
myImg.onload = function() {
ctx.drawImage(myImg, myImgPos.x, myImgPos.y, myImgPos.width, myImgPos.height);
}
myImg.src = "https://mario.wiki.gallery/images/thumb/c/cc/NSMBUD_Mariojump.png/1200px-NSMBUD_Mariojump.png";
}
function moveMyImg() {
ctx.clearRect(myImgPos.x, myImgPos.y, myImgPos.x + myImgPos.width, myImgPos.y +
myImgPos.height);
myImgPos.x -= 5;
}
setInterval(draw, 50);
setInterval(moveMyImg, 50);
<canvas id="canvas" class="canvas" width="250" height="150"></canvas>
For lag free animations,i generally use kinetic.js.
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var hexagon = new Kinetic.RegularPolygon({
x: stage.width()/2,
y: stage.height()/2,
sides: 6,
radius: 70,
fill: 'red',
stroke: 'black',
strokeWidth: 4
});
layer.add(hexagon);
stage.add(layer);
var amplitude = 150;
var period = 2000;
// in ms
var centerX = stage.width()/2;
var anim = new Kinetic.Animation(function(frame) {
hexagon.setX(amplitude * Math.sin(frame.time * 2 * Math.PI / period) + centerX);
}, layer);
anim.start();
Here's the example,if you wanna take a look.
http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-animate-position-tutorial/
Why i suggest this is because,setInterval or setTimeout a particular function causes issues when large amount of simultaneous animations take place,but kinetic.Animation deals with framerates more intelligently.
Explaining window.requestAnimationFrame() with an example
In the following snippet I'm using an image for the piece that is going to be animated.
I'll be honest... window.requestAnimationFrame() wasn't easy for me to understand, that is why I coded it as clear and intuitive as possible. So that you may struggle less than I did to get my head around it.
const
canvas = document.getElementById('root'),
btn = document.getElementById('btn'),
ctx = canvas.getContext('2d'),
brickImage = new Image(),
piece = {image: brickImage, x:400, y:70, width:70};
brickImage.src = "https://i.stack.imgur.com/YreH6.png";
// When btn is clicked execute start()
btn.addEventListener('click', start)
function start(){
btn.value = 'animation started'
// Start gameLoop()
brickImage.onload = window.requestAnimationFrame(gameLoop)
}
function gameLoop(){
// Clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height)
// Draw at coordinates x and y
ctx.drawImage(piece.image, piece.x, piece.y)
let pieceLeftSidePos = piece.x;
let middlePos = canvas.width/2 - piece.width/2;
// Brick stops when it gets to the middle of the canvas
if(pieceLeftSidePos > middlePos) piece.x -= 2;
window.requestAnimationFrame(gameLoop) // Needed to keep looping
}
<input id="btn" type="button" value="start" />
<p>
<canvas id="root" width="400" style="border:1px solid grey">
A key point
Inside the start() function we have:
brickImage.onload = window.requestAnimationFrame(gameLoop);
This could also be written like: window.requestAnimationFrame(gameLoop);
and it would probably work, but I'm adding the brickImage.onload to make sure that the image has loaded first. If not it could cause some issues.
Note: window.requestAnimationFrame() usually loops at 60 times per second.