Change image source created by context.drawimage - javascript

This code allow me to draw cross, with its (x,y) coordinates, one by one with 5 seconds of interval , it works fine :
<script src="http://alertifyjs.com/build/alertify.js"></script>
<link rel="stylesheet" href="http://alertifyjs.com/build/css/alertify.css" />
<link rel="stylesheet" href="http://alertifyjs.com/build/css/themes/default.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<div style="width : 75%;margin : auto;">
<canvas id="Canvas" width="954" height="267"></canvas>
<button class="play">Play</button>
<button class="pause">Pause</button>
</div>
<script>
var canvas = document.getElementById('Canvas');
var context = canvas.getContext("2d");
// Map sprite
var mapSprite = new Image();
mapSprite.src = "v1.png";
var array_x = [351,315,353,352,318,485,351,748,568,645,373,350,572,374,650,240,240,320,707,235,402,539,256,410,433,405,353,745,404,320,514,322,692,474,293,418,418,690,237,513,378,478,433,405,285,429,458,622,568,536,564,389,641,534,567,454,575,482,459,539,431,327,464,374,348,520,279,378,509,516,232,744,351,710,481,540,429,642,537,459,513,689,324,463,375,747,431,265,484,591,458,460,485,407,720,483,376,520,691,376,232,413,536,430,653,714,484,715,629,573,263,408,436,300,544,407,432,568,536,462,485,346,610,524];
var array_y = [18,18,181,228,60,232,34,32,26,37,65,62,228,180,91,83,83,81,88,62,35,65,52,155,23,90,94,95,230,232,15,105,37,68,47,186,186,93,14,65,22,10,230,68,18,91,226,22,150,227,89,43,76,92,62,12,187,96,78,33,35,180,151,230,151,154,95,96,31,233,39,77,79,20,30,165,65,51,18,62,96,19,150,33,79,19,35,23,210,20,180,95,184,19,76,64,36,186,73,151,26,192,153,156,24,36,165,97,85,78,77,101,184,22,177,212,210,166,79,210,150,168,45,18];
var isPaused = false;
var firstLoad = function () {
context.font = "15px Georgia";
context.textAlign = "center";
}
firstLoad();
var main = function () {
draw();
};
var draw = function () {
// Clear Canvas
context.fillStyle = "#000";
context.fillRect(0, 0, canvas.width, canvas.height);
// Draw map
context.drawImage(mapSprite, 0, 0, 954, 267);
//draw red cross
cross = new Image();
cross.src = "cross.png";
// draw blue cross
cross1 = new Image();
cross1.src = "cross-blue.png";
var t = window.setInterval(function() { if(!isPaused) { event_coor(); } }, 5000);
i=0;
function event_coor() {
if (i < array_x.length) {
context.drawImage(cross, array_x[i], array_y[i], 10, 10);
i=i+1;
}
}
}
mapSprite.addEventListener('load', main);
//with jquery
$('.pause').on('click', function(e) {
e.preventDefault();
isPaused = true;
});
$('.play').on('click', function(e) {
e.preventDefault();
isPaused = false;
});
</script>
What I want to do is to change the color of the image cross that will be displayed under mapSprite, let's say displaying it in red cross.png and after displaying the second one, the oldest will turn to blue cross-blue.png at the same time. As that I will always have the last one in red to catch the attention.
How to change le last image source context.drawimage after few seconds?
Thanks a lot.
EDIT 1 : Redraw above the last one after 2seconds
<script src="http://alertifyjs.com/build/alertify.js"></script>
<link rel="stylesheet" href="http://alertifyjs.com/build/css/alertify.css" />
<link rel="stylesheet" href="http://alertifyjs.com/build/css/themes/default.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<div style="width : 75%;margin : auto;">
<canvas id="Canvas" width="954" height="267"></canvas>
<button class="play">Play</button>
<button class="pause">Pause</button>
</div>
<script>
var canvas = document.getElementById('Canvas');
var context = canvas.getContext("2d");
// Map sprite
var mapSprite = new Image();
mapSprite.src = "v1.png";
var array_x = [351,315,353,352,318,485,351,748,568,645,373,350,572,374,650,240,240,320,707,235,402,539,256,410,433,405,353,745,404,320,514,322,692,474,293,418,418,690,237,513,378,478,433,405,285,429,458,622,568,536,564,389,641,534,567,454,575,482,459,539,431,327,464,374,348,520,279,378,509,516,232,744,351,710,481,540,429,642,537,459,513,689,324,463,375,747,431,265,484,591,458,460,485,407,720,483,376,520,691,376,232,413,536,430,653,714,484,715,629,573,263,408,436,300,544,407,432,568,536,462,485,346,610,524];
var array_y = [18,18,181,228,60,232,34,32,26,37,65,62,228,180,91,83,83,81,88,62,35,65,52,155,23,90,94,95,230,232,15,105,37,68,47,186,186,93,14,65,22,10,230,68,18,91,226,22,150,227,89,43,76,92,62,12,187,96,78,33,35,180,151,230,151,154,95,96,31,233,39,77,79,20,30,165,65,51,18,62,96,19,150,33,79,19,35,23,210,20,180,95,184,19,76,64,36,186,73,151,26,192,153,156,24,36,165,97,85,78,77,101,184,22,177,212,210,166,79,210,150,168,45,18];
var isPaused = false;
var firstLoad = function () {
context.font = "15px Georgia";
context.textAlign = "center";
}
firstLoad();
var main = function () {
draw();
};
var draw = function () {
// Clear Canvas
context.fillStyle = "#000";
context.fillRect(0, 0, canvas.width, canvas.height);
// Draw map
context.drawImage(mapSprite, 0, 0, 954, 267);
//draw red cross
cross = new Image();
cross.src = "cross.png";
// draw blue cross
cross1 = new Image();
cross1.src = "cross-blue.png";
var t = window.setInterval(function() { if(!isPaused) { event_coor(); } }, 5000);
i=0;
function event_coor() {
if (i < array_x.length) {
context.drawImage(cross, array_x[i], array_y[i], 10, 10);
window.setInterval (function () { context.drawImage(cross1, array_x[i], array_y[i], 10, 10);}, 2000);
i=i+1;
}
}
}
mapSprite.addEventListener('load', main);
//with jquery
$('.pause').on('click', function(e) {
e.preventDefault();
isPaused = true;
});
$('.play').on('click', function(e) {
e.preventDefault();
isPaused = false;
});
</script>

You have to redraw the whole scene, or if the cross is not overlapped by other elements / has solid color, just the cross.
There is no way to change the src of already rendered element, since there is no history (scene graph) of what has been drawn on canvas previously.

Related

Repeating image in a canvas with responsive height

I'm trying to create a canvas where I have an image as a background that repeats horizontally and adapts the height automatically.
I've managed to repeat the background image following the x-axis but I'm unable to make the height responsive.
This is my code so far:
const cvs = document.getElementById("canvas");
const ctx = cvs.getContext("2d");
const bg = new Image();
bg.src = "http://lorempixel.com/100/100";
const draw = () => {
const ptrn = ctx.createPattern(bg, "repeat-x");
ctx.fillStyle = ptrn;
ctx.fillRect(0, 0, canvas.width, canvas.height);
requestAnimationFrame(draw);
};
draw();
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</head>
<body>
<canvas id="canvas" width="1000" height="200"></canvas>
<script src="index.js"></script>
</body>
</html>
TLDR: I would like to be able to have an image within my canvas that repeats horizontally and its height is responsive.
Thanks in advance.
Hopefully the explanation in the comments answers your question. Feel free to ask for clarification.
const cvs = document.getElementById("canvas");
const ctx = cvs.getContext("2d");
// First stretch the canvas so we can get
// the full size of teh browser window
cvs.style.height = '100vh';
cvs.style.width = '100vw';
// Now adjust actual canvas size to match
const {width, height} = cvs.getBoundingClientRect();
cvs.height = height;
cvs.width = width;
const bg = new Image();
// Should always wait for onload
// before drawing to prevent race condition.
bg.onload = ()=>{
var x=0;
while(x < cvs.width){
ctx.drawImage(bg, x, 0, 100, cvs.height);
x += bg.width;
}
// draw the image a bunch of times
// var x=0, y=0;
// while(x < cvs.width && y < cvs.height){
// ctx.drawImage(bg, x, y);
// x += bg.width;
// if(x > cvs.width){
// x = 0;
// y += bg.height;
// }
// }
};
bg.src = "http://lorempixel.com/100/100";
<canvas id="canvas"></canvas>
<script src="index.js"></script>
If I got it right you want to fill the height and repeat horizontally, is that correct?
const cvs = document.getElementById("canvas");
const ctx = cvs.getContext("2d");
var bg = new Image();
bg.src = "http://lorempixel.com/100/100";
var tempCanvas = document.createElement("canvas"),
tCtx = tempCanvas.getContext("2d");
var imgWidth = 200;
var imgHeight = 200;
const draw = () => {
tempCanvas.width = imgWidth;
tempCanvas.height = imgHeight;
tCtx.drawImage(bg, 0, 0, 100, 100, 0, 0, imgWidth, imgHeight);
const ptrn = ctx.createPattern(tempCanvas , "repeat-x");
ctx.fillStyle = ptrn;
ctx.fillRect(0, 0, canvas.width, canvas.height);
requestAnimationFrame(draw);
};
bg.onload = () => {
draw();
}
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</head>
<body>
<canvas id="canvas" width="1000" height="200"></canvas>
<script src="index.js"></script>
</body>
</html>
try setting up the image size to match the canvas size just like that:
bg.src = "http://lorempixel.com/200/200";
Cheers! :)

Create smooth animation in canvas

I have a canvas object which is rendering an image. When the user click on button the image will move to right. My problem is this movement is not smooth. The image is simply jumping to the specified position. How can I make this movement smooth? This is the codepen example Can anyone please help me?
$(window).on('load', function () {
myCanvas();
});
function myCanvas() {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var x = 0;
function fly() {
ctx.clearRect(0, 0, c.width, c.height);
ctx.closePath();
ctx.beginPath();
var img = new Image();
img.onload = function () {
ctx.drawImage(img, x, 0);
};
img.src = 'http://via.placeholder.com/200x200?text=first';
}
fly();
$('#movebutton').click(function () {
for (i = 0; i < 200; i++) {
x = i;
requestAnimationFrame(fly);
}
});
}
<canvas id="myCanvas" width="960" height="600"></canvas>
<button id="movebutton">Move</button>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
First of all, why are you loading your image in your frame rendering function - if cache is disabled, it will request an image every frame!
I rewrote the script so that the animation is linear and smooth, you can edit the speed variable to adjust the movement speed.
$(window).on('load', function () {
var img = new Image();
img.onload = function () {
myCanvas(img);
};
img.src = 'http://via.placeholder.com/200x200?text=first';
});
function myCanvas(img) {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var x = 0;
var last_ts = -1
var speed = 0.1
function renderScene() {
ctx.clearRect(0, 0, c.width, c.height);
ctx.closePath();
ctx.beginPath();
ctx.drawImage(img, x, 0);
}
function fly(ts) {
if(last_ts > 0) {
x += speed*(ts - last_ts)
}
last_ts = ts
if(x < 200) {
renderScene()
requestAnimationFrame(fly);
}
}
renderScene()
$('#movebutton').click(function () {
x = 0;
requestAnimationFrame(fly);
});
}

Auto refresh html canvas image not working

For my website, I need to redraw an image from server which is continuously updating. I found the solution and tried but it still does not auto refresh. I also tried adding a dummy string to my image(local0.jpg) so that the browser does not use cached image but no success. What am I doing wrong?
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<canvas id="canvas" width="400" height="400"> </canvas>
<script>
var imageObj=new Image();
imageObj.src="local0.jpg?dummy=8484744"
imageObj.onload=function()
{
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
ctx.drawImage(imageObj,0, 0,canvas.width,canvas.height);
setTimeout(timedRefresh,1000);
}
function timedRefresh()
{
imageObj.src = "local0.jpg?dummy=8484749"
}
</script>
</body>
</html>
Try the following code
var imageObj = new Image();
imageObj.onload = function() {
drawOnCanvas();
setTimeout(timedRefresh, 1000);
}
// set src AFTER assigning load
imageObj.src = "local0.jpg?dummy=" + Math.random();
function timedRefresh() {
imageObj.src = "local0.jpg?dummy=" + Math.random();
//drawOnCanvas(); //flicker was due this line as it try to draw image load so i commented it... now it should work...
}
function drawOnCanvas() {
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(imageObj, 0, 0, canvas.width, canvas.height);
}
your function timedRefresh add random values to image
function timedRefresh()
{
imageObj.src = "local0.jpg?dummy=" + Math.floor((Math.random() * 10000) + 1);
}

how to get mouseover to draw on html canvas with event listener with my code? https://jsfiddle.net/dannixx/d0p0j8cL/

how to get mouseover to draw on html canvas with event listener with my code? https://jsfiddle.net/dannixx/d0p0j8cL/
jifiddle file, i want to be able to draw line on canvas with mouseover https://jsfiddle.net/dannixx/d0p0j8cL/
<!DOCTYPE html>
<html>
<head>
<title>Canvas</title>
<style type="text/css">
#Canvas1 {
border: : dotted 3px black;
background-color: blue;
}
</style>
<script>
window.onload = function(){
var theCanvas = document.getElementById("Canvas1");
if (theCanvas && document.getContext("2d")){
var ctx = theCanvas.getContext("2d";)
if(ctx){
ctx.fillStyle = "lightblue";
ctx.fillRect(0,0 ctx.canvas.width, ctx.canvas.height)
}
}
}
</script>
</head>
<body>
<h1>cnavas</h1>
<p>ex</p>
<canvas id="Canvas1" width="400", height="300"></canvas>
<p id="demo"></p>
</body>
</html>
Here is a really simple example using a onmousemove listener that updates the new mouse coordinates and draws a line from the previous coordinates to the new coordinates. Run it and see!
var x = null;
var y = null;
var c = null;
var ctx = null;
function getPos(e) {
//if it is the first time the event listener is called then set x and y to the new mouse coordinate
if(x == null) {
x=e.clientX;
y=e.clientY;
}
//otherwise draw from the previous point (x, y) to the new coordinates (e.clientX, e.clientY).
ctx.beginPath();
ctx.moveTo(x,y);
ctx.lineTo(e.clientX,e.clientY);
ctx.stroke();
x=e.clientX;
y=e.clientY;
}
window.onload = function(){
c=document.getElementById("Canvas1");
ctx=c.getContext("2d");
}
<canvas onmousemove="getPos(event)" id="Canvas1" width="400", height="300"></canvas>
Here is a simple example script (using the stroke method) for drawing on a canvas:
HTML :
<canvas id="can1"></canvas>
CSS :
#can1 {
border:dashed 3px #000;
}
JavaScript :
var can = document.getElementById("can1");
var canCtx = can.getContext("2d");
var sx = 0, sy = 0;
var clicked = false;
function _left(e){
return e.pageX - can.offsetLeft;
}
function _top(e){
return e.pageY - can.offsetTop;
}
function _draw(e, sx, sy){
var x = _left(e);
var y = _top(e);
canCtx.moveTo(sx, sy);
canCtx.lineTo(x, y);
canCtx.strokeStyle="red";
canCtx.stroke();
}
can.addEventListener("mousedown", function(e){
sx = _left(e);
sy = _top(e);
_draw(e, sx, sy);
clicked = true;
}, false);
can.addEventListener("mousemove", function(e){
if(clicked == true){
_draw(e, can);
}
}, false);
addEventListener("mouseup", function(){
clicked = false;
}, false);

How to add multiple images using array in kineticJS?

I am actually trying to implement the functionality where I can add multiple images onto a canvas using array and kineticJs. I am unable to load images onto the canvas however these images are created outside the canvas body. I want to draw these circle images onto the canvas body. Cheers
<html>
<head>
<title>Bomb Game</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src = "https://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.4.3.min.js"></script>
</head>
<body>
<div id = "container"></div>
<script>
window.onload = $(document).ready(function()
{
var bombLeft, bombTop, bombRight, bombBottom;
var timerLeft, timerTop, timerRight, timerBottom;
var numberCircles = [];
function loadImages(sources, callback)
{
var images = {};
var loadedImages = 0;
var numImages = 0;
// get num of sources
for(var src in sources)
{
numImages++;
}
for(var src in sources)
{
images[src] = new Image();
images[src].onload = function()
{
if(++loadedImages >= numImages)
{
callback(images);
}
};
images[src].src = sources[src];
}
}
var newCanvas = document.createElement("canvas");
var ctx = newCanvas.getContext("2d");
newCanvas.width = window.innerWidth;
newCanvas.height = window.innerHeight;
newCanvas.style.border = "10px solid #000000";
newCanvas.style.margin = "0px";
$("#container").append(newCanvas);
var sources = {background: 'bomb_artwork/background.jpg', bomb: 'bomb_artwork/bomb.png', timer: 'bomb_artwork/timer.png',
boxSmall: 'bomb_artwork/box_1.png',boxBig: 'bomb_artwork/box_2.png', numberCircle: 'bomb_artwork/number_circle.png', explode: 'bomb_artwork/explode.png'};
function initStage(images)
{
var stage = new Kinetic.Stage({
container: 'container',
width: newCanvas.width,
height: newCanvas.height
});
var layer = new Kinetic.Layer();
loadImages(sources,function(images){
<!-- For background image -->
ctx.drawImage(images.background,0,0,newCanvas.width,newCanvas.height);
x1 = newCanvas.width/7;
y1 = newCanvas.height/3;
x2 = newCanvas.width/8;
y2 = newCanvas.height/8;
<!-- To add boxes in background>
ctx.drawImage(images.boxBig,750,370,150,120);
ctx.drawImage(images.boxBig,754,270,150,120);
ctx.drawImage(images.boxSmall,788,210,120,80);
<!-- For bombbottom -->
bombBottom = images.bomb;
timerBottom = images.timer;
ctx.drawImage(bombBottom,newCanvas.width/2-newCanvas.width/8,newCanvas.height-150,x1,y1);
ctx.drawImage(timerBottom,newCanvas.width/2+newCanvas.width/10000,newCanvas.height-50,x2,y2);
ctx.font = "28pt Times New Roman";
ctx.fillStyle = "yellow";
ctx.fillText("Player 1", 720, 635);
ctx.font = "20pt Times New Roman";
ctx.fillStyle = "yellow";
ctx.fillText("? - 6 = 11", 730, 670);
<!-- For bombleft-->
bombLeft = images.bomb;
timerLeft = images.timer;
ctx.save();
ctx.rotate(Math.PI / 2);
ctx.drawImage(bombLeft,230,-newCanvas.height/4,x1,y1);
ctx.drawImage(timerLeft,400,-newCanvas.height/13,x2,y2);
ctx.restore();
<!-- For bombtop-->
bombTop = images.bomb;
timerTop = images.timer;
ctx.save();
ctx.translate(100, 100);
ctx.rotate(Math.PI);
ctx.drawImage(bombTop,-650,-50,x1,y1);
ctx.drawImage(timerTop,-480,50,x2,y2);
ctx.restore();
<!-- For bombright-->
bombRight = images.bomb;
timerRight = images.timer;
ctx.save();
ctx.translate(100, 100);
ctx.rotate(-Math.PI/2);
ctx.drawImage(bombRight,-325,1100,x1,y1);
ctx.drawImage(timerRight,-150,1215,x2,y2);
ctx.restore();
<!-- TO draw random circles -->
for(var i = 0; i < 30;i++)
{
numberCircles[i] = new Kinetic.Image({
image : images.numberCircle,
x : Math.floor(Math.random()* newCanvas.width),
y : Math.floor(Math.random()*newCanvas.height),
width : 50,
height : 50,
draggable : true,
stroke : 'red',
strokeWidth : 10,
strokeEnabled : false
/*if((x > newCanvas.width/8 && x < newCanvas.width-newCanvas.width/6)&&(y > newCanvas.height/4 && y < newCanvas.height-newCanvas.height/3))
{
ctx.drawImage(numberCircles[i],x,y,50,50);
}
else
{
i = i-1;
continue;
}*/
});
layer.add(numberCircles[i]);
stage.add(layer);
}
// use event delegation to update pointer style
// and apply borders
layer.on('mouseover', function(evt) {
//var shape = evt.shape;
document.body.style.cursor = 'pointer';
//shape.enableStroke();
layer.draw();
});
layer.on('mouseout', function(evt) {
//var shape = evt.shape;
document.body.style.cursor = 'default';
//shape.disableStroke();
layer.draw();
});
});
}
loadImages(sources,initStage);
});
</script>
</body>
</html>

Categories