Add popup renderer
This commit is contained in:
parent
93e1a8d3ef
commit
90398b593e
@ -68,7 +68,13 @@ class CommandBar extends Component<ICommandBarProps & IMixinSettingProps & IMixi
|
|||||||
{this.getRenderButton({ iconName: "Camera", i18NKey: "Command.Bar.Camera.Info" })}
|
{this.getRenderButton({ iconName: "Camera", i18NKey: "Command.Bar.Camera.Info" })}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{this.getRenderButton({ iconName: "Settings", i18NKey: "Command.Bar.Setting.Info" })}
|
{this.getRenderButton({
|
||||||
|
iconName: "Settings",
|
||||||
|
i18NKey: "Command.Bar.Setting.Info",
|
||||||
|
click: () => {
|
||||||
|
this.props.status ? this.props.status.popup.showPopup() : undefined;
|
||||||
|
}
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
</Theme>
|
</Theme>
|
||||||
}
|
}
|
||||||
|
71
source/Component/Popup/Popup.scss
Normal file
71
source/Component/Popup/Popup.scss
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
@import "../Theme/Theme.scss";
|
||||||
|
|
||||||
|
@keyframes show-scale{
|
||||||
|
from {
|
||||||
|
transform: scale3d(1.15, 1.15, 1);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: scale3d(1, 1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes show-fade{
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
div.popup-mask.show-fade {
|
||||||
|
animation: show-fade .1s cubic-bezier(0, 0, 1, 1) both;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.popup-layer.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.popup-mask {
|
||||||
|
position: absolute;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.popup-layer {
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 3px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
div.popup-layer-header {
|
||||||
|
min-height: 32px;
|
||||||
|
max-height: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
div.popup-layer.dark {
|
||||||
|
|
||||||
|
div.popup-layer-header {
|
||||||
|
background-color: $lt-bg-color-lvl3-dark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
div.popup-layer.light {
|
||||||
|
|
||||||
|
div.popup-layer-header {
|
||||||
|
background-color: $lt-bg-color-lvl3-light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
div.dark.popup-mask {
|
||||||
|
background-color: rgba(0, 0, 0, 0.55);
|
||||||
|
}
|
||||||
|
|
||||||
|
div.light.popup-mask {
|
||||||
|
background-color: rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
97
source/Component/Popup/Popup.tsx
Normal file
97
source/Component/Popup/Popup.tsx
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
import { Component, ReactNode } from "react";
|
||||||
|
import { IMixinStatusProps, useStatusWithEvent } from "@Context/Status";
|
||||||
|
import { BackgroundLevel, Theme } from "@Component/Theme/Theme";
|
||||||
|
import { Popup as PopupModel } from "@Context/Popups";
|
||||||
|
import "./Popup.scss";
|
||||||
|
|
||||||
|
interface IPopupProps {}
|
||||||
|
|
||||||
|
@useStatusWithEvent("popupChange")
|
||||||
|
class Popup extends Component<IPopupProps & IMixinStatusProps> {
|
||||||
|
|
||||||
|
public renderMask(index?: number, click?: () => void, key?: string): ReactNode {
|
||||||
|
const classList: string[] = ["popup-mask", "show-fade"];
|
||||||
|
return <Theme
|
||||||
|
key={key}
|
||||||
|
onClick={click}
|
||||||
|
className={classList.join(" ")}
|
||||||
|
style={{
|
||||||
|
zIndex: index,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
|
public renderRootMask(): ReactNode {
|
||||||
|
if (this.props.status) {
|
||||||
|
const needMask = this.props.status.popup.popups.some(popup => popup.needMask);
|
||||||
|
if (!needMask) return null;
|
||||||
|
return this.renderMask(this.props.status.popup.zIndex,
|
||||||
|
() => {
|
||||||
|
this.props.status?.popup.popups.forEach(
|
||||||
|
popup => popup.onClose()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public renderMaskList(): ReactNode {
|
||||||
|
if (this.props.status) {
|
||||||
|
return this.props.status.popup.popups
|
||||||
|
.filter((popup) => {
|
||||||
|
return popup.needMask && popup.maskForSelf;
|
||||||
|
})
|
||||||
|
.filter((_, index) => {
|
||||||
|
if (index === 0) return false;
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.map((popup) => {
|
||||||
|
return this.renderMask(popup.zIndex() - 1,
|
||||||
|
() => {
|
||||||
|
popup.onClose();
|
||||||
|
}, popup.id
|
||||||
|
);
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public renderLayer(popup: PopupModel) {
|
||||||
|
const pageWidth = document.documentElement.clientWidth;
|
||||||
|
const pageHeight = document.documentElement.clientHeight;
|
||||||
|
const top = (pageHeight - popup.height) / 2;
|
||||||
|
const left = (pageWidth - popup.width) / 2;
|
||||||
|
|
||||||
|
return <Theme
|
||||||
|
style={{
|
||||||
|
width: popup.width,
|
||||||
|
height: popup.height,
|
||||||
|
zIndex: popup.zIndex(),
|
||||||
|
top: top,
|
||||||
|
left: left
|
||||||
|
}}
|
||||||
|
key={popup.id}
|
||||||
|
backgroundLevel={BackgroundLevel.Level4}
|
||||||
|
className="popup-layer show-scale"
|
||||||
|
>
|
||||||
|
<div className="popup-layer-header">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</Theme>
|
||||||
|
}
|
||||||
|
|
||||||
|
public render(): ReactNode {
|
||||||
|
return <>
|
||||||
|
{this.renderRootMask()}
|
||||||
|
{this.renderMaskList()}
|
||||||
|
{this.props.status?.popup.popups.map((popup) => {
|
||||||
|
return this.renderLayer(popup);
|
||||||
|
})}
|
||||||
|
</>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Popup };
|
@ -8,11 +8,33 @@ type IPopupConstructor = new (controller: PopupController, id: string) => Popup;
|
|||||||
*/
|
*/
|
||||||
class Popup {
|
class Popup {
|
||||||
|
|
||||||
|
public zIndex() {
|
||||||
|
return this.index * 2 + this.controller.zIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public width: number = 300;
|
||||||
|
|
||||||
|
public height: number = 200;
|
||||||
|
|
||||||
|
public top: number = 0;
|
||||||
|
|
||||||
|
public left: number = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否关闭
|
* 是否关闭
|
||||||
*/
|
*/
|
||||||
public isClose: boolean = false;
|
public isClose: boolean = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 需要蒙版
|
||||||
|
*/
|
||||||
|
public needMask: boolean = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单独遮挡下层的蒙版
|
||||||
|
*/
|
||||||
|
public maskForSelf: boolean = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 唯一标识符
|
* 唯一标识符
|
||||||
*/
|
*/
|
||||||
@ -43,7 +65,9 @@ class Popup {
|
|||||||
/**
|
/**
|
||||||
* 关闭回调
|
* 关闭回调
|
||||||
*/
|
*/
|
||||||
public onClose(): void {};
|
public onClose(): void {
|
||||||
|
this.close();
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 渲染节点
|
* 渲染节点
|
||||||
@ -77,6 +101,11 @@ class PopupController extends Emitter<IPopupControllerEvent> {
|
|||||||
*/
|
*/
|
||||||
private idIndex = 0;
|
private idIndex = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最小弹窗 Index
|
||||||
|
*/
|
||||||
|
public zIndex = 100;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 弹窗列表
|
* 弹窗列表
|
||||||
*/
|
*/
|
||||||
@ -121,7 +150,6 @@ class PopupController extends Emitter<IPopupControllerEvent> {
|
|||||||
if (isDelete) {
|
if (isDelete) {
|
||||||
closePopup = currentPopup;
|
closePopup = currentPopup;
|
||||||
currentPopup.isClose = true;
|
currentPopup.isClose = true;
|
||||||
currentPopup.onClose();
|
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
|
@ -9,6 +9,7 @@ import { initializeIcons } from '@fluentui/font-icons-mdl2';
|
|||||||
import { RootContainer } from "@Component/Container/RootContainer";
|
import { RootContainer } from "@Component/Container/RootContainer";
|
||||||
import { LayoutDirection } from "@Context/Layout";
|
import { LayoutDirection } from "@Context/Layout";
|
||||||
import { CommandBar } from "@Component/CommandBar/CommandBar";
|
import { CommandBar } from "@Component/CommandBar/CommandBar";
|
||||||
|
import { Popup } from "@Component/Popup/Popup";
|
||||||
import "./SimulatorWeb.scss";
|
import "./SimulatorWeb.scss";
|
||||||
|
|
||||||
initializeIcons("https://img.mrkbear.com/fabric-cdn-prod_20210407.001/");
|
initializeIcons("https://img.mrkbear.com/fabric-cdn-prod_20210407.001/");
|
||||||
@ -101,6 +102,7 @@ class SimulatorWeb extends Component {
|
|||||||
backgroundLevel={BackgroundLevel.Level5}
|
backgroundLevel={BackgroundLevel.Level5}
|
||||||
fontLevel={FontLevel.Level3}
|
fontLevel={FontLevel.Level3}
|
||||||
>
|
>
|
||||||
|
<Popup/>
|
||||||
<HeaderBar height={45}/>
|
<HeaderBar height={45}/>
|
||||||
<div className="app-root-space" style={{
|
<div className="app-root-space" style={{
|
||||||
height: `calc( 100% - ${45}px)`
|
height: `calc( 100% - ${45}px)`
|
||||||
|
Loading…
Reference in New Issue
Block a user