очистите только определенные компоненты холста

#javascript #html #css #canvas

Вопрос:

Я создаю слайдер карусели с холстом. Для каждого нового слайда с фотографией я хотел бы сохранить предыдущий, пока полностью не появится новый.

Я использую requestAnimationFrame для создания эффекта скольжения. Каждый раз мне нужно очищать холст для анимации. Но я хотел бы сохранить предыдущее изображение(рисунок).

Вот пример эффекта, но я делаю это очень неэффективным способом. мой javascript

 window.onload = () =gt; {  let canvas = document.getElementById("myCanvas");  let ctx = canvas.getContext("2d");   let head = canvas.width;  function draw1() {  if (head gt; 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 gt; 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 gt; 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(() =gt; {  head = canvas.width;  draw2();  }, 2000);   setTimeout(() =gt; {  head = canvas.width;  draw3();  }, 4000); };  

Любая помощь будет признательна. Спасибо.

Комментарии:

1. Есть ли причина для использования холста и JS, а не изображений слайдов с использованием CSS?

Ответ №1:

В вашем случае вы можете рисовать поверх предыдущего изображения, не очищая холст

 window.onload = () =gt; {  let canvas = document.getElementById('myCanvas')  let ctx = canvas.getContext('2d')  let head = canvas.width   function drawImage(current) {  if (head gt; 0) {  head = head - 10  ctx.drawImage(current, head, 0, canvas.width, canvas.height)  window.requestAnimationFrame(() =gt; drawImage(current))  }  }   const empty = new Image()   const img1 = new Image()  img1.src =  'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAegr5NqpnuNQdxthB4Ys5O_uiyEqs-CQp6wamp;usqp=CAU'    const img2 = new Image()  img2.src =  'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSHFvenDq4nX-LgsmrRPamE9i-NMBkefW7Lzgamp;usqp=CAU'   const img3 = new Image()  img3.src =  'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiU9Jkual4WsPg38vFfxvYgDQlUdzOOecVgamp;usqp=CAU'   head = canvas.width   img1.onload = () =gt; {  drawImage(img1)  }   img2.onload = () =gt; {  setTimeout(() =gt; {  head = canvas.width  drawImage(img2)  }, 2000)  }   img3.onload = () =gt; {  setTimeout(() =gt; {  head = canvas.width  drawImage(img3)  }, 4000)  } } 
 body {  display: flex;  justify-content: center;  align-items: center; }  canvas {  border: 1px solid #000000; } 
 lt;canvas id="myCanvas" width="440" height="160"gt;lt;/canvasgt; 

Редактировать:

Для прозрачных изображений вы можете очистить только ту часть холста, где отображается новое прозрачное изображение. Так что что-то вроде:

 ctx.clearRect(head, 0, canvas.width - head, canvas.height)  

Вот пример:

 window.onload = () =gt; {  let canvas = document.getElementById('myCanvas')  let ctx = canvas.getContext('2d')  let head = canvas.width   function drawImage(current) {  if (head gt; 0) {  head = head - 10  ctx.clearRect(head, 0, canvas.width - head, canvas.height)  ctx.drawImage(current, head, 0, canvas.width, canvas.height)  window.requestAnimationFrame(() =gt; drawImage(current))  }  }   const empty = new Image()   const img1 = new Image()  img1.src = 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAegr5NqpnuNQdxthB4Ys5O_uiyEqs-CQp6wamp;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 = () =gt; {  drawImage(img1)  }   img2.onload = () =gt; {  setTimeout(() =gt; {  head = canvas.width  drawImage(img2)  }, 2000)  }   img3.onload = () =gt; {  setTimeout(() =gt; {  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; } 
 lt;canvas id="myCanvas" width="440" height="170"gt;lt;/canvasgt; 

И для того, чтобы иметь прозрачное изображение поверх предыдущего изображения, вы можете сделать что-то вроде этого:

 window.onload = () =gt; {  let canvas = document.getElementById('myCanvas')  let ctx = canvas.getContext('2d')  let head = canvas.width   function drawImage(prev, current) {  if (head gt; 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(() =gt; drawImage(prev, current))  }  }   const empty = new Image()   const img1 = new Image()  img1.src = 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAegr5NqpnuNQdxthB4Ys5O_uiyEqs-CQp6wamp;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-NMBkefW7Lzgamp;usqp=CAU'   const img4 = new Image()  img4.src = 'https://api.iconify.design/foundation:social-twitter.svg'     head = canvas.width   img1.onload = () =gt; {  drawImage(empty, img1)  }   img2.onload = () =gt; {  setTimeout(() =gt; {  head = canvas.width  drawImage(img1, img2)  }, 2000)  }   img3.onload = () =gt; {  setTimeout(() =gt; {  head = canvas.width  drawImage(img2, img3)  }, 5000);  }    img4.onload = () =gt; {  setTimeout(() =gt; {  head = canvas.width  drawImage(img3, img4)  }, 8000);  }  } 
 body {  display: flex;  justify-content: center;  align-items: center; }  canvas {  border: 1px solid #000000; } 
 lt;canvas id="myCanvas" width="440" height="170"gt;lt;/canvasgt; 

Комментарии:

1. некоторые из моих фотографий в формате png, и у них прозрачный фон

2. @user16971617 В этом случае вы можете очистить только часть нового изображения, используя ctx.clearRect(head, 0, canvas.width - head, canvas.height) вместо очистки всего холста. см. Пример в отредактированном ответе.

3. Спасибо. Но есть ли способ сохранить предыдущее изображение в фоновом режиме?

4. @user16971617 Вы имеете в виду, что когда новое прозрачное изображение полностью сдвинуто, старое изображение все еще видно сзади?

5. да, потому что мне нужно увидеть старое изображение во время перехода.