I am creating a carousel slider with a canvas. For every new photo slide in, I would like to keep the previous one until the new one completely comes in.
I use requestAnimationFrame to do the sliding effect. Every time, I need to clear the canvas for the animation. But I would like to keep the previous image(drawing).
Here is an example of the effect but I do it in a very inefficient way. my javascript
window.onload = () => {
let canvas = document.getElementById("myCanvas");
let ctx = canvas.getContext("2d");
let head = canvas.width;
function draw1() {
if (head > 0) {
head = head - 10;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "rgba(0, 255, 255,1)";
ctx.fillRect(head, 0, canvas.width - head, canvas.height);
window.requestAnimationFrame(draw1);
}
}
function draw2() {
if (head > 0) {
head = head - 10;
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw the previous canvas again for every update
ctx.fillStyle = "rgba(0, 255, 255,1)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "rgba(255, 0, 255,1)";
ctx.fillRect(head, 0, canvas.width - head, canvas.height);
window.requestAnimationFrame(draw2);
}
}
function draw3() {
if (head > 0) {
head = head - 10;
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw the previous canvas again for every update
ctx.fillStyle = "rgba(255, 0, 255,1)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "rgba(255, 255, 0,1)";
ctx.fillRect(head, 0, canvas.width - head, canvas.height);
window.requestAnimationFrame(draw3);
}
}
head = canvas.width;
draw1();
setTimeout(() => {
head = canvas.width;
draw2();
}, 2000);
setTimeout(() => {
head = canvas.width;
draw3();
}, 4000);
};
Any help is appreciated. Thanks.
CodePudding user response:
For your case you can draw over the previous image without clearing the canvas
window.onload = () => {
let canvas = document.getElementById('myCanvas')
let ctx = canvas.getContext('2d')
let head = canvas.width
function drawImage(current) {
if (head > 0) {
head = head - 10
ctx.drawImage(current, head, 0, canvas.width, canvas.height)
window.requestAnimationFrame(() => drawImage(current))
}
}
const empty = new Image()
const img1 = new Image()
img1.src =
'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAegr5NqpnuNQdxthB4Ys5O_uiyEqs-CQp6w&usqp=CAU'
const img2 = new Image()
img2.src =
'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSHFvenDq4nX-LgsmrRPamE9i-NMBkefW7Lzg&usqp=CAU'
const img3 = new Image()
img3.src =
'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiU9Jkual4WsPg38vFfxvYgDQlUdzOOecVg&usqp=CAU'
head = canvas.width
img1.onload = () => {
drawImage(img1)
}
img2.onload = () => {
setTimeout(() => {
head = canvas.width
drawImage(img2)
}, 2000)
}
img3.onload = () => {
setTimeout(() => {
head = canvas.width
drawImage(img3)
}, 4000)
}
}
body {
display: flex;
justify-content: center;
align-items: center;
}
canvas {
border: 1px solid #000000;
}
<canvas id="myCanvas" width="440" height="160"></canvas>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
EDIT:
For transparent images you can clear just the part of the canvas where the new transparent image is showing. So something like:
ctx.clearRect(head, 0, canvas.width - head, canvas.height)
Here is an example:
window.onload = () => {
let canvas = document.getElementById('myCanvas')
let ctx = canvas.getContext('2d')
let head = canvas.width
function drawImage(current) {
if (head > 0) {
head = head - 10
ctx.clearRect(head, 0, canvas.width - head, canvas.height)
ctx.drawImage(current, head, 0, canvas.width, canvas.height)
window.requestAnimationFrame(() => drawImage(current))
}
}
const empty = new Image()
const img1 = new Image()
img1.src = 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAegr5NqpnuNQdxthB4Ys5O_uiyEqs-CQp6w&usqp=CAU'
const img2 = new Image()
img2.src = 'https://api.iconify.design/foundation:social-github.svg'
const img3 = new Image()
img3.src = 'https://api.iconify.design/foundation:social-twitter.svg'
head = canvas.width
img1.onload = () => {
drawImage(img1)
}
img2.onload = () => {
setTimeout(() => {
head = canvas.width
drawImage(img2)
}, 2000)
}
img3.onload = () => {
setTimeout(() => {
head = canvas.width
drawImage(img3)
}, 4000)
}
}
body {
display: flex;
justify-content: center;
align-items: center;
}
canvas {
border: 1px solid #000000;
}
body {
display: flex;
justify-content: center;
align-items: center;
}
canvas {
border: 1px solid #000000;
}
<canvas id="myCanvas" width="440" height="170"></canvas>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
And for having a transparent image on top of the previous image you can do something like this:
window.onload = () => {
let canvas = document.getElementById('myCanvas')
let ctx = canvas.getContext('2d')
let head = canvas.width
function drawImage(prev, current) {
if (head > 0) {
head = head - 10
ctx.clearRect(head, 0, canvas.width - head, canvas.height)
ctx.drawImage(prev, 0, 0, canvas.width, canvas.height)
ctx.drawImage(current, head, 0, canvas.width, canvas.height)
window.requestAnimationFrame(() => drawImage(prev, current))
}
}
const empty = new Image()
const img1 = new Image()
img1.src = 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAegr5NqpnuNQdxthB4Ys5O_uiyEqs-CQp6w&usqp=CAU'
const img2 = new Image()
img2.src = 'https://api.iconify.design/foundation:social-github.svg'
const img3 = new Image()
img3.src = 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSHFvenDq4nX-LgsmrRPamE9i-NMBkefW7Lzg&usqp=CAU'
const img4 = new Image()
img4.src = 'https://api.iconify.design/foundation:social-twitter.svg'
head = canvas.width
img1.onload = () => {
drawImage(empty, img1)
}
img2.onload = () => {
setTimeout(() => {
head = canvas.width
drawImage(img1, img2)
}, 2000)
}
img3.onload = () => {
setTimeout(() => {
head = canvas.width
drawImage(img2, img3)
}, 5000);
}
img4.onload = () => {
setTimeout(() => {
head = canvas.width
drawImage(img3, img4)
}, 8000);
}
}
body {
display: flex;
justify-content: center;
align-items: center;
}
canvas {
border: 1px solid #000000;
}
<canvas id="myCanvas" width="440" height="170"></canvas>
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>