From c86d747885c82a7bd5e9fccc1f68b99b1ea645c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=87=E5=A4=A9?= Date: Wed, 20 Feb 2019 15:34:02 +0800 Subject: [PATCH] update to 2.x;rewrite layer component --- build.dev.js | 35 ++++----- build.next.js | 109 --------------------------- build.prod.js | 42 +++++------ package.json | 13 ++-- src/css/elem-ui.scss | 2 +- src/css/layer-normal.scss | 50 ++++++------- src/layer/index.js | 150 +++++++++++++++++--------------------- 7 files changed, 127 insertions(+), 274 deletions(-) delete mode 100644 build.next.js diff --git a/build.dev.js b/build.dev.js index c5c4d0b..c48c0aa 100644 --- a/build.dev.js +++ b/build.dev.js @@ -14,38 +14,29 @@ const sourceDir = path.resolve(__dirname, 'src') const buildDir = path.resolve(__dirname, 'dist') const prefixer = postcss().use( autoprefixer({ - browsers: ['ie > 9', 'iOS > 8', 'Android >= 4.4', 'ff > 38', 'Chrome > 38'] + browsers: ['ff > 61', 'Chrome > 63'] }) ) -const jsOpt = { - presets: ['es2015'], - plugins: [ - 'transform-es2015-modules-amd', - 'transform-decorators-legacy', - 'transform-object-rest-spread', - ['transform-es2015-classes', { loose: true }], - ['transform-es2015-for-of', { loose: true }] - ] -} -const cssOpt = { - outputStyle: 'compressed' -} const compileJs = (entry, output) => { log('编译JS: %s', chalk.green(entry)) - try { - let { code } = babel.transformFileSync(entry, jsOpt) - code = code.replace(/\.scss/g, '.css') - fs.echo(code, output) - } catch (err) { - return log(err) - } + let buf = fs.cat(entry).toString() + let code = buf + .replace(/\.scss/g, '.css') + .replace(/import '([a-z0-9\/\.\-_]*)(? { log('编译scss: %s', chalk.green(entry)) try { - const { css } = scss.renderSync({ ...cssOpt, file: entry }) + const { css } = scss.renderSync({ file: entry }) prefixer.process(css, { from: '', to: '' }).then(result => { fs.echo(result.css, output) }) diff --git a/build.next.js b/build.next.js deleted file mode 100644 index 29eb9e0..0000000 --- a/build.next.js +++ /dev/null @@ -1,109 +0,0 @@ -#! /usr/bin/env node - -const log = console.log -const fs = require('iofs') -const path = require('path') -const scss = require('node-sass') -const postcss = require('postcss') -const autoprefixer = require('autoprefixer') -const chalk = require('chalk') -const uglify = require('uglify-es') - -const sourceDir = path.resolve(__dirname, 'src') -const buildDir = path.resolve(__dirname, 'dist') -const prefixer = postcss().use( - autoprefixer({ - browsers: ['ff > 58', 'Chrome > 61'] - }) -) - -const cssOpt = { - outputStyle: 'compressed' -} - -const compileJs = (entry, output) => { - if (/touch\.patch/.test(entry)) { - return - } - let t1 = Date.now() - let buf = fs.cat(entry).toString() - let { code } = uglify.minify(buf) - code = code - .replace(/\.scss/g, '.css') - .replace(/import"([a-z0-9\/\.\-_]*)(? { - let t1 = Date.now() - const { css } = scss.renderSync({ ...cssOpt, file: entry }) - - prefixer.process(css, { from: '', to: '' }).then(result => { - log( - '编译scss: %s, 耗时 %s ms', - chalk.green(entry), - chalk.yellow(Date.now() - t1) - ) - fs.echo(result.css, output) - }) -} - -/*=======================================================*/ -/*===== ===*/ -/*=======================================================*/ - -if (fs.isdir(buildDir)) { - fs.rm(buildDir, true) - log(chalk.cyan('清除旧目录 dist/')) -} -fs.mkdir(buildDir) - -let list = fs.ls('./node_modules/anot/dist/') -list.forEach(it => { - fs.cp(it, path.resolve(buildDir, path.parse(it).base)) -}) - -log('复制anot框架文件完成...') - -/*----------------------------------------------*/ -/*----------------------------------------------*/ -/*----------------------------------------------*/ - -let files = fs.ls(sourceDir, true) -files = files.map(it => { - let file = path.parse(it) - if (!file.ext || file.base === '.DS_Store' || file.base === 'var.scss') { - return null - } - return { path: it, ext: file.ext, name: file.base } -}) - -files.forEach(file => { - if (!file) { - return - } - let entry = file.path - let output = file.path.replace('src/', 'dist/') - - switch (file.ext) { - case '.js': - compileJs(entry, output) - break - case '.scss': - output = output.replace(/\.scss$/, '.css') - compileCss(entry, output) - break - default: - fs.cp(entry, output) - } -}) diff --git a/build.prod.js b/build.prod.js index 0e77e8e..6e721de 100644 --- a/build.prod.js +++ b/build.prod.js @@ -3,7 +3,6 @@ const log = console.log const fs = require('iofs') const path = require('path') -const babel = require('babel-core') const scss = require('node-sass') const postcss = require('postcss') const autoprefixer = require('autoprefixer') @@ -14,43 +13,38 @@ const sourceDir = path.resolve(__dirname, 'src') const buildDir = path.resolve(__dirname, 'dist') const prefixer = postcss().use( autoprefixer({ - browsers: ['ie > 9', 'iOS > 8', 'Android >= 4.4', 'ff > 38', 'Chrome > 38'] + browsers: ['ff > 61', 'Chrome > 63'] }) ) -const jsOpt = { - presets: ['es2015'], - plugins: [ - 'transform-es2015-modules-amd', - 'transform-decorators-legacy', - 'transform-object-rest-spread', - ['transform-es2015-classes', { loose: true }], - ['transform-es2015-for-of', { loose: true }] - ] -} + const cssOpt = { outputStyle: 'compressed' } const compileJs = (entry, output) => { let t1 = Date.now() - try { - let { code } = babel.transformFileSync(entry, jsOpt) - code = uglify.minify(code).code.replace(/\.scss/g, '.css') - - log( - '编译JS: %s, 耗时 %s ms', - chalk.green(entry), - chalk.yellow(Date.now() - t1) + let buf = fs.cat(entry).toString() + let { code } = uglify.minify(buf) + code = code + .replace(/\.scss/g, '.css') + .replace(/import"([a-z0-9\/\.\-_]*)(? { let t1 = Date.now() const { css } = scss.renderSync({ ...cssOpt, file: entry }) + prefixer.process(css, { from: '', to: '' }).then(result => { log( '编译scss: %s, 耗时 %s ms', diff --git a/package.json b/package.json index 6ace4b0..ae3518d 100644 --- a/package.json +++ b/package.json @@ -1,21 +1,17 @@ { "name": "doui-anot", - "version": "0.0.1", + "version": "2.0.0", "description": "基于Anot框架的doUI组件库。支持IE10+,及现代浏览器。", "main": "index.js", "scripts": { "start": "node ./build.dev.js", - "prod": "node ./build.prod.js", - "next": "node ./build.next.js" + "prod": "node ./build.prod.js" }, "repository": { "type": "git", "url": "git+https://github.com/yutent/doui.git" }, - "keywords": [ - "doui", - "Anot" - ], + "keywords": ["doui", "Anot"], "author": "yutent", "license": "MIT", "dependencies": {}, @@ -32,6 +28,7 @@ "iofs": "^1.1.0", "node-sass": "^4.9.0", "postcss": "^6.0.22", - "uglify-es": "^3.3.9" + "uglify-es": "^3.3.9", + "anot": "^2.0.0" } } diff --git a/src/css/elem-ui.scss b/src/css/elem-ui.scss index 9fa2aa3..1ddb5de 100644 --- a/src/css/elem-ui.scss +++ b/src/css/elem-ui.scss @@ -10,7 +10,7 @@ /*--------各种按钮---------*/ -.do-ui-button {display:inline-block;height:16px;padding:2px 5px;line-height:12px;border-radius:2px;text-align:center;font-size:12px;background:nth($cp, 2);color:nth($cgr, 1);cursor:pointer;@include ts; +.do-ui-button {display:inline-block;height:16px;padding:2px 5px;line-height:12px;border:0;border-radius:2px;text-align:center;font-size:12px;background:nth($cp, 2);color:nth($cgr, 1);cursor:pointer;@include ts; &.medium {min-width:80px;height:30px;padding:0 8px;line-height:30px;font-size:14px} &.large {min-width:130px;height:45px;padding:0 13px;line-height:45px;border-radius:3px;font-size:18px;} diff --git a/src/css/layer-normal.scss b/src/css/layer-normal.scss index 2969658..1b4e833 100644 --- a/src/css/layer-normal.scss +++ b/src/css/layer-normal.scss @@ -9,23 +9,15 @@ @import "var.scss"; -.do-layer {width:auto;height:auto; +.do-layer {display:flex;justify-content:center;align-items:center;width:auto;height:auto; a {text-decoration:none;} - .layer-box {position:absolute;z-index:65535;opacity:0; + .layer-box {flex:0 auto;position:absolute;z-index:65535;opacity:0; &.shift {transition: all .5s ease-out;} - &.__tc {top:0;left:50%;} - &.__tl {top:0;left:0;} - &.__tr {top:0;left:100%;} - &.__ct {top:50%;left:50%;} - &.__cc {top:47.5%;left:50%;} - &.__bc {top:100%;left:50%;} - &.__bl {top:100%;left:0;} - &.__br {top:100%;left:100%;} @@ -94,7 +86,10 @@ /* loading类弹层 */ - &.type-6 {z-index:65539;box-shadow:none;background:transparent;} + &.type-6 {z-index:65539;box-shadow:none;background:transparent; + + .layer-content {display:flex;justify-content:center;align-items:center;} + } /* 特殊类弹层(toast弹层) */ @@ -121,23 +116,19 @@ /* 常规的转动 */ &.style-1 { - .dot-box {width:70%;height:70%;margin:15%;line-height:70px;font-size:70px;text-align:center; + .dot-box {width:70%;height:70%;margin:15%;line-height:70px;font-size:70px;text-align:center;animation: circle .8s infinite linear; i {display:block;width:100%;height:100%;} } } - - &.style-1 { - .dot-box {animation: circle .8s infinite linear;} - } /* 频谱波动 */ - &.style-2 {height:50px; + &.style-2 {height:40px; - .dot-box{width:100%;height:100%; + .dot-box{display:flex;justify-content:center;width:100%;height:100%; - i {float:left;display:block;width:10px;height:100%;margin:0 5px;background:nth($ct, 3);animation: bounce 1s infinite ease-in-out;transform:scaleY(.6); + i {float:left;display:block;width:6px;height:100%;margin:0 3px;background:nth($ct, 3);animation: bounce 1s infinite ease-in-out;transform:scaleY(.6); &:nth-child(2) {animation-delay:.1s;} &:nth-child(3) {animation-delay:.2s;} @@ -148,11 +139,11 @@ } /* 缓动圆圈 */ - &.style-3 { + &.style-3 {width:50px;height:50px; - .dot-box{width:60%;height:60%;margin:20%; + .dot-box{width:100%;height:100%; - i {position:absolute;display:block;width:60px;height:60px;animation: circle2 2s infinite ease-in-out;transform: rotate(45deg); + i {position:absolute;display:block;width:100%;height:100%;animation: circle2 2s infinite ease-in-out;transform: rotate(45deg);opacity:.5; &::before {display:block;width:8px;height:8px;background:nth($ct, 3);border-radius:50%;content:""} @@ -165,11 +156,11 @@ } /* 矩阵 */ - &.style-4 { + &.style-4 {width:60px;height:60px; - .dot-box{width:90%;height:90%;margin:5%; + .dot-box{ - i {float:left;display:block;width:30px;height:30px;background:nth($ct, 3);animation: grid 1.5s infinite linear; + i {float:left;display:block;width:20px;height:20px;background:nth($ct, 3);animation: grid 1.5s infinite linear; &:nth-child(4), &:nth-child(8) {animation-delay:.2s;} @@ -189,6 +180,9 @@ } + + + &.mask {position:fixed;z-index:65534;left:0;top:0;width:100%;height:100%;background:transparent; &.shift {transition: all .5s ease-out;} @@ -199,7 +193,7 @@ /* 指令式的tips */ -.do-layer__tips {visibility:hidden;position:fixed;z-index:65534;min-width:75px;max-width:600px;padding:10px;line-height:1.5;border-radius:3px;font-size:14px;color:#fff;background:rgba(0,0,0,.5); +.do-layer__tips {visibility:hidden;position:absolute;z-index:65534;min-width:75px;max-width:600px;padding:10px;line-height:1.5;border-radius:3px;font-size:14px;color:#fff;background:rgba(0,0,0,.5); i.arrow {position:absolute;width:0;height:0;border:6px solid transparent;content: ""} i.offset-top {left:5px;bottom:-14px;border-top:8px solid rgba(0,0,0,.5);} @@ -217,12 +211,12 @@ } @keyframes circle2 { - 70%,to {transform: rotate(405deg);} + 70%,to {transform: rotate(405deg);opacity:1} } @keyframes bounce { - 25% {transform: scaleY(1.3);} + 25% {transform: scaleY(1);} 50% {transform: scaleY(.6);} } diff --git a/src/layer/index.js b/src/layer/index.js index 68c7ca2..6fd9bda 100644 --- a/src/layer/index.js +++ b/src/layer/index.js @@ -12,6 +12,8 @@ import 'css/layer-normal.scss' Anot.ui.layer = '1.0.0-normal' +const log = console.log + const LANGUAGES = { en: { TITLE: 'Dialog', @@ -54,8 +56,8 @@ let defconf = { menubar: true, // 是否显示菜单栏 content: '', // 弹窗的内容 fixed: false, // 是否固定不可拖拽 - shift: 'cc', // 弹窗出来的初始位置,用于出场动画 - offset: [], // 弹窗出来后的坐标, 为数组,可有4个值,依次是 上右下左 + shift: {}, // 弹窗出来的初始位置,用于出场动画 + offset: {}, // 弹窗出来后的坐标, 为数组,可有4个值,依次是 上右下左 btns: [lang.YES_BTN, lang.NO_BTN] // 弹窗的2个按钮的文字 } const $doc = Anot(document) @@ -94,21 +96,17 @@ const close = function(id) { document.body.style.overflow = '' } -const repeat = function(str, num) { - let idx = 0 - let result = '' - while (idx < num) { - result += str - idx++ - } - return result -} -const fixOffset = function(val) { - if (!val && val !== 0) { - return 'auto' - } else { - return val +const fixOffset = function(offset) { + for (let i in offset) { + if (offset[i] === 'auto' || (!offset[i] && offset[i] !== 0)) { + delete offset[i] + } else { + if (isFinite(offset[i])) { + offset[i] += 'px' + } + } } + return offset } /* type: { // 弹窗类型对应的id值 @@ -223,19 +221,13 @@ class __layer__ { this.init.methods.autoSize = function() { let { layer, frame } = this.$refs frame.onload = function() { - setTimeout(function() { - try { - let $body = frame.contentWindow.document.body - let { clientWidth, clientHeight } = $body - Anot(layer).css({ - width: clientWidth, - height: clientHeight, - marginLeft: -clientWidth / 2, - marginTop: -clientHeight / 2 - }) - Anot(frame).css({ height: clientHeight }) - } catch (err) {} - }, 500) + try { + let $body = frame.contentWindow.document.body + let { clientWidth, clientHeight } = $body + + layer.style.cssText += `width: ${clientWidth}px;height: ${clientHeight}px;` + frame.style.cssText += `height: ${clientHeight}px;` + } catch (err) {} } } } @@ -269,9 +261,8 @@ class __layer__ { layBox.classList.add(state.extraClass) delete state.extraClass } - if (typeof state.shift === 'string') { - layBox.classList.add('__' + state.shift) - } else { + if (state.shift) { + fixOffset(state.shift) for (let k in state.shift) { let val = state.shift[k] val += isFinite(val) ? 'px' : '' @@ -332,10 +323,9 @@ class __layer__ { return `
- ${repeat( - style === 1 ? '' : '', - this.dot[style] - )} + ${(style === 1 ? '' : '').repeat( + this.dot[style] + )}
` @@ -421,11 +411,13 @@ class __layer__ { setTimeout(function() { let style = { background: state.background } - let css = getComputedStyle(layerDom[$id][1]) + + let $dom1 = Anot(layerDom[$id][1]) // tips类型, 弹层的定位要在指定的容器上 if (state.type === 5) { - // only type[tips] can define `color` + let css = getComputedStyle(layerDom[$id][1]) + // 只有tips类型可以定义 `color` style.color = state.color style.opacity = 1 let $container = Anot(container) @@ -463,7 +455,7 @@ class __layer__ { } $arrow.classList.add('offset-' + arrowOffset.join('-')) - Anot(layerDom[$id][1]).css(tmpStyle) + $dom1.css(tmpStyle) }) $container.bind('mouseleave', () => { setTimeout(() => { @@ -477,37 +469,19 @@ class __layer__ { } else { let offsetStyle = { opacity: 1 } if (state.offset) { - offsetStyle.top = fixOffset(state.offset[0]) - offsetStyle.right = fixOffset(state.offset[1]) - offsetStyle.bottom = fixOffset(state.offset[2]) - offsetStyle.left = fixOffset(state.offset[3]) - //左右都为auto时,改为居中 - if (offsetStyle.left === 'auto' && offsetStyle.right === 'auto') { - offsetStyle.left = '50%' - style.marginLeft = -parseInt(css.width) / 2 - } - //上下都为auto时,同样改为居中 - if (offsetStyle.top === 'auto' && offsetStyle.bottom === 'auto') { - offsetStyle.top = '50%' - style.marginTop = -parseInt(css.height) / 2 - } - } else { - style = Object.assign(style, { - marginLeft: -parseInt(css.width) / 2, - marginTop: -parseInt(css.height) / 2 - }) - } - Anot(layerDom[$id][1]).css(style) + fixOffset(state.offset) + Object.assign(offsetStyle, state.offset) + } + $dom1.css(style) setTimeout(() => { document.body.style.overflow = 'hidden' layerDom[$id][1].classList.add('shift') setTimeout(_ => { - Anot(layerDom[$id][1]).css(offsetStyle) + $dom1.css(offsetStyle) setTimeout(_ => { try { layerDom[$id][1].classList.remove('shift') - layerDom[$id][1].classList.remove('__' + state.shift) } catch (err) {} }, 500) }, 50) @@ -610,9 +584,9 @@ const _layer = { menubar: false, mask: false, type: 7, - shift: 'tc', + shift: { top: 0 }, timeout, - offset: [50, 'auto'], + offset: { top: 50 }, fixed: true, toast: true // toast模式 } @@ -641,7 +615,6 @@ const _layer = { yes: cb, menubar: false, background: 'none', - shift: 'ct', fixed: true }) }, @@ -729,7 +702,6 @@ Anot.directive('layer', { }, update: function(val) { if (!val) { - console.error(this) return console.error( `SyntaxError: Unexpected [${this.name}=${this.expr}]` ) @@ -743,9 +715,14 @@ Anot.directive('layer', { if (state.hasOwnProperty('area')) { state.area = state.area.split(',') } - if (state.hasOwnProperty('offset')) { - state.offset = state.offset.split(',') + if (state.hasOwnProperty('shift')) { + state.shift = fixOffset(new Function(`return ${state.shift}`)()) } + + if (state.hasOwnProperty('offset')) { + state.offset = fixOffset(new Function(`return ${state.offset}`)()) + } + if (state.hasOwnProperty('btns')) { state.btns = state.btns.split(',') } @@ -772,14 +749,23 @@ Anot.directive('layer', { let tips = document.createElement('div') let cont = document.createElement('span') let arrow = document.createElement('i') + let $container = Anot(this.element) + let { position } = getComputedStyle(this.element) + tips.className = 'do-layer__tips' cont.className = 'layer-content' arrow.className = 'arrow' cont.textContent = val tips.appendChild(cont) tips.appendChild(arrow) + + if (position === 'static') { + this.element.style.position = 'relative' + } this.element.appendChild(tips) + let style = {} + if (state.color) { style.color = state.color } @@ -787,39 +773,39 @@ Anot.directive('layer', { style.background = state.background } - let style = {} - let css = getComputedStyle(tips) - let $container = Anot(this.element) let cw = $container.innerWidth() let ch = $container.innerHeight() - let ol = $container.offset().left - $doc.scrollLeft() - let ot = $container.offset().top - $doc.scrollTop() - let layw = parseInt(css.width) - let layh = parseInt(css.height) let arrowOffset = ['top'] + // log(tips, layw, layh) Anot(tips).css(style) $container.bind('mouseenter', ev => { let tmpStyle = { visibility: 'visible' } - ol = $container.offset().left - $doc.scrollLeft() - ot = $container.offset().top - $doc.scrollTop() + let layw = tips.clientWidth + let layh = tips.clientHeight + let { left, top } = $container.offset() + let ol = left - $doc.scrollLeft() + let ot = top - $doc.scrollTop() - if (ot + 18 < layh) { + // 判断位置是以确定出现 在上还是在下 + if (ot < layh + 8) { arrowOffset[0] = 'bottom' arrow.style.borderBottomColor = state.background - tmpStyle.top = ot + ch + 8 + tmpStyle.bottom = '' + tmpStyle.top = ch + 8 } else { arrow.style.borderTopColor = state.background - tmpStyle.top = ot - layh - 8 + tmpStyle.top = '' + tmpStyle.bottom = ch + 8 } if (ol + cw * 0.7 + layw > window.innerWidth) { - tmpStyle.left = ol + cw * 0.3 - layw + tmpStyle.left = cw * 0.3 - layw arrowOffset[1] = 'left' } else { - tmpStyle.left = ol + cw * 0.7 + tmpStyle.left = cw * 0.7 } arrow.classList.add('offset-' + arrowOffset.join('-'))