diff --git a/example/src/components/HelloWord.vue b/example/src/components/HelloWord.vue index 8c304839465354c7430288ee44f085a4efe603e3..9006c616efceafb4d573b061fcb8169abb111d77 100644 --- a/example/src/components/HelloWord.vue +++ b/example/src/components/HelloWord.vue @@ -1,24 +1,39 @@ - diff --git a/src/css/layer.css b/src/css/layer.css index ce7f6c1b4a1c6a8c5f3e7e6a00a9be2d219473de..ee0ff21734493acb9e67732c11c4c573a2d4718e 100644 --- a/src/css/layer.css +++ b/src/css/layer.css @@ -99,6 +99,284 @@ html #layuicss-layer { -webkit-animation-duration: .3s; animation-duration: .3s } +/* 抽屉开始 */ +/* right to left */ +@keyframes layer-rl { + from { + -webkit-transform: translate3d(100%, 0, 0); + -ms-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + opacity: 0; + + } + to { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +@-webkit-keyframes layer-rl { + from { + -webkit-transform: translate3d(100%, 0, 0); + -ms-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + opacity: 0; + + } + to { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +.layer-anim-rl { + -webkit-animation-name: layer-rl; + animation-name: layer-rl; + /* animation-timing-function:cubic-bezier(0.7, 0.3, 0.1, 1); */ +} + +/* right to left close */ +@keyframes layer-rl-close { + from { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + + } + to { + -webkit-transform: translate3d(100%, 0, 0); + -ms-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } +} + +@-webkit-keyframes layer-rl-close { + from { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + + } + to { + -webkit-transform: translate3d(100%, 0, 0); + -ms-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } +} + +.layer-anim-rl-close { + -webkit-animation-name: layer-rl-close; + animation-name: layer-rl-close; + /* animation-timing-function:cubic-bezier(0.7, 0.3, 0.1, 1); */ +} +/* left to right */ +@-webkit-keyframes layer-lr { + from { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 0 + } + to { + -webkit-transform: translate3d(-100%, 0, 0); + -ms-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + opacity: 1 + } +} + +@keyframes layer-lr { + from { + -webkit-transform: translate3d(-100%, 0, 0); + -ms-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + opacity: 0 + } + to { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1 + } +} +.layer-anim-lr { + -webkit-animation-name: layer-lr; + animation-name: layer-lr +} + +/* left to right close */ +@-webkit-keyframes layer-lr-close { + from { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + to { + -webkit-transform: translate3d(-100%, 0, 0); + -ms-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } +} + +@keyframes layer-lr-close { + from { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + to { + -webkit-transform: translate3d(-100%, 0, 0); + -ms-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } +} +.layer-anim-lr-close { + -webkit-animation-name: layer-lr-close; + animation-name: layer-lr-close +} + +/* top to bottom */ +@-webkit-keyframes layer-tb { + from { + -webkit-transform: translate3d(0, -100%, 0); + -ms-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + opacity: 0; + animation-timing-function:cubic-bezier(0.7, 0.3, 0.1, 1); + } + to { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + animation-timing-function:cubic-bezier(0.7, 0.3, 0.1, 1); + } +} + +@keyframes layer-tb { + from { + -webkit-transform: translate3d(0, -100%, 0); + -ms-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + opacity: 0; + animation-timing-function:cubic-bezier(0.7, 0.3, 0.1, 1); + } + to { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + animation-timing-function:cubic-bezier(0.7, 0.3, 0.1, 1); + } +} +.layer-anim-tb { + -webkit-animation-name: layer-tb; + animation-name: layer-tb +} + +/* top to bottom close */ +@-webkit-keyframes layer-tb-close { + from { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + to { + -webkit-transform: translate3d(0, -100%, 0); + -ms-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } +} + +@keyframes layer-tb-close { + from { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + to { + -webkit-transform: translate3d(0, -100%, 0); + -ms-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } +} +.layer-anim-tb-close { + -webkit-animation-name: layer-tb-close; + animation-name: layer-tb-close +} + +/* bottom to top */ +@-webkit-keyframes layer-bt { + from { + -webkit-transform: translate3d(0, 100%, 0); + -ms-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + opacity: 0 + } + to { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1 + } +} + +@keyframes layer-bt { + from { + -webkit-transform: translate3d(0, 100%, 0); + -ms-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + opacity: 0 + } + to { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1 + } +} +.layer-anim-bt { + -webkit-animation-name: layer-bt; + animation-name: layer-bt +} + +/* bottom to top close */ +@-webkit-keyframes layer-bt-close { + from { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + to { + -webkit-transform: translate3d(0, 100%, 0); + -ms-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } +} + +@keyframes layer-bt-close { + from { + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + + } + to { + -webkit-transform: translate3d(0, 100%, 0); + -ms-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + + } +} +.layer-anim-bt-close { + -webkit-animation-name: layer-bt-close; + animation-name: layer-bt-close +} +/* 抽屉结束 */ @-webkit-keyframes layer-bounceIn { 0% { diff --git a/src/layer/index.ts b/src/layer/index.ts index 592cd11cd5c4345902fee868fe7eceb840e5e71d..e7e0deff56597a420de6a9cb00e2877a9277ef2b 100644 --- a/src/layer/index.ts +++ b/src/layer/index.ts @@ -69,6 +69,13 @@ const layer = { let defaultOption = {}; return layer.create(option, defaultOption, callback); }, + // 抽屉 + drawer: (option: any, callback: Function) => { + let defaultOption = { + type:"drawer", + }; + return layer.create(option, defaultOption, callback); + }, // 消息框 msg: (message: string, option: any, callback: Function) => { let defaultOption = { diff --git a/src/module/modal/index.vue b/src/module/modal/index.vue index 820b0ff76a1c2a33d6ac4b46e83326783f914d3e..ed70cc0e3c1edf1aceca6dbe1a012cb2a6bd2219 100644 --- a/src/module/modal/index.vue +++ b/src/module/modal/index.vue @@ -20,6 +20,8 @@ import { minArea, minOffset, updateMinArrays, + getDrawerAnimationClass, + calculateDrawerArea, } from "../../tools"; import useMove from "../../tools/useMove"; @@ -43,7 +45,7 @@ export interface LayModalProps { btn?: Record[] | false; move?: boolean | string; resize?: boolean | string; - type?: 0 | 1 | 2 | 3 | "dialog" | "component" | "iframe" | "loading"; + type?: 0 | 1 | 2 | 3 | "dialog" | "component" | "iframe" | "loading" | "drawer"; content?: string | Function | object | VNodeTypes isHtmlFragment?: boolean; shade?: boolean | string; @@ -99,8 +101,8 @@ const id: Ref = ref(nextId()); const max: Ref = ref(false); const min: Ref = ref(false); const type: number = calculateType(props.type); -const area: Ref = ref(calculateArea(props.area)); -const offset: Ref = ref(calculateOffset(props.offset, area)); +const area: Ref = props.type != "drawer" ? ref(calculateArea(props.area)) : ref(calculateDrawerArea(props.offset, props.area)); +const offset: Ref = ref(calculateOffset(props.offset, area, props.type)); const contentHeight = ref(calculateContent(area.value[1], props.btn, type)); const index: Ref = ref(props.zIndex); const visible: Ref = ref(false); @@ -122,7 +124,7 @@ const _l: Ref = ref(offset.value[1]); const firstOpenDelayCalculation = function () { setTimeout(() => { area.value = getArea(layero.value); - offset.value = calculateOffset(props.offset, area.value); + offset.value = calculateOffset(props.offset, area.value, props.type); w.value = area.value[0]; h.value = area.value[1]; t.value = offset.value[0]; @@ -241,7 +243,7 @@ const setTopHandle = () => { // 拖拽支持 const supportMove = function () { - if (props.move) { + if (props.move && props.type != "drawer") { if (layero.value != null) { // @ts-ignore useMove(layero.value, (width, height, left, top) => { @@ -269,11 +271,17 @@ const styles = computed(() => { // 入场动画 const enterActiveClass = computed(() => { + if(props.type === "drawer"){ + return getDrawerAnimationClass(props.offset) + } return `layer-anim layer-anim-0${props.anim}`; }); // 出场动画 const leaveActiveClass = computed(() => { + if(props.type === "drawer"){ + return getDrawerAnimationClass(props.offset,true); + } return props.isOutAnim ? `layer-anim-close` : ""; }); diff --git a/src/tools/index.ts b/src/tools/index.ts index 39544b2d2c3ea0346b7e22acd815a41b6edf5e0e..971c4813760e71f741f4c6fbdcaed7bf489536c6 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -50,10 +50,13 @@ export function calculateArea(area: any) { // @param offset // @param domSize // @return 正确位置 -export function calculateOffset(offset: any, area: any) { +export function calculateOffset(offset: any, area: any, type: any) { var arr = ['t', 'r', 'b', 'l', 'lt', 'lb', 'rt', 'rb'] var t = offset[0]; var l = offset[1]; + if(offset instanceof Array && type === "drawer"){ + offset = 'r'; + } // @ts-ignore if (arr.indexOf(offset) > -1) { t = '50%'; @@ -80,7 +83,7 @@ export function calculateOffset(offset: any, area: any) { export function calculateType(modalType: number | string) { if(modalType === 'dialog' || modalType === 0 || modalType === '0'){ return 0; - }else if(modalType === 'component' || modalType === 1 || modalType === '1'){ + }else if(modalType === 'component' || modalType === 'drawer' || modalType === 1 || modalType === '1'){ return 1; }else if(modalType === 'iframe' || modalType === 2 || modalType === '2'){ return 2; @@ -171,4 +174,36 @@ export function updateMinArrays(id: string, state: Boolean) { i = -1; } return i; -} \ No newline at end of file +} + +// 抽屉动画类 +export function getDrawerAnimationClass(offset: any,isClose: boolean = false){ + const prefix = "layer-anim layer-anim"; + let suffix = "rl"; + if(offset === "l"){ + suffix = "lr"; + }else if(offset === "r"){ + suffix = "rl" + }else if(offset === "t"){ + suffix = "tb" + }else if(offset === "b"){ + suffix = "bt" + } + return isClose ? `${prefix}-${suffix}-close` : `${prefix}-${suffix}`; +} + +// 抽屉宽/高 +export function calculateDrawerArea(offset: any, drawerArea: string[] | string = "350px"){ + if(drawerArea instanceof Array){ + return drawerArea; + } + if(drawerArea === "auto"){ + drawerArea = "350px"; + } + if(offset === "l" || offset === "r"){ + return [drawerArea, "100%"]; + }else if(offset === "t" || offset === "b"){ + return ["100%", drawerArea]; + } + return [drawerArea,"100%"]; +}