UNPKG

amis

Version:

一种MIS页面生成工具

161 lines (141 loc) 4.53 kB
/** * @file resize-sensor.js. * @author fex */ class EventQueue { q: Array<Function> = []; add(cb: Function) { this.q.push(cb); } call(...args: Array<any>) { this.q.forEach(fn => { fn(...args); }); } } export function getComputedStyle(element: HTMLElement, prop: string) { if ((element as any).currentStyle) { return (element as any).currentStyle[prop]; } else if (window.getComputedStyle) { const style = window.getComputedStyle(element, undefined); return style ? style.getPropertyValue(prop) : undefined; } else { return element.style[prop as any]; } } function attachResizeEvent(element: HTMLElement, resized: Function) { if (!(element as any).resizedAttached) { (element as any).resizedAttached = new EventQueue(); (element as any).resizedAttached.add(resized); } else if ((element as any).resizedAttached) { (element as any).resizedAttached.add(resized); return; } const resizeSensor = ((element as any).resizeSensor = document.createElement( 'div' )); resizeSensor.className = 'resize-sensor'; let style = 'position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: scroll; z-index: -1; visibility: hidden;'; let styleChild = 'position: absolute; left: 0; top: 0;'; resizeSensor.style.cssText = style; resizeSensor.innerHTML = ` <div class="resize-sensor-expand" style="${style}"> <div style="${styleChild}"></div> </div> <div class="resize-sensor-shrink" style="${style}"> <div style="${styleChild} width: 200%; height: 200%"></div> </div> <div class="resize-sensor-appear" style="${style}animation-name: apearSensor; animation-duration: 0.2s;"></div>`; // 要定义 resizeSensor 这个动画,靠这个监听出现。 element.appendChild(resizeSensor); (element as any).hasInlineStyle = element.hasAttribute('style'); const position = ((element as any).originPosition = getComputedStyle( element, 'position' )); if (!~['fixed', 'absolute'].indexOf(position)) { element.style.position = 'relative'; } const expand = resizeSensor.children[0] as HTMLElement; const expandChild = expand.children[0] as HTMLElement; const shrink = resizeSensor.children[1] as HTMLElement; // let shrinkChild = shrink.children[0] as HTMLElement; const appear = resizeSensor.children[2] as HTMLElement; let lastWidth: number, lastHeight: number; const reset = function () { expandChild.style.width = expand.offsetWidth + 10 + 'px'; expandChild.style.height = expand.offsetHeight + 10 + 'px'; expand.scrollLeft = expand.scrollWidth; expand.scrollTop = expand.scrollHeight; shrink.scrollLeft = shrink.scrollWidth; shrink.scrollTop = shrink.scrollHeight; lastWidth = element.offsetWidth; lastHeight = element.offsetHeight; }; reset(); let changed = function () { if ((element as any).resizedAttached) { (element as any).resizedAttached.call(); } }; let addEvent = function (el: HTMLElement, name: string, cb: Function) { if ((el as any).attachEvent) { (el as any).attachEvent('on' + name, cb); } else { el.addEventListener(name, cb as any); } }; let onScroll = function (e: Event) { if ( element.offsetWidth != lastWidth || element.offsetHeight != lastHeight ) { changed(); } reset(); }; addEvent(expand, 'scroll', onScroll); addEvent(shrink, 'scroll', onScroll); addEvent(appear, 'animationstart', reset); } function detach(element: HTMLElement) { if ((element as any).resizeSensor) { if ((element as any).hasInlineStyle) { element.style.position = (element as any).originPosition; } else { element.removeAttribute('style'); } try { element.removeChild((element as any).resizeSensor); } catch (e) {} delete (element as any).resizeSensor; delete (element as any).resizedAttached; delete (element as any).hasInlineStyle; delete (element as any).originPosition; } } export function resizeSensor( element: HTMLElement, callback: Function ): () => void; export function resizeSensor( element: HTMLElement, callback: Function, once: boolean = false ) { if (once) { attachResizeEvent(element, function (this: any) { callback.apply(this, arguments); detach(element); }); return; } attachResizeEvent(element, callback); let detached = false; return function () { if (detached) return; detached = true; detach(element); }; }