UNPKG

viewerjs-optimize

Version:
283 lines (240 loc) 7.14 kB
import { CLASS_LOADING, CLASS_TRANSITION, EVENT_LOAD, EVENT_TRANSITION_END, EVENT_VIEWED, } from './constants'; import { addClass, addListener, assign, escapeHTMLEntities, forEach, getImageNameFromURL, getImageNaturalSizes, getTransforms, isFunction, isString, removeClass, removeListener, setData, setStyle, } from './utilities'; export default { render() { this.initContainer(); this.initViewer(); this.initList(); this.renderViewer(); }, initContainer() { this.containerData = { width: window.innerWidth, height: window.innerHeight, }; }, initViewer() { const { options, parent } = this; let viewerData; if (options.inline) { viewerData = { width: Math.max(parent.offsetWidth, options.minWidth), height: Math.max(parent.offsetHeight, options.minHeight), }; this.parentData = viewerData; } const containerBox = document.querySelector('#viewer-canvas'); viewerData = { width: Math.max(containerBox.offsetWidth, options.minWidth), height: Math.max(containerBox.offsetHeight, options.minHeight), }; // eslint-disable-next-line prefer-template const elementClassName = '.' + options.className.split(' ')[1]; const div1 = document.querySelector(elementClassName); div1.onmousedown = function mouseDownFunction(ev) { const oevent = ev || window.event; const distanceX = oevent.clientX - div1.offsetLeft; const distanceY = oevent.clientY - div1.offsetTop; document.onmousemove = function mouseMoveFunction(evs) { const oevents = evs || window.event; div1.style.left = `${oevents.clientX - distanceX}px`; div1.style.top = `${oevents.clientY - distanceY}px`; }; document.onmouseup = function mouseUpFunction() { document.onmousemove = null; document.onmouseup = null; }; }; // if (this.fulled || !viewerData) { // viewerData = this.containerData; // } this.viewerData = assign({}, viewerData); }, renderViewer() { if (this.options.inline && !this.fulled) { setStyle(this.viewer, this.viewerData); } }, initList() { const { element, options, list } = this; const items = []; forEach(this.images, (image, i) => { const src = escapeHTMLEntities(image.src); const alt = escapeHTMLEntities(image.alt || getImageNameFromURL(src)); let { url } = options; if (isString(url)) { url = escapeHTMLEntities(image.getAttribute(url)); } else if (isFunction(url)) { url = escapeHTMLEntities(url.call(this, image)); } if (src || url) { items.push('<li>' + '<img' + ` src="${src || url}"` + ' role="button"' + ' data-viewer-action="view"' + ` data-index="${i}"` + ` data-original-url="${url || src}"` + ` alt="${alt}"` + '>' + '</li>'); } }); list.innerHTML = items.join(''); this.items = list.getElementsByTagName('li'); forEach(this.items, (item) => { const image = item.firstElementChild; setData(image, 'filled', true); if (options.loading) { addClass(item, CLASS_LOADING); } addListener(image, EVENT_LOAD, (event) => { if (options.loading) { removeClass(item, CLASS_LOADING); } this.loadImage(event); }, { once: true, }); }); if (options.transition) { addListener(element, EVENT_VIEWED, () => { addClass(list, CLASS_TRANSITION); }, { once: true, }); } }, renderList(index) { const i = index || this.index; const width = this.items[i].offsetWidth || 30; const outerWidth = width + 1; // 1 pixel of `margin-left` width // Place the active item in the center of the screen setStyle(this.list, assign({ width: outerWidth * this.length, }, getTransforms({ translateX: 0, // translateX: ((this.viewerData.width - width) / 2) - (outerWidth * i), }))); }, resetList() { const { list } = this; list.innerHTML = ''; removeClass(list, CLASS_TRANSITION); setStyle(list, getTransforms({ translateX: 0, })); }, initImage(done) { const { options, image, viewerData } = this; const footerHeight = this.footer.offsetHeight; const viewerWidth = viewerData.width; const viewerHeight = Math.max(viewerData.height - footerHeight, footerHeight); const oldImageData = this.imageData || {}; let sizingImage; this.imageInitializing = { abort() { sizingImage.onload = null; }, }; sizingImage = getImageNaturalSizes(image, (naturalWidth, naturalHeight) => { const aspectRatio = naturalWidth / naturalHeight; let width = viewerWidth; let height = viewerHeight; this.imageInitializing = false; if (viewerHeight * aspectRatio > viewerWidth) { height = viewerWidth / aspectRatio; } else { width = viewerHeight * aspectRatio; } width = Math.min(width * 0.9, naturalWidth); height = Math.min(height * 0.9, naturalHeight); const imageData = { naturalWidth, naturalHeight, aspectRatio, ratio: width / naturalWidth, width, height, left: (viewerWidth - width) / 2, top: (viewerHeight - height) / 2, }; const initialImageData = assign({}, imageData); if (options.rotatable) { imageData.rotate = oldImageData.rotate || 0; initialImageData.rotate = 0; } if (options.scalable) { imageData.scaleX = oldImageData.scaleX || 1; imageData.scaleY = oldImageData.scaleY || 1; initialImageData.scaleX = 1; initialImageData.scaleY = 1; } this.imageData = imageData; this.initialImageData = initialImageData; if (done) { done(); } }); }, renderImage(done) { const { image, imageData } = this; setStyle(image, assign({ width: imageData.width, height: imageData.height, // XXX: Not to use translateX/Y to avoid image shaking when zooming marginLeft: imageData.left, marginTop: imageData.top, }, getTransforms(imageData))); if (done) { if ((this.viewing || this.zooming) && this.options.transition) { const onTransitionEnd = () => { this.imageRendering = false; done(); }; this.imageRendering = { abort() { removeListener(image, EVENT_TRANSITION_END, onTransitionEnd); }, }; addListener(image, EVENT_TRANSITION_END, onTransitionEnd, { once: true, }); } else { done(); } } }, resetImage() { // this.image only defined after viewed if (this.viewing || this.viewed) { const { image } = this; if (this.viewing) { this.viewing.abort(); } image.parentNode.removeChild(image); this.image = null; } }, };