Scroll Image in canvas from top to bottom - javascript

How can I scroll Image from top to bottom position. Currently, it is moving from left to right and also tried interchanging the "xpos" and "y" value but the Image is getting distorted .Any help would be appreciated.
(function() {
window.requestAnimationFrame = window.requestAnimationFrame
|| window.webkitRequestAnimationFrame
|| window.mozRequestAnimationFrame
|| function(callback) { window.setTimeout(callback, 1000 / 60); };
var canvas = document.getElementById('bg');
var context = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var looping = false;
var totalSeconds = 0;
var img = new Image();
img.onload = imageLoaded;
img.src = 'https://preview.ibb.co/dpQ6Ak/test.jpg';
function imageLoaded() {
draw(0);
startStop();
}
var lastFrameTime = 0;
function startStop() {
looping = !looping;
if (looping) {
lastFrameTime = Date.now();
requestAnimationFrame(loop);
}
}
function loop() {
if (!looping) {
return;
}
requestAnimationFrame(loop);
var now = Date.now();
var deltaSeconds = (now - lastFrameTime) / 1000;
lastFrameTime = now;
draw(deltaSeconds);
}
function draw(delta) {
totalSeconds += delta;
var vx = 100; // the background scrolls with a speed of 100 pixels/sec
var numImages = Math.ceil(canvas.width / img.width) + 1;
var xpos = totalSeconds * vx % img.width;
context.save();
context.translate(-xpos, 0);
for (var i = 0; i < numImages; i++) {
context.drawImage(img, i * img.width, 0);
}
context.restore();
}
}());
<canvas id="bg" ></canvas>

I guess this is your answer
(function() {
window.requestAnimationFrame = window.requestAnimationFrame
|| window.webkitRequestAnimationFrame
|| window.mozRequestAnimationFrame
|| function(callback) { window.setTimeout(callback, 1000 / 60); };
var canvas = document.getElementById('bg');
var context = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var looping = false;
var totalSeconds = 0;
var img = new Image();
img.onload = imageLoaded;
img.src = 'https://preview.ibb.co/dpQ6Ak/test.jpg';
function imageLoaded() {
draw(0);
startStop();
}
var lastFrameTime = 0;
function startStop() {
looping = !looping;
if (looping) {
lastFrameTime = Date.now();
requestAnimationFrame(loop);
}
}
function loop() {
if (!looping) {
return;
}
requestAnimationFrame(loop);
var now = Date.now();
var deltaSeconds = (now - lastFrameTime) / 1000;
lastFrameTime = now;
draw(deltaSeconds);
}
function draw(delta) {
totalSeconds += delta;
var vx = 100; // the background scrolls with a speed of 100 pixels/sec
var numImages = Math.ceil(canvas.height / img.height) + 1;
var xpos = totalSeconds * vx % img.height;
context.save();
context.translate( 0,xpos);
for (var i = 0; i < numImages; i++) {
context.drawImage(img, 0,-(i * img.height));
}
context.restore();
}
}());
<canvas id="bg" ></canvas>

Drawing an image moving in any direction
var imageScroll = scrollImage("myCan",1.57,60);
setTimeout(randomScroll,10000);
function randomScroll(){
imageScroll.setSpeed( Math.random() * 60 + 20)
.setDirection( Math.random() * Math.PI * 2);
setTimeout(randomScroll,1000 + 2000 * Math.random());
}
function scrollImage(canvasId, direction, speed, URL){
var w, h, iW, iH; // alias for width and height, an image W H
var x, y; // current image pos;
var lastTime; // to track frame time
var stop = false; // when true stop
const rAF = requestAnimationFrame; // Alias
const canvas = document.getElementById(canvasId);
if (canvas === null) { throw new ReferenceError("Can not find canvas with id : '" + canvasId + "'") }
const ctx = canvas.getContext('2d');
const img = new Image;
w = canvas.width = innerWidth;
h = canvas.height = innerHeight;
x = y = lastTime = 0;
lastTime = 0;
img.src = URL ? URL : 'https://preview.ibb.co/dpQ6Ak/test.jpg';
img.onload = () => {
iW = img.width;
iH = img.height;
loop(0)
}
function loop(time) {
var fTime = (time - lastTime) / 1000; // get frame time
lastTime = time;
x += Math.cos(direction) * speed * fTime ; // update position
y += Math.sin(direction) * speed * fTime ;
drawImageRep(x, y); // draw image at x,y
if (!stop){ requestAnimationFrame(loop) }
}
function drawImageRep(x,y){
x = ((x % iW) + iW) % iW;
y = ((y % iH) + iH) % iH;
for(var iy = y - iH; iy < h; iy += iH){
for(var ix = x - iW; ix < w; ix += iW){
ctx.drawImage(img, ix, iy);
}
}
}
return {
stop(){stop = true; return this },
setSpeed(nSpeed){ speed = nSpeed; return this },
setDirection(nDirection) { direction = nDirection; return this },
}
}
<canvas id="myCan"></canvas>

Related

Why won't the image load

What is wrong with the code, I can't find the problem. I think it's because of the drawFrame and loadImage function, but I don't know. So is there a way to make the image load and you will still be able to move it around and shoot?
And when I try to remove the drawFrame function nothing would work. And if posiible is there a way to change the bullet from squares to circles?
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta charset="UTF-8">
<style>
html,
body {
width: 100%;
height: 100%;
margin: 0;
}
canvas {
cursor: crosshair;
background-color: cornflowerblue;
}
</style>
</head>
<body>
<canvas id="Trump"></canvas>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
(async function main() {
var canvas = document.getElementById('Trump');
if (!canvas.getContext) return;
var ctx = canvas.getContext('2d');
ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;
//const fps = 60;
const ronaNum = 30; // number of particles at start
const ronaSize = 70; // corona size
const ronaSpeed = 100; // speed
let chinabmg;
function draw() {
$("canvas").one("click", function () {
chinabmg = new sound("stankytrumpchina.mp3");
chinabmg.play();
});
//mutes when clicked on m
document.body.onkeyup = function (e) {
if (e.keyCode == 77) { chinabmg.stop() }
};
//compatability
var requestAnimationFrame = window.requestAnimationFrame || //Chromium
window.webkitRequestAnimationFrame || //Webkit
window.mozRequestAnimationFrame || //Mozilla Geko
window.oRequestAnimationFrame || //Opera Presto
window.msRequestAnimationFrame || //IE Trident?
function (callback) { //Fallback function
window.setTimeout(callback, 1000 / 60);
};
var DrawX = 0;
var DrawY = 0;
var time = 0;
var width = canvas.width;
var height = canvas.height;
var offTop = canvas.offsetTop;
var offLeft = canvas.offsetLeft;
var rectWidth = 15;
var rectHeight = 15;
var speed = 1;
var x = width / 2;
var y = height / 2;
var size = 30;
var id = 0;
var bulletId = 0;
function sound(src) {
this.sound = document.createElement("audio");
this.sound.src = src;
this.sound.setAttribute("preload", "auto");
this.sound.setAttribute("controls", "none");
this.sound.setAttribute("loop", "auto");
this.sound.style.display = "none";
document.body.appendChild(this.sound);
this.play = function () {
this.sound.play();
}
this.stop = function () {
this.sound.pause();
}
}
function player(id, color, size, x, y) {
this.id = id;
this.color = color;
this.size = size;
this.x = x;
this.y = y;
this.speed = speed;
}
var playerList = [];
function addPlayer(color, size, x, y) {
playerList[id] = new player(id, color, size, x, y);
id += 1;
}
addPlayer("blue", size, width / 2 - 50, height / 2);
var pressedKeys = [];
function moveLeft(checkId, checkX, checkY, cSize, cSpeed, cKey) {
var x = checkX - cSpeed;
var y = checkY - cSpeed;
var x2 = checkX + cSize + cSpeed;
var y2 = checkY + cSize + cSpeed;
if (x > 0) {
playerList[checkId].x = checkX - cSpeed;
} else {
playerList[checkId].x = 0;
}
}
function moveUp(checkId, checkX, checkY, cSize, cSpeed, cKey) {
var x = checkX - cSpeed;
var y = checkY - cSpeed;
var x2 = checkX + cSize + cSpeed;
var y2 = checkY + cSize + cSpeed;
if (y > 0) {
playerList[checkId].y = checkY - cSpeed;
} else {
playerList[checkId].y = 0;
}
}
function moveRight(checkId, checkX, checkY, cSize, cSpeed, cKey) {
var x = checkX - cSpeed;
var y = checkY - cSpeed;
var x2 = checkX + cSize + cSpeed;
var y2 = checkY + cSize + cSpeed;
if (x2 < width) {
playerList[checkId].x = checkX + cSpeed;
} else {
playerList[checkId].x = width - cSize;
}
}
function moveDown(checkId, checkX, checkY, cSize, cSpeed, cKey) {
var x = checkX - cSpeed;
var y = checkY - cSpeed;
var x2 = checkX + cSize + cSpeed;
var y2 = checkY + cSize + cSpeed;
if (y2 < height) {
playerList[checkId].y = checkY + cSpeed;
} else {
playerList[checkId].y = height - cSize;
}
}
function Move(checkId, checkX, checkY, cSize, cSpeed, cKey) {
if (checkId === 0) {
switch (cKey) {
case 65:
// left
moveLeft(checkId, checkX, checkY, cSize, cSpeed, cKey);
break;
case 87:
// up
moveUp(checkId, checkX, checkY, cSize, cSpeed, cKey);
break;
case 68:
// right
moveRight(checkId, checkX, checkY, cSize, cSpeed, cKey);
break;
case 83:
// down
moveDown(checkId, checkX, checkY, cSize, cSpeed, cKey);
break;
default:
return; // exit this handler for other keys
}
}
}
var validKeys = [];
validKeys[0] = "65,87,68,83-107,109,80";
// == KEYDOWN ==
$(document.body).keydown(function (e) {
e.preventDefault();
//go through all players
$.each(playerList, function (i, currentPlayer) {
if (validKeys[currentPlayer.id].indexOf(e.which) == -1) return true;
if (!pressedKeys[e.which]) {
//set interval for the function
pressedKeys[e.which] = setInterval(function () {
Move(currentPlayer.id, currentPlayer.x, currentPlayer.y, currentPlayer.size, currentPlayer.speed, e.which);
}, 5);
}
});
});
// == KEYUP ==
$(document.body).keyup(function (e) {
if (pressedKeys[e.which]) {
clearInterval(pressedKeys[e.which]);
delete pressedKeys[e.which];
}
});
//=============================== SHOOTING ===============================
//Bullets
function bullet(id, color, size, speed, x, y, eX, eY) {
this.id = id;
this.color = color;
this.size = size;
this.x = x;
this.y = y;
this.eX = eX;
this.eY = eY;
this.velocityX = 1;
this.velocityY = 1;
this.speed = 9;
}
var bulletList = [];
function addBullet(color, bsize, bspeed, x, y, eX, eY) {
bulletList[bulletId] = new bullet(bulletId, color, bsize, 9, x, y, eX, eY);
bulletId += 1;
}
function updateBullet(bullet, player) {
var dx = (bullet.eX - player.x);
var dy = (bullet.eY - player.y);
var mag = Math.sqrt(dx * dx + dy * dy);
bullet.velocityX = (dx / mag) * 9;
bullet.velocityY = (dy / mag) * 9;
bullet.x += bullet.velocityX;
bullet.y += bullet.velocityY;
}
// Add event listener for `click` events.
canvas.onmousedown = function (e) {
addBullet("#696969", 10, 2, playerList[0].x, playerList[0].y, e.x, e.y);
};
//corona part
let corona = [];
createCoronaParticles();
// game loop
//setInterval(update, 1000 / fps);
function createCoronaParticles() {
corona = [];
let cx, cy;
for (var i = 0; i < ronaNum; i++) {
do {
cx = Math.floor(Math.random() * canvas.width);
cy = Math.floor(Math.random() * canvas.height);
} while (noSpawnOnFigure(canvas.height / 2, canvas.width / 2, cy, cx) < ronaSize * 5);
corona.push(newParticle(cx, cy));
}
}
function noSpawnOnFigure(cy1, cx1, cy2, cx2) {
return Math.sqrt(Math.pow(cy2 - cy1, 2) + Math.pow(cx2 - cx1, 2));
}
function newParticle(cx, cy) {
let rona = {
ca: Math.random() * Math.PI * 2, //radians
cr: ronaSize / 2,
cx: cx,
cy: cy,
cxv: Math.random() * ronaSpeed / 60 * (Math.random() < 0.5 ? 1 : -1),
cyv: Math.random() * ronaSpeed / 60 * (Math.random() < 0.5 ? 1 : -1)
};
return rona;
}
// function update() {
// }
// ======= DRAWING =======
function drawFrame() {
requestAnimationFrame(drawFrame);
ctx.font = "15pt Georgia"; // sets the font and font size of the text
ctx.clearRect(0, 0, width, height);
$.each(playerList, function (index, currentPlayer) {
//debug
//draw players
function loadImage(path) {
let image = new Image();
let promise = new Promise((resolve, reject) => {
image.onload = () => resolve(image);
image.onerror = reject
});
image.src = path;
return promise;
}
loadImage.src = 'trump.gif';
});
//draw bullets
$.each(bulletList, function (index, bullet) {
updateBullet(bullet, playerList[0]);
ctx.fillStyle = bullet.color;
ctx.fillRect(bullet.x, bullet.y, bullet.size, bullet.size);
});
// canvas
//ctx.clearRect(0, 0, canvas.width, canvas.height);
// draw corona particles
ctx.strokeStyle = "rgb(150, 0, 0)";
ctx.lineWidth = 20;
let ca, cr, cx, cy;
for (let i = 0; i < corona.length; i++) {
// get properties
ca = corona[i].ca;
cr = corona[i].cr;
cx = corona[i].cx;
cy = corona[i].cy;
// draw path
ctx.beginPath();
ctx.fillStyle = "rgb(200, 0, 0)"
ctx.moveTo(
cx + cr * Math.cos(ca),
cy + cr * Math.sin(ca)
);
// draw circle
for (let j = 1; j < 180; j++) {
ctx.lineTo(
cx + cr * Math.cos(ca + j * Math.PI * 2 / 180),
cy + cr * Math.sin(ca + j * Math.PI * 2 / 180)
);
}
ctx.closePath();
ctx.stroke();
ctx.fill();
// move particles
corona[i].cx += corona[i].cxv;
corona[i].cy += corona[i].cyv;
// particle edge of screen
if (corona[i].cx < 0 - corona[i].cr) {
corona[i].cx = canvas.width + corona[i].cr;
} else if (corona[i].cx > canvas.width + corona[i].cr) {
corona[i].cx = 0 - corona[i].cr
}
if (corona[i].cy < 0 - corona[i].cr) {
corona[i].cy = canvas.height + corona[i].cr;
} else if (corona[i].cy > canvas.height + corona[i].cr) {
corona[i].cy = 0 - corona[i].cr
}
}
}
drawFrame();
}
$(draw);
}
)();
</script>
</body>
</html>
//draw players
function loadImage(path) {
let image = new Image();
let promise = new Promise((resolve, reject) => {
image.onload = () => resolve(image);
image.onerror = reject
});
image.src = path;
//Add the following line
ctx.drawImage(image,playerList[0].x,playerList[0].y);
return promise;
}
// change loadImage.src = 'trump.gif' into this
loadImage('trump.gif');

How can I reverse the direction of this square after it reaches a certain value?

I'm trying to create an idle animation where the red rectangle moves back and forth slightly in a loop. For some reason once it reaches the specified threshhold instead of proceeding to move in the opposite direction, it just stops.
What did I do wrong?
<canvas id="myCanvas" width="1500" height="500" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
<script>
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
// Spaceship structure
var shipWidth = 250;
var shipHeight = 100;
// Canvas parameters
var cWidth = canvas.width;
var cHeight = canvas.height;
// Positioning variables
var centerWidthPosition = (cWidth / 2) - (shipWidth / 2);
var centerHeightPosition = (cHeight / 2) - (shipHeight / 2);
var requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
function drawShip(){
ctx.clearRect(0, 0, cWidth, cHeight);
ctx.fillStyle = "#FF0000";
ctx.fillRect(centerWidthPosition,centerHeightPosition,shipWidth,shipHeight);
centerWidthPosition--;
if (centerWidthPosition < 400){
++centerWidthPosition;
}
requestAnimationFrame(drawShip);
}
drawShip();
</script>
#TheAmberlamps explained why it's doing that. Here I offer you a solution to achieve what I believe you are trying to do.
Use a velocity variable that changes magnitude. X position always increases by velocity value. Velocity changes directions at screen edges.
// use a velocity variable
var xspeed = 1;
// always increase by velocity
centerWidthPosition += xspeed;
// screen edges are 0 and 400 in this example
if (centerWidthPosition > 400 || centerWidthPosition < 0){
xspeed *= -1; // change velocity direction
}
I added another condition in your if that causes the object to bounce back and forth. Remove the selection after || if you don't want it doing that.
Your function is caught in a loop; once centerWidthPosition reaches 399 your conditional makes it increment back up to 400, and then it decrements back to 399.
here is another one as a brain teaser - how would go by making this animation bounce in the loop - basically turn text into particles and then reverse back to text and reverse back to particles and back to text and so on and on and on infinitely:
var random = Math.random;
window.onresize = function () {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
};
window.onresize();
var ctx = canvas.getContext('2d');
ctx.font = 'bold 50px "somefont"';
ctx.textBaseline = 'center';
ctx.fillStyle = 'rgba(255,255,255,1)';
var _particles = [];
var particlesLength = 0;
var currentText = "SOMETEXT";
var createParticle = function createParticle(x, y) {_particles.push(new Particle(x, y));};
var checkAlpha = function checkAlpha(pixels, i) {return pixels[i * 4 + 3] > 0;};
var createParticles = function createParticles() {
var textSize = ctx.measureText(currentText);
ctx.fillText(currentText,Math.round((canvas.width / 2) - (textSize.width / 2)),Math.round(canvas.height / 2));
var imageData = ctx.getImageData(1, 1, canvas.width, canvas.height);
var pixels = imageData.data;
var dataLength = imageData.width * imageData.height;
for (var i = 0; i < dataLength; i++) {
var currentRow = Math.floor(i / imageData.width);
var currentColumn = i - Math.floor(i / imageData.height);
if (currentRow % 2 || currentColumn % 2) continue;
if (checkAlpha(pixels, i)) {
var cy = ~~(i / imageData.width);
var cx = ~~(i - (cy * imageData.width));
createParticle(cx, cy);
}}
particlesLength = _particles.length;
};
var Point = function Point(x, y) {
this.set(x, y);
};
Point.prototype = {
set: function (x, y) {
x = x || 0;
y = y || x || 0;
this._sX = x;
this._sY = y;
this.reset();
},
add: function (point) {
this.x += point.x;
this.y += point.y;
},
multiply: function (point) {
this.x *= point.x;
this.y *= point.y;
},
reset: function () {
this.x = this._sX;
this.y = this._sY;
return this;
},
};
var FRICT = new Point(0.98);//set to 0 if no flying needed
var Particle = function Particle(x, y) {
this.startPos = new Point(x, y);
this.v = new Point();
this.a = new Point();
this.reset();
};
Particle.prototype = {
reset: function () {
this.x = this.startPos.x;
this.y = this.startPos.y;
this.life = Math.round(random() * 300);
this.isActive = true;
this.v.reset();
this.a.reset();
},
tick: function () {
if (!this.isActive) return;
this.physics();
this.checkLife();
this.draw();
return this.isActive;
},
checkLife: function () {
this.life -= 1;
this.isActive = !(this.life < 1);
},
draw: function () {
ctx.fillRect(this.x, this.y, 1, 1);
},
physics: function () {
if (performance.now()<nextTime) return;
this.a.x = (random() - 0.5) * 0.8;
this.a.y = (random() - 0.5) * 0.8;
this.v.add(this.a);
this.v.multiply(FRICT);
this.x += this.v.x;
this.y += this.v.y;
this.x = Math.round(this.x * 10) / 10;
this.y = Math.round(this.y * 10) / 10;
}
};
var nextTime = performance.now()+3000;
createParticles();
function clearCanvas() {
ctx.fillStyle = 'rgba(0,0,0,1)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
(function clearLoop() {
clearCanvas();
requestAnimationFrame(clearLoop);
})();
(function animLoop(time) {
ctx.fillStyle = 'rgba(255,255,255,1)';
var isAlive = true;
for (var i = 0; i < particlesLength; i++) {
if (_particles[i].tick()) isAlive = true;
}
requestAnimationFrame(animLoop);
})();
function resetParticles() {
for (var i = 0; i < particlesLength; i++) {
_particles[i].reset();
}}

Return true when user click a bug

I am making a bug smasher game, and want Boolean value(isOnCircle) to return 'true' when a user clicks the bug. However, it always returns 'false'. Although when I tested it as a circle instead of a bug image (with 'context.arc'), it returned 'true'.
*I also inserted an image into the canvas background.
bug.r=32 is the bug image's correct radius size.
var Bug = (function () {
function Bug() {
}
return Bug;
}());
var jumpInterval;
var interval = 4000;
var bug = new Bug();
var canvas = document.getElementById('canvas');
canvas.width =727
canvas.height = 483;
var context = canvas.getContext('2d');
var background = new Image();
background.src = "images/lawn.jpg";
background.onload = function () {
context.drawImage(background, 0, 0);
}
function handleClick(evt) {
console.log(evt.x + ',' + evt.y);
var x = evt.x - 50;
var y = evt.y - 100;
// (x - center_x)^2 + (y - center_y)^2 < radius^2
var isOnCircle = Math.pow(x - bug.x, 2) + Math.pow(y - bug.y, 2) < Math.pow(bug.r, 2);
console.log(isOnCircle);
if (interval > 500) {
interval -= 300;
} else {
interval = 500;
}
console.log(interval);
}
function jump() {
bug.x = ((Math.random() * 10324897) % 500) + 1;
bug.y = ((Math.random() * 10324897) % 500) + 1;
bug.r = 32;
context.clearRect(0, 0, canvas.width, canvas.height);
var background = new Image();
background.src = "images/lawn.jpg";
background.onload = function () {
context.drawImage(background, 0, 0);
}
console.log(bug.x);
console.log(bug.y);
context.beginPath();
//context.arc(bug.x, bug.y, bug.r, 0, 2 * Math.PI);
var bugImage = new Image();
bugImage.src = "images/bug.PNG";
bugImage.onload = function () {
context.drawImage(bugImage, bug.x, bug.y);
}
context.stroke();
clearInterval(jumpInterval);
jumpInterval = setInterval(jump, interval);
}
jumpInterval = setInterval(jump, interval);
canvas.addEventListener("click", handleClick);

How can I get this GIF from another website?

I'm creating a website and I want a certain gif background that runs automatically on page load, here is the link of the website
http://contact-festival.com/
And I want to use the moving star-background on the artist line up list
I checked my developer tools and the network , but can't seem to find a source
These are not gifs . These are made with canvas tags and javascript coding.
So here is an example below that you can use.
window.onload = function () {
var element = "starfield";
var bgColor = "#030304";
var FPS = 30;
var displacementRate = 5;
var accelerationRate = 10;
var maxSpeed = 100;
var maxStars = 1000;
var speedUp = setInterval(function(){
if (accelerationRate > maxSpeed) {
clearInterval(speedUp);
}
accelerationRate = accelerationRate * 1.1;
},100);
var Star = function() {
this.x = 0;
this.y = 0;
this.z = 0;
this.maxDepth = 0;
this.alpha = 0;
this.radius = 0;
this.dx = 0;
this.dy = 0;
this.dz = 0;
this.ddx = 0;
this.ddy = 0;
this.drawInContext = function(ctx, deltaX, deltaY) {
ctx.beginPath();
ctx.fillStyle = "rgba(255, 255, 255," + this.alpha + ")";
ctx.arc(this.x + deltaX, this.y + deltaY, this.radius, 0, Math.PI * 2, false);
ctx.fill();
};
};
var requestAnimationFrame =
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame ||
function(callback) {
return window.setTimeout(callback, 1000 / FPS);
};
function isCanvasSupported(element) {
return !!(element.getContext && element.getContext("2d"));
}
function backingScale(context) {
if ('devicePixelRatio' in window) {
if (window.devicePixelRatio > 1) {
return window.devicePixelRatio;
}
}
return 1;
}
function StarField(canvasID) {
this.canvas = document.getElementById(canvasID);
if (!isCanvasSupported(this.canvas)) {
this.canvas.className = "inactive";
this.canvas.width = window.innerWidth;
this.isCanvasEnabled = false;
return this;
}
this.isCanvasEnabled = true;
this.ctx = this.canvas.getContext("2d");
this.scaleFactor = backingScale(this.ctx);
this.stars = new Array();
function newStar() {
var star = new Star();
star.x = Math.random() * this.canvas.width - this.originX;
star.y = Math.random() * this.canvas.height - this.originY;
star.z = star.max_depth = Math.max(this.canvas.width, this.canvas.height);
star.alpha = Math.random();
star.radius = Math.random();
var xcoeff = star.x > 0 ? 1 : -1;
var ycoeff = star.y > 0 ? 1 : -1;
if (Math.abs(star.x) > Math.abs(star.y)) {
star.dx = 1.0;
star.dy = Math.abs(star.y / star.x);
} else {
star.dx = Math.abs(star.x / star.y);
star.dy = 1.0;
}
star.dx *= xcoeff * (displacementRate / 10);
star.dy *= ycoeff * (displacementRate / 10);
star.dz = -1;
star.ddx = (accelerationRate * star.dx) / 10;
star.ddy = (accelerationRate * star.dy) / 10;
return star;
}
function move(star) {
star.x += star.dx;
star.y += star.dy;
star.z += star.dz;
star.dx += star.ddx;
star.dy += star.ddy;
}
function updateStars(ctx, stars) {
for (var i=0; i<stars.length; i++) {
move(stars[i]);
if (stars[i].x < -this.originX || stars[i].x > this.originX || stars[i].y < -this.originY || stars[i].y > this.originY) {
// Remove
stars[i] = newStar();
} else {
// Paint
var deltaX = this.originX;
var deltaY = this.originY;
stars[i].drawInContext(ctx, deltaX, deltaY);
}
}
}
this.configureGeometry = function() {
// Ensure we are always at full width
this.canvas.width = window.innerWidth;
this.canvas.style.backgroundColor = bgColor;
var ratio = 1;
// Retina support
// See http://www.html5rocks.com/en/tutorials/canvas/hidpi/
if (this.scaleFactor > 1) {
var devicePixelRatio = this.scaleFactor;
var context = this.ctx;
var backingStoreRatio = context.webkitBackingStorePixelRatio ||
context.mozBackingStorePixelRatio ||
context.msBackingStorePixelRatio ||
context.oBackingStorePixelRatio ||
context.backingStorePixelRatio || 1;
ratio = devicePixelRatio / backingStoreRatio;
// Upscale the canvas if the two ratios don't match
if (devicePixelRatio !== backingStoreRatio) {
var canvas = this.canvas;
var oldWidth = canvas.width;
var oldHeight = canvas.height;
canvas.width = oldWidth * ratio;
canvas.height = oldHeight * ratio;
canvas.style.width = oldWidth + 'px';
canvas.style.height = oldHeight + 'px';
// Now scale the context to counter the fact that we've manually scaled our canvas element
context.scale(ratio, ratio);
}
}
// Starting origin of stars
var logicalWidth = this.canvas.width / ratio;
var logicalHeight = this.canvas.height / ratio;
this.originX = logicalWidth / 2;
this.originY = logicalHeight / 2;
var numStars = logicalWidth / 2;
this.numStars = numStars > maxStars ? maxStars : numStars;
}
this.render = function() {
setTimeout(function() {
// Drawing
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
updateStars(this.ctx, this.stars);
requestAnimationFrame(render);
}, 1000 / FPS);
};
// Configure origin and frames before creating initial batch of stars
this.configureGeometry();
for (var i=0; i<this.numStars; i++) {
this.stars.push(newStar());
}
return this;
}
var starfield = StarField(element);
if (starfield.isCanvasEnabled) {
starfield.render();
}
// Make sure we adjust the canvas whenever the window resizes
// Don't rely on CSS rules for 100% width because that causes rendering issues
window.addEventListener('resize', resizeCanvas, false);
function resizeCanvas() {
if (starfield.isCanvasEnabled) {
starfield.configureGeometry();
} else {
starfield.canvas.width = window.innerWidth;
}
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="starfield" width="100%" height="400px"></canvas>

How to change the zoom factor to only zoom OUT on Ken Burns effect?

I am helping a friend with a website, and he is using the Ken Burns Effect with Javascript and Canvas from this site https://www.willmcgugan.com/blog/tech/post/ken-burns-effect-with-javascript-and-canvas/
for a slide-show. It works perfectly, but he would like to change the zoom effect to where all of the images zoom OUT, instead of alternating between zooming in and out.
After about a week of "scrambling" the code unsuccessfully, he posted a question about it on the site. The reply he received was (quote) "That's definitely possible, with a few tweaks of the code. Sorry, no time to give you guidance at the moment, but it shouldn't be all that difficult" (end quote).
I can't seem to figure it out either, so I'm hoping that someone here may be of help. Below is the code as posted on the willmcgugan.com website. Any help on how to change the zoom effect would be greatly appreciated.
(function($){
$.fn.kenburns = function(options) {
var $canvas = $(this);
var ctx = this[0].getContext('2d');
var start_time = null;
var width = $canvas.width();
var height = $canvas.height();
var image_paths = options.images;
var display_time = options.display_time || 7000;
var fade_time = Math.min(display_time / 2, options.fade_time || 1000);
var solid_time = display_time - (fade_time * 2);
var fade_ratio = fade_time - display_time
var frames_per_second = options.frames_per_second || 30;
var frame_time = (1 / frames_per_second) * 1000;
var zoom_level = 1 / (options.zoom || 2);
var clear_color = options.background_color || '#000000';
var images = [];
$(image_paths).each(function(i, image_path){
images.push({path:image_path,
initialized:false,
loaded:false});
});
function get_time() {
var d = new Date();
return d.getTime() - start_time;
}
function interpolate_point(x1, y1, x2, y2, i) {
// Finds a point between two other points
return {x: x1 + (x2 - x1) * i,
y: y1 + (y2 - y1) * i}
}
function interpolate_rect(r1, r2, i) {
// Blend one rect in to another
var p1 = interpolate_point(r1[0], r1[1], r2[0], r2[1], i);
var p2 = interpolate_point(r1[2], r1[3], r2[2], r2[3], i);
return [p1.x, p1.y, p2.x, p2.y];
}
function scale_rect(r, scale) {
// Scale a rect around its center
var w = r[2] - r[0];
var h = r[3] - r[1];
var cx = (r[2] + r[0]) / 2;
var cy = (r[3] + r[1]) / 2;
var scalew = w * scale;
var scaleh = h * scale;
return [cx - scalew/2,
cy - scaleh/2,
cx + scalew/2,
cy + scaleh/2];
}
function fit(src_w, src_h, dst_w, dst_h) {
// Finds the best-fit rect so that the destination can be covered
var src_a = src_w / src_h;
var dst_a = dst_w / dst_h;
var w = src_h * dst_a;
var h = src_h;
if (w > src_w)
{
var w = src_w;
var h = src_w / dst_a;
}
var x = (src_w - w) / 2;
var y = (src_h - h) / 2;
return [x, y, x+w, y+h];
}
function get_image_info(image_index, load_callback) {
// Gets information structure for a given index
// Also loads the image asynchronously, if required
var image_info = images[image_index];
if (!image_info.initialized) {
var image = new Image();
image_info.image = image;
image_info.loaded = false;
image.onload = function(){
image_info.loaded = true;
var iw = image.width;
var ih = image.height;
var r1 = fit(iw, ih, width, height);;
var r2 = scale_rect(r1, zoom_level);
var align_x = Math.floor(Math.random() * 3) - 1;
var align_y = Math.floor(Math.random() * 3) - 1;
align_x /= 2;
align_y /= 2;
var x = r2[0];
r2[0] += x * align_x;
r2[2] += x * align_x;
var y = r2[1];
r2[1] += y * align_y;
r2[3] += y * align_y;
if (image_index % 2) {
image_info.r1 = r1;
image_info.r2 = r2;
}
else {
image_info.r1 = r2;
image_info.r2 = r1;
}
if(load_callback) {
load_callback();
}
}
image_info.initialized = true;
image.src = image_info.path;
}
return image_info;
}
function render_image(image_index, anim, fade) {
// Renders a frame of the effect
if (anim > 1) {
return;
}
var image_info = get_image_info(image_index);
if (image_info.loaded) {
var r = interpolate_rect(image_info.r1, image_info.r2, anim);
var transparency = Math.min(1, fade);
if (transparency > 0) {
ctx.save();
ctx.globalAlpha = Math.min(1, transparency);
ctx.drawImage(image_info.image, r[0], r[1], r[2] - r[0], r[3] - r[1], 0, 0, width, height);
ctx.restore();
}
}
}
function clear() {
// Clear the canvas
ctx.save();
ctx.globalAlpha = 1;
ctx.fillStyle = clear_color;
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.restore();
}
function update() {
// Render the next frame
var update_time = get_time();
var top_frame = Math.floor(update_time / (display_time - fade_time));
var frame_start_time = top_frame * (display_time - fade_time);
var time_passed = update_time - frame_start_time;
function wrap_index(i) {
return (i + images.length) % images.length;
}
if (time_passed < fade_time)
{
var bottom_frame = top_frame - 1;
var bottom_frame_start_time = frame_start_time - display_time + fade_time;
var bottom_time_passed = update_time - bottom_frame_start_time;
if (update_time < fade_time) {
clear();
} else {
render_image(wrap_index(bottom_frame), bottom_time_passed / display_time, 1);
}
}
render_image(wrap_index(top_frame), time_passed / display_time, time_passed / fade_time);
if (options.post_render_callback) {
options.post_render_callback($canvas, ctx);
}
// Pre-load the next image in the sequence, so it has loaded
// by the time we get to it
var preload_image = wrap_index(top_frame + 1);
get_image_info(preload_image);
}
// Pre-load the first two images then start a timer
get_image_info(0, function(){
get_image_info(1, function(){
start_time = get_time();
setInterval(update, frame_time);
})
});
};
})( jQuery );
If you want the simplest solution, I forked and modified your Codepen here:
http://codepen.io/jjwilly16/pen/NAovkp?editors=1010
I just removed a conditional that controls whether the zoom is moving out or in.
if (image_index % 2) {
image_info.r1 = r1;
image_info.r2 = r2;
}
else {
image_info.r1 = r2;
image_info.r2 = r1;
}
Changed to:
image_info.r1 = r2;
image_info.r2 = r1;
Now it only zooms out :)

Categories

Resources