(#36) Merge mask modular & popup modular in popup layer modular.
This commit is contained in:
@@ -1,45 +0,0 @@
|
||||
@import "../../app.scss";
|
||||
|
||||
view.mask {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba($color: #000000, $alpha: .2);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
view.mask.block {
|
||||
display: block;
|
||||
}
|
||||
|
||||
view.mask.none {
|
||||
display: none;
|
||||
}
|
||||
|
||||
view.mask.show {
|
||||
animation: show .1s cubic-bezier(0, 0, 1, 1) both;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
view.mask.hide {
|
||||
animation: hide .1s cubic-bezier(0, 0, 1, 1) both;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
@keyframes show{
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hide{
|
||||
from {
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
import { Modular, Manager } from "../../core/Module";
|
||||
|
||||
/**
|
||||
* 蒙版事件
|
||||
*/
|
||||
type IMaskEvent = {
|
||||
|
||||
/**
|
||||
* 蒙版显示事件
|
||||
*/
|
||||
show: void;
|
||||
|
||||
/**
|
||||
* 蒙版隐藏事件
|
||||
*/
|
||||
hide: void;
|
||||
|
||||
/**
|
||||
* 蒙版状态改变事件
|
||||
*/
|
||||
change: boolean;
|
||||
|
||||
/**
|
||||
* 蒙版点击事件
|
||||
*/
|
||||
click: void;
|
||||
}
|
||||
|
||||
/**
|
||||
* 蒙版 Modular
|
||||
*/
|
||||
class Mask<M extends Manager> extends Modular<M, {}, IMaskEvent> {
|
||||
|
||||
/**
|
||||
* 动画运行时间
|
||||
*/
|
||||
public static readonly animateTime: number = 100;
|
||||
|
||||
public data? = {
|
||||
|
||||
/**
|
||||
* 蒙版的层级
|
||||
*/
|
||||
zIndex: 1,
|
||||
|
||||
/**
|
||||
* 蒙版是否显示
|
||||
*/
|
||||
isDisplay: false,
|
||||
|
||||
/**
|
||||
* 蒙版是否显示
|
||||
*/
|
||||
isShow: false
|
||||
};
|
||||
|
||||
/**
|
||||
* 当点击时是否自动关闭蒙版
|
||||
*/
|
||||
public autoCloseOnClick: boolean = true;
|
||||
|
||||
/**
|
||||
* 消失动画计时器
|
||||
*/
|
||||
private disappearTimer?: number;
|
||||
|
||||
public override onLoad() {
|
||||
this.setFunc(this.handleClickMask, "handleClickMask");
|
||||
this.on("show", this.showMask);
|
||||
this.on("hide", this.hideMask);
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示蒙版
|
||||
*/
|
||||
private showMask = () => {
|
||||
|
||||
this.disappearTimer && clearTimeout(this.disappearTimer);
|
||||
|
||||
this.setData({
|
||||
isShow: true,
|
||||
isDisplay: true
|
||||
});
|
||||
|
||||
this.emit("change", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏蒙版
|
||||
*/
|
||||
private hideMask = () => {
|
||||
this.setData({
|
||||
isShow: false
|
||||
});
|
||||
|
||||
this.disappearTimer = setTimeout(() => {
|
||||
this.setData({
|
||||
isDisplay: false
|
||||
});
|
||||
}, Mask.animateTime);
|
||||
|
||||
this.emit("change", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理蒙版点击事件
|
||||
*/
|
||||
private handleClickMask() {
|
||||
if (this.autoCloseOnClick) this.emit("hide");
|
||||
this.emit("click");
|
||||
}
|
||||
}
|
||||
|
||||
export { Mask };
|
||||
export default Mask;
|
||||
@@ -0,0 +1,99 @@
|
||||
@import "../app.scss";
|
||||
|
||||
view.mask {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba($color: #000000, $alpha: .2);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
view.layer {
|
||||
position: fixed;
|
||||
@include container;
|
||||
height: 100%;
|
||||
z-index: 2;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
view.occlude {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
view.mask.block, view.layer.block, view.occlude.block {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
view.mask.none, view.layer.none, view.occlude.none {
|
||||
display: none;
|
||||
}
|
||||
|
||||
view.mask.show-fade, view.layer.show-fade, view.occlude.show-fade {
|
||||
animation: show-fade .1s cubic-bezier(0, 0, 1, 1) both;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
view.mask.hide-fade, view.layer.hide-fade, view.occlude.hide-fade {
|
||||
animation: hide-fade .1s cubic-bezier(0, 0, 1, 1) both;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
view.mask.show-scale, view.layer.show-scale, view.occlude.show-scale {
|
||||
animation: show-scale .3s cubic-bezier(.1, .9, .2, 1) both,
|
||||
show-fade .1s cubic-bezier(0, 0, 1, 1) both;
|
||||
transform: scale3d(1, 1, 1);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
view.mask.hide-scale, view.layer.hide-scale, view.occlude.hide-scale {
|
||||
animation: hide-scale .3s cubic-bezier(.1, .9, .2, 1) both,
|
||||
hide-fade .1s cubic-bezier(0, 0, 1, 1) both;
|
||||
transform: scale3d(.9, .9, 1);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
view.mask {
|
||||
background-color: rgba($color: #000000, $alpha: .5);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes show-fade{
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hide-fade{
|
||||
from {
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes show-scale{
|
||||
from {
|
||||
transform: scale3d(1.15, 1.15, 1);
|
||||
}
|
||||
to {
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hide-scale{
|
||||
from {
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
to {
|
||||
transform: scale3d(.9, .9, 1);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
import { IAnyData } from "core/Api";
|
||||
import { Emitter } from "core/Emitter";
|
||||
import { Modular, Manager } from "../core/Module";
|
||||
|
||||
/**
|
||||
@@ -16,12 +18,12 @@ class DisplayLayer {
|
||||
public animateTime: number = 300;
|
||||
|
||||
/**
|
||||
* 蒙版是否显示
|
||||
* 是否显示
|
||||
*/
|
||||
public isDisplay: boolean = false;
|
||||
|
||||
/**
|
||||
* 蒙版是否显示
|
||||
* 是否显示
|
||||
*/
|
||||
public isShow: boolean = false;
|
||||
|
||||
@@ -57,28 +59,54 @@ type IPopupLayerEvent<L extends string> = {
|
||||
change: Readonly<DisplayLayer>;
|
||||
}
|
||||
|
||||
type commonLayerType = "mask" | "occlude";
|
||||
|
||||
/**
|
||||
* 弹出层
|
||||
*/
|
||||
class PopupLayer<
|
||||
L extends string,
|
||||
M extends Manager = Manager
|
||||
> extends Modular<M, {}, IPopupLayerEvent<L>> {
|
||||
> extends Modular<M, {}, IPopupLayerEvent<L | commonLayerType>> {
|
||||
|
||||
/**
|
||||
* 当点击时是否自动关闭蒙版
|
||||
*/
|
||||
public autoCloseOnClick: boolean = true;
|
||||
|
||||
/**
|
||||
* 关闭动画执行时是否屏蔽用户点击
|
||||
*/
|
||||
public showOccludeWhenHide: boolean = true;
|
||||
|
||||
/**
|
||||
* 显示 Layer 时自动关闭其他层
|
||||
*/
|
||||
public hideOtherWhenShow: boolean = true;
|
||||
|
||||
/**
|
||||
* 层列表
|
||||
*/
|
||||
private layers: Map<L, DisplayLayer> = new Map();
|
||||
private layers: Map<L | commonLayerType, DisplayLayer> = new Map();
|
||||
|
||||
public onLoad(): void {
|
||||
this.on("show", this.handleShowLayer);
|
||||
this.on("hide", this.handleHideLayer);
|
||||
this.setFunc(this.handleClickMask, "clickMask");
|
||||
|
||||
// 添加蒙版层
|
||||
const maskLayer = this.getDisplayLayer("mask");
|
||||
maskLayer.animateTime = 100;
|
||||
|
||||
// 添加遮蔽层
|
||||
const occludeLayer = this.getDisplayLayer("occlude");
|
||||
occludeLayer.animateTime = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取显示层
|
||||
*/
|
||||
private getDisplayLayer<K extends L>(e: K): DisplayLayer {
|
||||
private getDisplayLayer<K extends L | commonLayerType>(e: K): DisplayLayer {
|
||||
let displayLayer = this.layers.get(e);
|
||||
if (!displayLayer) {
|
||||
displayLayer = new DisplayLayer();
|
||||
@@ -88,16 +116,51 @@ class PopupLayer<
|
||||
return displayLayer;
|
||||
}
|
||||
|
||||
/**
|
||||
* 响应蒙版点击事件
|
||||
*/
|
||||
private handleClickMask = () => {
|
||||
|
||||
if (!this.autoCloseOnClick) return;
|
||||
|
||||
// 关闭全部开启的层
|
||||
this.layers.forEach((layer) => {
|
||||
if (layer.isShow) (this as Emitter<IAnyData>).emit("hide", layer.key);
|
||||
});
|
||||
|
||||
// 关闭蒙版
|
||||
(this as Emitter<IAnyData>).emit("hide", "mask");
|
||||
}
|
||||
|
||||
/**
|
||||
* 响应显示层事件
|
||||
*/
|
||||
private handleShowLayer = <K extends L>(e: K) => {
|
||||
private handleShowLayer = <K extends L | commonLayerType>(e: K) => {
|
||||
let displayLayer = this.getDisplayLayer(e);
|
||||
|
||||
// 阻止未发生的变化
|
||||
if (displayLayer.isShow) return;
|
||||
|
||||
// 关闭其他层
|
||||
if (e !== "mask" && e !== "occlude" && this.hideOtherWhenShow) {
|
||||
this.layers.forEach((layer) => {
|
||||
if (layer.key === "mask" || layer.key === "occlude") return;
|
||||
if (layer.isShow) {
|
||||
(this as Emitter<IAnyData>).emit("hide", layer.key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 显示蒙版
|
||||
if (e !== "mask" && e !== "occlude")
|
||||
(this as Emitter<IAnyData>).emit("show", "mask");
|
||||
|
||||
// 取消消失定时
|
||||
displayLayer.disappearTimer &&
|
||||
clearTimeout(displayLayer.disappearTimer);
|
||||
|
||||
displayLayer.isShow = true;
|
||||
displayLayer.isDisplay = true;
|
||||
this.setData({
|
||||
[`${ e }$isShow`]: true,
|
||||
[`${ e }$isDisplay`]: true
|
||||
@@ -109,18 +172,66 @@ class PopupLayer<
|
||||
/**
|
||||
* 响应隐藏层事件
|
||||
*/
|
||||
private handleHideLayer = <K extends L>(e: K) => {
|
||||
private handleHideLayer = <K extends L | commonLayerType>(e: K) => {
|
||||
let displayLayer = this.getDisplayLayer(e);
|
||||
|
||||
this.setData({
|
||||
[`${ e }$isShow`]: false
|
||||
});
|
||||
// 阻止未发生的变化
|
||||
if (!displayLayer.isShow) return;
|
||||
|
||||
displayLayer.disappearTimer = setTimeout(() => {
|
||||
if (displayLayer.animateTime <= 0) {
|
||||
|
||||
displayLayer.isShow = false;
|
||||
displayLayer.isDisplay = false;
|
||||
this.setData({
|
||||
[`${ e }$isShow`]: false,
|
||||
[`${ e }$isDisplay`]: false
|
||||
});
|
||||
}, displayLayer.animateTime);
|
||||
} else {
|
||||
|
||||
displayLayer.isShow = false;
|
||||
this.setData({
|
||||
[`${ e }$isShow`]: false
|
||||
});
|
||||
|
||||
// 开启遮蔽
|
||||
if (this.showOccludeWhenHide) {
|
||||
(this as Emitter<IAnyData>).emit("show", "occlude");
|
||||
}
|
||||
|
||||
displayLayer.disappearTimer = setTimeout(() => {
|
||||
displayLayer.isDisplay = false;
|
||||
this.setData({
|
||||
[`${ e }$isDisplay`]: false
|
||||
});
|
||||
|
||||
// 取消 timer
|
||||
displayLayer.disappearTimer = undefined;
|
||||
|
||||
// 检测是否关闭遮蔽
|
||||
let needOcclude = true;
|
||||
this.layers.forEach((layer) => {
|
||||
if (layer === displayLayer) return;
|
||||
if (layer.disappearTimer) needOcclude = false;
|
||||
});
|
||||
|
||||
// 关闭遮蔽
|
||||
if (needOcclude && this.showOccludeWhenHide) {
|
||||
(this as Emitter<IAnyData>).emit("hide", "occlude");
|
||||
}
|
||||
|
||||
}, displayLayer.animateTime);
|
||||
}
|
||||
|
||||
// 关闭蒙版
|
||||
if (e !== "mask" && e !== "occlude") {
|
||||
let needMask = true;
|
||||
this.layers.forEach((layer) => {
|
||||
if (layer === displayLayer) return;
|
||||
if (layer.isShow) needMask = false;
|
||||
});
|
||||
|
||||
if (needMask) (this as Emitter<IAnyData>).emit("hide", "mask");
|
||||
}
|
||||
|
||||
this.emit("change", displayLayer);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user