UNPKG

@massimo-cassandro/unsplash-page

Version:

A page with a photo from Unsplash to display some message (useful for error pages)

147 lines (114 loc) 6 kB
import imageIcon from './icons/image-duotone.svg'; import arrowIcon from './icons/arrow-fat-lines-left-duotone.svg'; import { breakpoints } from './src/img-breakpoints'; import { fetchUnsplashData } from './src/fetch-unsplash-data'; import { decode } from 'blurhash'; export function unsplashPageJS(settings) { const default_settings = { targetElement : null, className : null, unsplashDataUrl : null, utmSource : null, title : null, text : null, backLink : null, hidePhotoLink : true, cssModulesObj : null }, required_settings = ['targetElement', 'unsplashDataUrl', 'utmSource', 'title']; settings = {...default_settings, ...settings}; try { if(required_settings .map(i => settings[i]) .filter(i => i !== null && i !== '').length !== required_settings.length) { throw new Error( `I parametri ${required_settings.map(i => `\`${i}\``).join(',')} sono obbligatori` ); } const cssClass = classname => settings.cssModulesObj? settings.cssModulesObj[classname] : classname; settings.targetElement.innerHTML = `<div class="${cssClass('upContainer') + (settings.className? ` ${settings.className}` : '')}"></div>`; const container = settings.targetElement.querySelector('.' + cssClass('upContainer')); container.innerHTML = `<div class="${cssClass('upLoaderWrapper')}"><div class="${cssClass('upLoader')}"></div></div>`; fetchUnsplashData({unsplash_data_url: settings.unsplashDataUrl}) .then(photo => { const pixels = decode(photo.blur_hash, container.offsetWidth, container.offsetHeight); const canvas = document.createElement('canvas'); canvas.className = cssClass('upCanvas'); canvas.width = container.offsetWidth; canvas.height = container.offsetHeight; const ctx = canvas.getContext('2d'); const imageData = ctx.createImageData(container.offsetWidth, container.offsetHeight); imageData.data.set(pixels); ctx.putImageData(imageData, 0, 0); container.insertAdjacentElement('afterbegin', canvas); const formats = ['avif', 'webp', 'pjpg']; // `fm` parameter, in order of use container.insertAdjacentHTML('beforeend', '<picture>' + breakpoints.map((brk, idx) => { const is_last_brk = idx === breakpoints.length - 1; return formats.map(fmt => { const is_default_fmt = fmt === formats.at(-1); // https://unsplash.com/documentation#supported-parameters // https://docs.imgix.com/apis/rendering/size/w // https://docs.imgix.com/apis/rendering/size/h // https://docs.imgix.com/apis/rendering/size/ar // https://docs.imgix.com/apis/rendering/size/fit // https://docs.imgix.com/apis/rendering/size/crop // https://docs.imgix.com/apis/rendering/format/q let url = photo.base_url + (/\?/.test(photo.base_url)? '&' : '?') + 'fit=crop&crop=focalpoint' + // top, bottom, left, right, faces, focalpoint, edges, and entropy '&q=60' + `&w=${brk.w}&h=${brk.h}` + `&fm=${fmt}`; if(is_last_brk && is_default_fmt) { return '<img ' + `class="${cssClass('unsplashPhoto')}" `+ `src="${url}" `+ `srcset="${url}${brk.dpr2? ` 1x, ${url}&dpr=2 2x` : ''}" `+ `alt="${photo.alt_description?? `${photo.author} / Unsplash`}" `+ `width="${brk.w}" height="${brk.h}">`; } else { return '<source ' + `srcset="${url}${brk.dpr2? ` 1x, ${url}&dpr=2 2x` : ''}" `+ (!is_default_fmt? `type="image/${fmt}" ` : '')+ `media="${brk.mq}" `+ `width="${brk.w}" height="${brk.h}">`; } }).join(''); }).join('') + '</picture>' ); // end insert <picture> const img = container.querySelector('.' + cssClass('unsplashPhoto')); img.onload = () => { container.querySelector('.' + cssClass('upLoaderWrapper'))?.remove(); container.classList.add(cssClass('show')); container.insertAdjacentHTML('beforeend', `<div class="${cssClass('upMessageBox')}"> <div class="${cssClass('upMessage')}"> <h1>${settings.title}</h1> ${settings.text? `<p>${settings.text}</p>` : ''} ${settings.backLink ? `<p class="${cssClass('upBackLink')}">${settings.backLink}</p>` : ''} <div class="${cssClass('upArrowWrapper')}" role="button"> <img src="${arrowIcon}" alt="Icona freccia"> </div> </div> <div class="${cssClass('upCredits')}"> <em>${photo.image_description}</em> <span>Photo <a href="${`${photo.author_profile}?utmSource=${settings.utmSource}&utm_medium=referral`}"> ${photo.author} / Unsplash </a> </span> </div> </div> <div class="${cssClass('unsplashPhotoLink')}${settings.hidePhotoLink? ` ${cssClass('upShowOnHover')}` : ''}"> <a href="${`${photo.unsplash_url}?utm_source=${settings.utmSource}&utm_medium=referral`}" target="_blank" rel="noopener noreferrer"> <img src="${imageIcon}" alt="Icona immagine" /> </a> </div>`); container.querySelector('.' + cssClass('upArrowWrapper')).addEventListener('click', e => { e.target.closest(`.${cssClass('upMessage')}`).classList.toggle(cssClass('hidden')); }, false); }; // end img.onload }); // end .then } catch(e) { console.error( e ); // eslint-disable-line } }