-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
123 lines (108 loc) · 2.6 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
'use strict'
class Compressor {
/** @type {File} */
originalFile
/** @type {string} */
fileUrl
/** @type {File} */
fileFile
/** @type {JSZip} */
zip
currentQuality = 1
compressionRatio = ''
/**
* @param {File} v
*/
set file(v) {
if (this.fileUrl) URL.revokeObjectURL(this.fileUrl)
this.fileFile = v
this.fileUrl = URL.createObjectURL(v)
}
/**
* @param {File} originalFile
* @param {JSZip} zip
*/
constructor(originalFile, zip) {
this.originalFile = originalFile
this.file = originalFile
this.zip = zip
}
/**
* @param {File} originalFile
* @param {JSZip} zip
*/
static async create(originalFile, zip) {
const item = new Compressor(originalFile, zip)
await item.compress(50)
return item
}
/**
* @param {number} quality
*/
async compress(quality) {
quality /= 100
this.compressionRatio = 'Compressing...'
const compressed = await imageCompression(this.originalFile, {
initialQuality: quality,
useWebWorker: true,
maxIteration: 50,
})
this.file = compressed
this.currentQuality = quality
this.compressionRatio = (
this.originalFile.size / this.fileFile.size
).toFixed(2)
zip.file(this.originalFile.name, compressed)
}
}
var zip = new JSZip()
/**
* Generates a zip file.
* @param {Compressor} images
* @returns the blob.
*/
function generateAsync(images) {
return zip.generateAsync({
type: 'blob',
compression: 'DEFLATE',
compressionOptions: { level: 1 },
})
}
function getRows(a, n) {
return a
?.map((v, i) => (i % n ? undefined : a.slice(i, i + n)))
.filter((v) => v)
}
document.addEventListener('alpine:init', () => {
Alpine.store('images', [])
})
let zipUrl = ''
function cleanOldZip() {
if (!zipUrl) return
URL.revokeObjectURL(zipUrl)
Alpine.store('zip', '')
}
async function updateZip() {
const zipBlob = await generateAsync()
zipUrl = URL.createObjectURL(zipBlob)
Alpine.store('zip', zipUrl)
}
async function compressImages(images, quality) {
cleanOldZip()
await Promise.all(images?.map((v) => v.compress(quality)))
await updateZip()
}
async function addImages(images, event) {
cleanOldZip()
const files = event.target.files
if (!files) return
for (let i = 0; i < files.length; i++)
images.push(await Compressor.create(files[i], zip))
await updateZip()
}
function spaceSavings(images) {
const original = images.reduce((p, c) => p + c.originalFile.size, 0)
const compressed = images.reduce((p, c) => p + c.fileFile.size, 0)
const result = (1 - compressed / original) * 100
return result.toFixed(2)
}