如何将多个DIV转换为多个图像并一次性下载它们

huangapple go评论77阅读模式
英文:

How to convert multiple DIVs into multiple images and download them all at once

问题

我在HTML中以项目符号的方式编写了一些内容,然后使用swiper.js库(https://swiperjs.com/demos/255-effect-cards/core)将它们显示为滑块。我给滑块添加了一个下载按钮,希望用户可以一次下载所有写在HTML div中的滑块。

你可以帮我解决这个问题吗?

  • 用户看到滑块
  • 用户点击下载按钮
  • 应该将所有N个滑块转换为图像格式文件(png/jpeg)并下载每个图像到用户设备。

具有多个div和每个div中内容的js滑块的代码

<div class="swiper mySwiper">
  <div class="swiper-wrapper">
    <div class="swiper-slide">
      <h3 id="screen">{{summary[0]}}</h3>
    </div>
    <div class="swiper-slide">
      <h3 id="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>

将每个div转换为图像

<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;

当用户点击按钮时,它应该一次下载所有滑块

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();
});
英文:

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

&lt;div class=&quot;swiper mySwiper&quot; &gt;
  &lt;div class=&quot;swiper-wrapper&quot;&gt;
    &lt;div class=&quot;swiper-slide&quot;&gt;
      &lt;h3  #screen&gt;{{summary[0]}}&lt;/h3&gt;
    &lt;/div&gt;
    &lt;div class=&quot;swiper-slide&quot; &gt;
      &lt;h3 #screen&gt;{{summary[1]}}&lt;/h3&gt;
    &lt;/div&gt;
    &lt;div class=&quot;swiper-slide&quot;&gt;
      &lt;h3&gt;{{summary[2]}}&lt;/h3&gt;
    &lt;/div&gt;
    &lt;div class=&quot;swiper-slide&quot;&gt;
      &lt;h3&gt;{{summary[3]}}&lt;/h3&gt;
    &lt;/div&gt;
    &lt;div *ngIf=&quot;summary[4] != null&quot; class=&quot;swiper-slide&quot;&gt;
      &lt;h3&gt;{{summary[4]}}&lt;/h3&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;  

converting each div into an image

&lt;div id=&quot;download&quot; class=&quot;main&quot; *ngIf=&quot;image&quot;&gt;
  &lt;img #canvas&gt;
  &lt;a #downloadLink&gt;&lt;/a&gt;
&lt;/div&gt; 
@ViewChild(&#39;screen&#39;) screen: ElementRef;
@ViewChild(&#39;canvas&#39;) canvas: ElementRef;
@ViewChild(&#39;downloadLink&#39;) 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) =&gt; {
  this.canvas.nativeElement.src = canvas.toDataURL();
  this.downloadLink.nativeElement.href = canvas.toDataURL(&#39;image/png&#39;);
  this.downloadLink.nativeElement.download = &#39;summary.png&#39;;
  this.downloadLink.nativeElement.click();
});

答案1

得分: 1

Anant V 已经评论的那样,jszip.js 可以将多个文件合并成单个下载。

略微棘手的部分:

  • 由于这特定的“卡牌堆叠”滑块样式,我们需要临时重置变换,否则画布到图像的输出将返回裁剪过的图像。
  • 存在许多异步调用(等待画布渲染,等待 blob 创建等)。

在 SO 片段中,下载功能不起作用:
请查看工作的 codepen 示例

如何工作:

  1. 循环遍历所有幻灯片并通过 html2canvas 创建图像。
  2. 为每个图像创建 blob 并将其收集在 jszip.js 提供的 zip 对象中。
  3. 为下载链接/按钮创建一个对象 URL。
英文:

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

<!-- begin snippet: js hide: true console: false babel: false -->

<!-- language: lang-js -->

// init swiper
const swiper = new Swiper(&quot;.mySwiper&quot;, {
  effect: &quot;cards&quot;,
  grabCursor: true
});
// wait for all fonts
document.fonts.ready.then(function () {
  // convert slides to image blobs and zip them
  zipImagesInBackground(mySwiper, aDownload, 2, &quot;myswiperDownload.zip&quot;);
});
async function zipImagesInBackground(
  slider,
  downloadEl,
  scale = 1,
  filename = &quot;example.zip&quot;
) {
  // init zip object
  let zip = new JSZip();
  // create canvas for each slide
  let slides = slider.querySelectorAll(&quot;.swiper-slide&quot;);
  for (let i = 0; i &lt; 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 = &quot;none&quot;;
    let canvas = await html2canvas(slide, {
      scale: scale
    });
    let dataUrl = await canvas.toDataURL();
    let base64 = dataUrl.split(&quot;base64,&quot;)[1];
    zip.file(`slide${i}.png`, base64, {
      base64: true
    });
    //re-apply transform
    slide.style.transform = transform;
  }
  slider.classList.remove(&quot;hidden&quot;);
  // create zip
  let blob = await zip.generateAsync({
    type: &quot;blob&quot;
  });
  downloadEl.href = URL.createObjectURL(blob);
  downloadEl.download = filename;
}

<!-- language: lang-css -->

body {
  font-family: &quot;Noto Sans&quot;;
  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);
}

<!-- language: lang-html -->

&lt;link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/swiper@9/swiper-bundle.min.css&quot; /&gt;
&lt;link href=&quot;https://fonts.googleapis.com/css2?family=Noto+Sans&amp;display=swap&quot; rel=&quot;stylesheet&quot;&gt;

&lt;p&gt;&lt;a id=&quot;aDownload&quot; class=&quot;btn-default&quot; download=&quot;slides.zip&quot; href=&quot;&quot;&gt;Download Slides&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;layout&quot;&gt;
  &lt;div id=&quot;mySwiper&quot; class=&quot;swiper mySwiper hidden&quot;&gt;
    &lt;div class=&quot;swiper-wrapper&quot;&gt;
      &lt;div class=&quot;swiper-slide&quot;&gt;Slide 1&lt;/div&gt;
      &lt;div class=&quot;swiper-slide &quot;&gt;Slide 2&lt;/div&gt;
      &lt;div class=&quot;swiper-slide&quot;&gt;Slide 3&lt;/div&gt;
      &lt;div class=&quot;swiper-slide&quot;&gt;Slide 4&lt;/div&gt;
      &lt;div class=&quot;swiper-slide&quot;&gt;Slide 5&lt;/div&gt;
      &lt;div class=&quot;swiper-slide&quot;&gt;Slide 6&lt;/div&gt;
      &lt;div class=&quot;swiper-slide&quot;&gt;Slide 7&lt;/div&gt;
      &lt;div class=&quot;swiper-slide&quot;&gt;Slide 8&lt;/div&gt;
      &lt;div class=&quot;swiper-slide&quot;&gt;Slide 9&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;script src=&quot;https://cdn.jsdelivr.net/npm/swiper@9/swiper-bundle.min.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;https://cdn.jsdelivr.net/npm/jszip@3.2.2/dist/jszip.js&quot;&gt;&lt;/script&gt;

<!-- end snippet -->

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

答案2

得分: 0

I've used this library before, but it only works for saving images written to the canvas. Documentation for the library can be found here: eligrey/FileSaver

HTML:

<div class="swiper-slide"><img src='pic_the_scream.jpg';

JavaScript:

function saveIMG() {
    var div = document.getElementsByClassName('swiper-slide-active'); // Get the element with the active image
    var image = div[0].getElementsByTagName('img')[0];
    
    var canvas = document.createElement("canvas"); // Create a canvas element
    canvas.width = image.naturalWidth; // Set the width of the canvas element to match the image
    canvas.height = image.naturalHeight; // Set the height of the canvas element to match the image
    
    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'; // Name of the created file
    
    canvas.getContext("2d").drawImage(image, 0, 0, image.naturalWidth, image.naturalHeight, 0, 0, image.naturalWidth, image.naturalHeight); // Draw the image into the canvas element
    
    canvas.toBlob(function(blob) {
        saveAs(blob, title); // Save the generated image in the created canvas element
    });
};

meustestes: This is the GitHub repository I used for testing. To see the code working, visit the repository on GitHub.

There may be cross-contamination issues. The code gives an error when I try to run it on the local machine.

The images need to be on the same origin server. If you try to apply the code below, it 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 on w3schools, where the image and the origin server match, the image is downloaded intact.

Good luck resolving this issue.

英文:

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(&#39;swiper-slide-active&#39;);//obtem n&#243; com a imagem ativa
var image = div[0].getElementsByTagName(&#39;img&#39;)[0];

var canva = document.createElement(&quot;canvas&quot;);//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 = &#39;slide_&#39;+document.getElementsByClassName(&#39;swiper-slide-active&#39;)[0].getAttribute(&#39;aria-label&#39;).substring(0,document.getElementsByClassName(&#39;swiper-slide-active&#39;)[0].getAttribute(&#39;aria-label&#39;).indexOf(&#39;/&#39;)-1)+&#39;.png&#39;;//Nome do arquivo criado

canva.getContext(&quot;2d&quot;).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 = &#39;anonymous&#39;;

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

Good luck resolving this issue.

huangapple
  • 本文由 发表于 2023年3月31日 16:34:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/75896450.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定