let styles = require('./popup.css') styles = styles.default interface Icomponent { tempContainer: HTMLElement; init: () => void; template: () => void; handle: () => void; } interface Ipopup { width?: string; height?: string; title?: string; pos?: string; mask?: boolean; content?: (content: HTMLElement) => void } function popup(options: Ipopup) { return new Popup(options) } class Popup implements Icomponent { tempContainer; private settings; mask; private isDraging: boolean = false; private initX: number = 0; private initY: number = 0; private initOffsetTop = 0; private initOffsetLeft = 0; constructor(settings: Ipopup) { this.settings = Object.assign({ width: '100%', height: '100%', title: '', pos: 'center', mask: true, content: function () { } }, settings) this.init() } // 初始化 init() { this.template(); this.settings.mask && this.createMask(); this.contentCallback(); this.handle(); } // 创建模板 template() { this.tempContainer = document.createElement('div'); this.tempContainer.style.width = this.settings.width; this.tempContainer.style.height = this.settings.height; this.tempContainer.className = styles.popup; this.tempContainer.innerHTML = ` <div class="${styles['popup-title']}"> <h3>${this.settings.title}</h3> <i class="iconfont iconclose"></i> </div> <div class="${styles['popup-content']}"></div> ` document.body.appendChild(this.tempContainer) switch (this.settings.pos) { case 'left': this.tempContainer.style.left = 0; this.tempContainer.style.top = (window.innerHeight - this.tempContainer.offsetHeight) + 'px' break; case 'right': this.tempContainer.style.right = 0; this.tempContainer.style.top = (window.innerHeight - this.tempContainer.offsetHeight) + 'px'; break; default: this.tempContainer.style.left = (window.innerWidth - this.tempContainer.offsetWidth) / 2 + 'px'; this.tempContainer.style.top = (window.innerHeight - this.tempContainer.offsetHeight) / 2 + 'px'; break; } } handle() { let _this = this let popupClose = this.tempContainer.querySelector(`.${styles['popup-title']} i`); let popupTitle = this.tempContainer.querySelector(`.${styles['popup-title']}`); popupClose.addEventListener('click', () => { document.body.removeChild(this.tempContainer); this.settings.mask && document.body.removeChild(this.mask); }) popupTitle.addEventListener('mousedown', function (e: MouseEvent) { this.style.cursor = 'move' let downX = e.pageX // 鼠标按下时在页面上的x坐标 let downY = e.pageY // 鼠标按下时在页面上的y坐标 let downL = this.parentNode.offsetLeft let downT = this.parentNode.offsetTop document.onmousemove = (ev: MouseEvent) => { let pageX = ev.pageX let pageY = ev.pageY let viewHeight = getViewHeight() let viewWidth = getViewWidth() let left = pageX - downX + downL let top = pageY - downY + downT pageX <= 0 && (left = 0) console.log('viewWidth: ' + viewWidth + '---' + 'pageX: ' + pageX) pageX + 5 >= viewWidth && (left = viewWidth - _this.tempContainer.offsetWidth) pageY <= 0 && (top = 0) pageY + 5 >= viewHeight && (top = viewHeight - _this.tempContainer.offsetHeight) _this.tempContainer.style.left = left + 'px' _this.tempContainer.style.top = top + 'px' } document.onmouseup = () => { popupTitle.style.cursor = 'default' document.onmousemove = document.onmouseup = null } e.preventDefault() }) /** * 得到浏览器显示的屏幕高度 */ function getViewHeight() { if (window.innerHeight != window.undefined) return window.innerHeight; if (document.compatMode == 'CSS1Compat') return document.documentElement.clientHeight; if (document.body) return document.body.clientHeight; return window.undefined; } /** * 得到浏览器显示的屏幕宽度 */ function getViewWidth() { if (window.innerWidth != window.undefined) return window.innerWidth; if (document.compatMode == 'CSS1Compat') return document.documentElement.clientWidth; if (document.body) return document.body.clientWidth; } } createMask() { this.mask = document.createElement('div'); this.mask.className = styles.mask; document.body.appendChild(this.mask); } contentCallback() { let popupContent = this.tempContainer.querySelector(`.${styles['popup-content']}`); this.settings.content(popupContent) } } export default popup
.popup { position: fixed; z-index: 20; border: 1px solid #ccc; } .popup-title { height: 60px; background-color: #f5f5f5; display: flex; justify-content: space-between; align-items: center; } .popup-title h3 { font-size: 18px; margin-left: 20px; } .popup-title i { font-size: 18px; margin-right: 20px; cursor: pointer; } .popup-content { height: calc(100% - 60px); background-color: rgb(252, 249, 249); } .mask { position: absolute; left: 0; top: 0; right: 0; bottom: 0; z-index: 10; background-color: rgba(0, 0, 0, 0.5); }