const preloadedImages = {} export const preloadImages = urls => batchPromise(urls, 4, preloadImage) export const batchPromise = (list, count, fn) => { // console.log(list, count, fn) let cancelled = false const promise = new Promise((resolve, reject) => { let index = 0 let len = list.length const worker = j => ( new Promise(resolveWorker => { const next = () => { const i = index++ if (cancelled || i >= len) { return resolveWorker() } const item = list[i] // console.log(['worker', j, '=>', i, item].join(' ')) fn(item) .then(next) .catch(err => { console.error(err, item) next() }) } next() }) ) const workers = [] for (let j = 0; j < count; j++) { workers.push(worker(j)) } Promise.all(workers) .then(resolve) .catch(reject) }) const cancel = () => cancelled = true return { promise, cancel } } export const preloadImage = (url, anonymous=false) => ( new Promise((resolve, reject) => { if (preloadedImages[url] || typeof url === 'object' && url instanceof Image) { return resolve(url) } preloadedImages[url] = true const image = new Image() let loaded = false image.onload = () => { if (loaded) return loaded = true image.onload = null image.onerror = null resolve(image) } image.onerror = () => { if (loaded) return image.onload = null image.onerror = null reject(image) } // console.log(img.src) if (anonymous) { image.crossOrigin = 'anonymous' } image.src = url if (image.complete) { image.onload() } }) ) export const cropImage = (url, crop, maxSide) => { return new Promise((resolve, reject) => { preloadImage(url, true) .then(image => { let { x, y, w, h } = crop x = parseFloat(x) y = parseFloat(y) w = parseFloat(w) h = parseFloat(h) const canvas = document.createElement('canvas') const ctx = canvas.getContext('2d') const { naturalWidth, naturalHeight } = image let width, height let cropWidth = naturalWidth * w let cropHeight = naturalHeight * h if (maxSide > 0) { if (cropWidth > cropHeight) { width = Math.min(maxSide, cropWidth) height = cropHeight * width / cropWidth } else { height = Math.min(maxSide, cropHeight) width = cropWidth * height / cropHeight } } else { width = cropWidth height = cropHeight } canvas.width = width canvas.height = height ctx.drawImage( image, Math.round(x * naturalWidth), Math.round(y * naturalHeight), Math.round(w * naturalWidth), Math.round(h * naturalHeight), 0, 0, canvas.width, canvas.height ) // console.log(x, y, w, h) // console.log(naturalWidth, naturalHeight) // console.log(width, height) resolve(canvas) }) }) }