UNPKG

lu2

Version:

Simple and flexible UI component library based on native HTML and JavaScript

214 lines (179 loc) 7.12 kB
/** * @author zhangxinxu * @create 2022-02-09 * @description 进度条效果的增强处理 **/ /**/(async () => { /**/ if (!CSS.supports('overflow-anchor:auto') || !CSS.supports('offset:none')) { /**/ await import('../safari-polyfill.js'); /**/ } class UiProgress extends HTMLProgressElement { static get observedAttributes () { return ['color', 'height', 'radius', 'width', 'value', 'label']; } get color () { return this.getAttribute('color'); } set color (val) { this.setAttribute('color', val); } get label () { return this.getAttribute('label'); } set label (val) { this.setAttribute('label', val); } get radius () { let radius = this.getAttribute('radius'); if (!isNaN(radius) && !isNaN(parseFloat(radius))) { radius = radius + 'px'; } return radius; } set radius (val) { this.setAttribute('radius', val); } get height () { let height = this.getAttribute('height'); if (!isNaN(height) && !isNaN(parseFloat(height))) { height = height + 'px'; } return height; } set height (val) { this.setAttribute('height', val); } get width () { let width = this.getAttribute('width'); if (!isNaN(width) && !isNaN(parseFloat(width))) { width = width + 'px'; } return width; } set width (val) { this.setAttribute('width', val); } // 进度条进度信息显示 setLabel () { let label = this.label; if (!label && label !== '') { return; } this.style.setProperty('--ui-progress-offset', Math.round(this.getBoundingClientRect().width * (this.value / this.max))); this.style.setProperty('--ui-progress-percent', Math.round((this.value / this.max) * 100) + '%'); if (label == 'true' || label === '') { this.style.setProperty('--ui-progress-label', `'${Math.round((this.value / this.max) * 100) + '%'}'`); } else { // 自定义语法 this.style.setProperty('--ui-progress-label', `'${new Function(...['max', 'value'], `return \`${label}\`;`)(...[this.max, this.value])}'`); } // 模拟 label 效果 let eleLabel = this.element.label; if (eleLabel) { // 样式同步 eleLabel.setAttribute('style', this.getAttribute('style')); eleLabel.className = this.className; // 尺寸和偏移处理 // 按钮的尺寸和位置 let objBoundSelect = this.getBoundingClientRect(); // 尺寸设置 eleLabel.style.width = objBoundSelect.width + 'px'; eleLabel.style.height = objBoundSelect.height + 'px'; // 偏移对比 let objBoundTrigger = eleLabel.getBoundingClientRect(); let objStyleTrigger = getComputedStyle(eleLabel); // 目前的偏移 let numOffsetX = objStyleTrigger.getPropertyValue('--ui-offset-x') || 0; let numOffsetY = objStyleTrigger.getPropertyValue('--ui-offset-y') || 0; // 偏移误差 let numDistanceX = objBoundSelect.left - objBoundTrigger.left; let numDistanceY = objBoundSelect.top - objBoundTrigger.top; // 设置新的偏移值 eleLabel.style.setProperty('--ui-offset-x', Number(numOffsetX) + numDistanceX); eleLabel.style.setProperty('--ui-offset-y', Number(numOffsetY) + numDistanceY); } } renderAttribute (name, keep) { if (name === 'value' || name == 'label') { this.setLabel(); return; } if (typeof this[name] == 'string') { this.style.setProperty('--ui-progress-' + name, this[name]); } else if (!keep) { this.style.removeProperty('--ui-progress-' + name); } } render () { UiProgress.observedAttributes.forEach(attr => { this.renderAttribute(attr, true); }); } attributeChangedCallback (name) { this.render(name); } constructor () { super(); if (!this.element) { this.element = {}; } this.render(); const propValue = Object.getOwnPropertyDescriptor(HTMLProgressElement.prototype, 'value'); Object.defineProperty(UiProgress.prototype, 'value', { ...propValue, set (value) { // 赋值 propValue.set.call(this, value); // 触发渲染 this.renderAttribute('value'); } }); // Safari/Firefox 不支持伪元素,创建元素代替 if (this.hasAttribute('label') && (CSS.supports('-moz-appearance:none') || !CSS.supports('text-align-last:justify'))) { let eleLabel = document.createElement('label'); if (this.id) { eleLabel.setAttribute('for', this.id); } eleLabel.setAttribute('is', 'ui-progress'); // 暴露 this.element.label = eleLabel; } // 观察尺寸变化 let objResizeObserver = new ResizeObserver(() => { this.setLabel(); }); // 观察文本域元素 objResizeObserver.observe(this); } connectedCallback () { // 插入到页面中 let eleLabel = this.element.label; if (eleLabel) { this.insertAdjacentElement('beforebegin', eleLabel); // 定位和层级 // 是否是静态定位 if (getComputedStyle(eleLabel).position == 'static') { eleLabel.style.position = 'absolute'; } // 层级高一个 let numZIndex = getComputedStyle(this).zIndex; if (typeof numZIndex == 'number') { eleLabel.style.zIndex = numZIndex + 1; } this.setLabel(); } // 全局事件 this.dispatchEvent(new CustomEvent('connected', { detail: { type: 'ui-progress' } })); this.isConnectedCallback = true; } } if (!customElements.get('ui-progress')) { customElements.define('ui-progress', UiProgress, { extends: 'progress' }); } /**/})();