skip to Main Content

I am writing some content in bullet points in HTML and then using swiper.js library ( https://swiperjs.com/demos/255-effect-cards/core) to display them as sliders. I am giving a download button to the slider and want the user to download all those sliders at once which are written inside HTML divs

Can you help me with how can make it work?

  • User sees slider
  • The user clicks on the download
  • It should convert all N slides into image format files(png/jpeg) and
    download each image to the user’s device.

code for js slider which has multiple divs and content inside each div

<div class="swiper mySwiper" >
  <div class="swiper-wrapper">
    <div class="swiper-slide">
      <h3  #screen>{{summary[0]}}</h3>
    </div>
    <div class="swiper-slide" >
      <h3 #screen>{{summary[1]}}</h3>
    </div>
    <div class="swiper-slide">
      <h3>{{summary[2]}}</h3>
    </div>
    <div class="swiper-slide">
      <h3>{{summary[3]}}</h3>
    </div>
    <div *ngIf="summary[4] != null" class="swiper-slide">
      <h3>{{summary[4]}}</h3>
    </div>
  </div>
</div>  

converting each div into an image

<div id="download" class="main" *ngIf="image">
  <img #canvas>
  <a #downloadLink></a>
</div> 
@ViewChild('screen') screen: ElementRef;
@ViewChild('canvas') canvas: ElementRef;
@ViewChild('downloadLink') downloadLink: ElementRef;

when user clicks on the button it should download all of the slides in one go

html2canvas(this.screen.nativeElement).then((canvas: any) => {
  this.canvas.nativeElement.src = canvas.toDataURL();
  this.downloadLink.nativeElement.href = canvas.toDataURL('image/png');
  this.downloadLink.nativeElement.download = 'summary.png';
  this.downloadLink.nativeElement.click();
});

2

Answers


  1. I’ve used this library before, but it only works for saving images written to the canvas. documentação da biblioteca. eligrey/FileSaver

    HTML
    div class="swiper-slide"><img src=’pic_the_scream.jpg’

    JAVASCRIPT

    function saveIMG(){
    var div = document.getElementsByClassName('swiper-slide-active');//obtem nó com a imagem ativa
    var image = div[0].getElementsByTagName('img')[0];
    
    var canva = document.createElement("canvas");//cria um elemento canvas
    canva.width = image.naturalWidth;//define largura do object criado proporcional a imagem
    canva.height = image.naturalHeight;//define altura do object criado proporcional a imagem
    
    var title = 'slide_'+document.getElementsByClassName('swiper-slide-active')[0].getAttribute('aria-label').substring(0,document.getElementsByClassName('swiper-slide-active')[0].getAttribute('aria-label').indexOf('/')-1)+'.png';//Nome do arquivo criado
    
    canva.getContext("2d").drawImage(image, 0, 0, image.naturalWidth, image.naturalHeight, 0, 0, image.naturalWidth, image.naturalHeight);//desenha a image dentro do elemento canvas
    
    canva.toBlob(function(blob){
       saveAs(blob, title); //salva a imagem gerada no elemento canva criado
    });
    

    };

    meustestes: This is the github repository I used for testing. To see the code working, see the repository on github that let.

    There may be cross contamination issues. The code gives error when I try to run inside the machine.

    The images need to be inside the origin server, but if you try to apply the code below, the code saves an empty image.

    // Solving the contamination problem
    var img = new Image();
    img.src = image.src;    
    img.crossOrigin = 'anonymous';
    

    But if I run the code inside w3schools , the image origin server , the image is downloaded intact.

    Good luck resolving this issue.

    Login or Signup to reply.
  2. As already commented by Anant V jszip.js can combine multiple files to a single download.

    The slightly tricky parts:

    • due to this specific "card deck" swiper style we need to temporarily reset transformations – otherwise, the canvas to image output will return cropped images.
    • a lot of asynchronous calls (await for the canvas rendering, wait for the blob creation etc.)

    The download functionality doesn’t work in SO snippets:
    See working codepen example

    // init swiper
    const swiper = new Swiper(".mySwiper", {
      effect: "cards",
      grabCursor: true
    });
    // wait for all fonts
    document.fonts.ready.then(function () {
      // convert slides to image blobs and zip them
      zipImagesInBackground(mySwiper, aDownload, 2, "myswiperDownload.zip");
    });
    async function zipImagesInBackground(
      slider,
      downloadEl,
      scale = 1,
      filename = "example.zip"
    ) {
      // init zip object
      let zip = new JSZip();
      // create canvas for each slide
      let slides = slider.querySelectorAll(".swiper-slide");
      for (let i = 0; i < slides.length; i++) {
        let slide = slides[i];
        // temporarily disable transformation for canvas drawing
        let style = window.getComputedStyle(slide);
        let transform = style.transform;
        slide.style.transform = "none";
        let canvas = await html2canvas(slide, {
          scale: scale
        });
        let dataUrl = await canvas.toDataURL();
        let base64 = dataUrl.split("base64,")[1];
        zip.file(`slide${i}.png`, base64, {
          base64: true
        });
        //re-apply transform
        slide.style.transform = transform;
      }
      slider.classList.remove("hidden");
      // create zip
      let blob = await zip.generateAsync({
        type: "blob"
      });
      downloadEl.href = URL.createObjectURL(blob);
      downloadEl.download = filename;
    }
    body {
      font-family: "Noto Sans";
      font-weight: 400;
    }
    
    .swiper {
      transition: 0.3s;
    }
    .hidden {
      opacity: 1;
    }
    
    .btn-default {
      text-decoration: none;
      border: 1px solid #ccc;
      padding: 0.3em;
      color: inherit;
    }
    
    .layout {
      display: flex;
      justify-content: center;
      align-items: center;
      position: relative;
      height: 100%;
    }
    
    .swiper {
      width: 240px;
      height: 320px;
    }
    
    .swiper-slide {
      display: flex !important;
      align-items: center;
      justify-content: center;
      border-radius: 18px;
      font-size: 22px;
      font-weight: bold;
      color: #fff;
    }
    
    .swiper-slide:nth-child(1n) {
      background-color: rgb(206, 17, 17);
    }
    
    .swiper-slide:nth-child(2n) {
      background-color: rgb(0, 140, 255);
    }
    
    .swiper-slide:nth-child(3n) {
      background-color: rgb(10, 184, 111);
    }
    
    .swiper-slide:nth-child(4n) {
      background-color: rgb(211, 122, 7);
    }
    
    .swiper-slide:nth-child(5n) {
      background-color: rgb(118, 163, 12);
    }
    
    .swiper-slide:nth-child(6n) {
      background-color: rgb(180, 10, 47);
    }
    
    .swiper-slide:nth-child(7n) {
      background-color: rgb(35, 99, 19);
    }
    
    .swiper-slide:nth-child(8n) {
      background-color: rgb(0, 68, 255);
    }
    
    .swiper-slide:nth-child(9n) {
      background-color: rgb(218, 12, 218);
    }
    
    .swiper-slide:nth-child(10n) {
      background-color: rgb(54, 94, 77);
    }
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@9/swiper-bundle.min.css" />
    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans&display=swap" rel="stylesheet">
    
    <p><a id="aDownload" class="btn-default" download="slides.zip" href="">Download Slides</a></p>
    
    <div class="layout">
      <div id="mySwiper" class="swiper mySwiper hidden">
        <div class="swiper-wrapper">
          <div class="swiper-slide">Slide 1</div>
          <div class="swiper-slide ">Slide 2</div>
          <div class="swiper-slide">Slide 3</div>
          <div class="swiper-slide">Slide 4</div>
          <div class="swiper-slide">Slide 5</div>
          <div class="swiper-slide">Slide 6</div>
          <div class="swiper-slide">Slide 7</div>
          <div class="swiper-slide">Slide 8</div>
          <div class="swiper-slide">Slide 9</div>
        </div>
      </div>
    </div>
    
    <script src="https://cdn.jsdelivr.net/npm/swiper@9/swiper-bundle.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jszip.js"></script>

    How it works:

    1. loop through all slides and create images via html2canvas
    2. create blobs for each image and collect it in a zip object provided by jszip.js
    3. create an object URL for the download link/button
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search