start iframe

This commit is contained in:
hufeixiong
2021-07-17 22:15:30 +08:00
parent 4808062d79
commit f1a3d98bcb
17 changed files with 825 additions and 11 deletions

View File

@@ -2,7 +2,7 @@
* @Author: yehuozhili * @Author: yehuozhili
* @Date: 2021-07-07 11:11:52 * @Date: 2021-07-07 11:11:52
* @LastEditors: yehuozhili * @LastEditors: yehuozhili
* @LastEditTime: 2021-07-12 13:58:33 * @LastEditTime: 2021-07-17 10:15:46
* @FilePath: \dooringx\packages\dooringx-example\.umirc.ts * @FilePath: \dooringx\packages\dooringx-example\.umirc.ts
*/ */
import { defineConfig } from 'umi'; import { defineConfig } from 'umi';
@@ -26,6 +26,8 @@ export default defineConfig({
component: '@/layouts/index', component: '@/layouts/index',
routes: [ routes: [
{ path: '/', component: '@/pages/index' }, { path: '/', component: '@/pages/index' },
{ path: '/iframeTest', component: '@/pages/iframeTest' },
{ path: '/container', component: '@/pages/container' },
{ path: '/preview', component: '@/pages/preview' }, { path: '/preview', component: '@/pages/preview' },
{ path: '/iframe', component: '@/pages/iframe' }, { path: '/iframe', component: '@/pages/iframe' },
], ],

View File

@@ -0,0 +1,22 @@
/*
* @Author: yehuozhili
* @Date: 2021-07-16 20:55:50
* @LastEditors: yehuozhili
* @LastEditTime: 2021-07-17 14:02:12
* @FilePath: \dooringx\packages\dooringx-example\src\pages\container\index.tsx
*/
import { configContext } from '@/layouts';
import { useContext } from 'react';
import { IframeContainer } from '../../../../dooringx-lib/dist';
function ContainerPage() {
const config = useContext(configContext);
return (
<div>
<IframeContainer config={config} context="edit"></IframeContainer>
</div>
);
}
export default ContainerPage;

View File

@@ -0,0 +1,125 @@
/*
* @Author: yehuozhili
* @Date: 2021-07-17 10:12:11
* @LastEditors: yehuozhili
* @LastEditTime: 2021-07-17 22:13:20
* @FilePath: \dooringx\packages\dooringx-example\src\pages\iframeTest.tsx
*/
import {
RightConfig,
Container,
useStoreState,
innerContainerDragUp,
LeftConfig,
IframeContainerWrapper,
Control,
postMessage,
useIframePostMessage,
} from 'dooringx-lib';
import { useContext, useState } from 'react';
import { configContext } from '@/layouts';
import { useCallback } from 'react';
import { PREVIEWSTATE } from '@/constant';
import { useEffect } from 'react';
export const HeaderHeight = '40px';
export default function IndexPage() {
const config = useContext(configContext);
const everyFn = () => {};
const subscribeFn = useCallback(() => {
localStorage.setItem(PREVIEWSTATE, JSON.stringify(config.getStore().getData()));
}, [config]);
const [state] = useStoreState(config, subscribeFn, everyFn);
const [iframeReady, setIframeReady] = useState(false);
const [fnx] = useIframePostMessage(`${location.origin}/container`, config, iframeReady);
useEffect(() => {
const fn = (e: MessageEvent<any>) => {
console.log(e, '收到');
if (e.data === 'ready') {
setIframeReady(true);
fnx();
}
if (typeof e.data === 'object') {
if (e.data.type === 'update') {
if (e.data.column === 'scale') {
config.scaleState = e.data.data;
config.getStore().forceUpdate();
config.refreshIframe();
}
}
}
};
window.addEventListener('message', fn);
return () => {
window.removeEventListener('message', fn);
};
}, []);
const scaleState = config.getScaleState();
return (
<div {...innerContainerDragUp(config, 'iframe')}>
<div style={{ height: HeaderHeight }}>
head
<button
onClick={() => {
window.open('/iframe');
}}
>
go preview
</button>
<button
onClick={() => {
window.open('/preview');
}}
>
go preview
</button>
</div>
<div
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: `calc(100vh - ${HeaderHeight})`,
width: '100vw',
}}
>
<div style={{ height: '100%' }}>
<LeftConfig config={config}></LeftConfig>
</div>
<IframeContainerWrapper
config={config}
extra={
<Control
config={config}
style={{ position: 'fixed', bottom: '60px', right: '450px', zIndex: 100 }}
></Control>
}
>
<>
<iframe
id="yh-container-iframe"
style={{
width: state.container.width * scaleState.value,
height: state.container.height * scaleState.value + 1,
border: 'none',
userSelect: 'none',
}}
src="/container"
></iframe>
</>
</IframeContainerWrapper>
<div className="rightrender" style={{ height: '100%' }}>
<RightConfig state={state} config={config}></RightConfig>
</div>
</div>
</div>
);
}

View File

@@ -2,7 +2,7 @@
* @Author: yehuozhili * @Author: yehuozhili
* @Date: 2021-05-15 12:49:28 * @Date: 2021-05-15 12:49:28
* @LastEditors: yehuozhili * @LastEditors: yehuozhili
* @LastEditTime: 2021-07-12 20:19:38 * @LastEditTime: 2021-07-17 10:12:53
* @FilePath: \dooringx\packages\dooringx-example\src\pages\index.tsx * @FilePath: \dooringx\packages\dooringx-example\src\pages\index.tsx
*/ */
import { import {
@@ -13,6 +13,7 @@ import {
LeftConfig, LeftConfig,
ContainerWrapper, ContainerWrapper,
Control, Control,
postMessage,
} from 'dooringx-lib'; } from 'dooringx-lib';
import { useContext } from 'react'; import { useContext } from 'react';
import { configContext } from '@/layouts'; import { configContext } from '@/layouts';

View File

@@ -1,5 +1,5 @@
{ {
"version": "0.5.0", "version": "0.6.0",
"license": "MIT", "license": "MIT",
"main": "dist/index.js", "main": "dist/index.js",
"module": "dist/dooringx-lib.esm.js", "module": "dist/dooringx-lib.esm.js",

View File

@@ -0,0 +1,77 @@
/*
* @Author: yehuozhili
* @Date: 2021-02-21 22:17:29
* @LastEditors: yehuozhili
* @LastEditTime: 2021-07-17 11:24:59
* @FilePath: \dooringx\packages\dooringx-lib\src\components\IframeWrapperMove\event.ts
*/
import { RefObject } from 'react';
import { containerResizer } from '../../core/resizeHandler/containerResizer';
import { contextMenuState } from '../../core/contextMenu';
import UserConfig from '../../config';
export interface WrapperMoveStateProps {
isDrag: boolean;
startX: number;
startY: number;
needX: number;
needY: number;
}
export interface WrapperMoveRef {
ref: null | RefObject<HTMLDivElement>;
}
export const wrapperMoveState: WrapperMoveStateProps = {
isDrag: false,
startX: 0,
startY: 0,
needX: 0,
needY: 0,
};
export const wrapperRefState: WrapperMoveRef = {
ref: null,
};
export const wrapperEvent = (ref: RefObject<HTMLDivElement>, config: UserConfig) => {
const scale = config.getScaleState().value;
const store = config.getStore();
return {
onMouseDown: (e: React.MouseEvent) => {
// e.preventDefault();// 不能使用preventDefault 否则弹窗输入框焦点无法触发
contextMenuState.unmountContextMenu();
if (e.target !== ref.current) {
} else {
wrapperMoveState.isDrag = true;
wrapperMoveState.startX = e.clientX;
wrapperMoveState.startY = e.clientY;
if (ref.current) {
ref.current.style.cursor = 'grab';
wrapperRefState.ref = ref;
}
}
},
onMouseMove: (e: React.MouseEvent) => {
e.preventDefault();
if (wrapperMoveState.isDrag) {
const diffX = e.clientX - wrapperMoveState.startX;
const diffY = e.clientY - wrapperMoveState.startY;
wrapperMoveState.needX = wrapperMoveState.needX + diffX / scale;
wrapperMoveState.needY = wrapperMoveState.needY + diffY / scale;
wrapperMoveState.startX = e.clientX;
wrapperMoveState.startY = e.clientY;
store.forceUpdate();
}
containerResizer.onMouseMove(e, config);
},
};
};
export const wrapperMoveMouseUp = (config: UserConfig) => {
if (wrapperRefState.ref && wrapperRefState.ref.current) {
wrapperRefState.ref.current.style.cursor = 'default';
}
containerResizer.onMouseUp(config);
wrapperMoveState.isDrag = false;
};

View File

@@ -0,0 +1,86 @@
/*
* @Author: yehuozhili
* @Date: 2021-03-14 04:29:09
* @LastEditors: yehuozhili
* @LastEditTime: 2021-07-17 22:13:37
* @FilePath: \dooringx\packages\dooringx-lib\src\components\IframeWrapperMove\index.tsx
*/
import { AllHTMLAttributes, CSSProperties, PropsWithChildren, ReactNode, useRef } from 'react';
import { wrapperEvent } from './event';
import { onWheelEvent } from '../../core/scale';
import React from 'react';
import Ticker from './ticker';
import UserConfig from '../../config';
import { containerResizer } from '../../core/resizeHandler/containerResizer';
export interface ContainerWrapperProps extends AllHTMLAttributes<HTMLDivElement> {
config: UserConfig;
classNames?: string;
style?: CSSProperties;
extra?: ReactNode;
}
function ContainerWrapper(props: PropsWithChildren<ContainerWrapperProps>) {
const { children, style, classNames, config, extra, ...rest } = props;
const ref = useRef<HTMLDivElement>(null);
const ticker = props.config.ticker;
const wrapperMoveState = config.getWrapperMove().iframe;
const scaleState = config.getScaleState();
const state = props.config.getStore().getData();
return (
<div
className={`ant-menu ${classNames ? classNames : ''}`}
ref={ref}
style={{
backgroundColor: '#f0f0f0',
height: '100%',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
flex: 1,
flexDirection: 'column',
position: 'relative',
overflow: 'hidden',
...style,
}}
{...wrapperEvent(ref, props.config)}
{...onWheelEvent(props.config)}
{...rest}
>
<div
style={{
position: 'absolute',
transform: `scale(${scaleState.value}) translate(${wrapperMoveState.needX}px, ${wrapperMoveState.needY}px)`,
width: state.container.width * scaleState.value,
height: state.container.height * scaleState.value,
}}
>
{children}
<div
style={{
height: '50px',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
width: state.container.width * scaleState.value,
}}
>
<div
style={{
fontSize: '20px',
cursor: 's-resize',
}}
onMouseDown={(e) => containerResizer.onMousedown(e, props.config)}
>
{props.config.getConfig().containerIcon}
</div>
</div>
</div>
{extra && extra}
{ticker && <Ticker config={props.config}></Ticker>}
</div>
);
}
export default ContainerWrapper;

View File

@@ -0,0 +1,156 @@
/*
* @Author: yehuozhili
* @Date: 2021-07-12 15:54:35
* @LastEditors: yehuozhili
* @LastEditTime: 2021-07-13 21:07:22
* @FilePath: \dooringx\packages\dooringx-lib\src\components\wrapperMove\ticker.tsx
*/
import React, { useEffect, useRef, useState } from 'react';
import UserConfig from '../../config';
const width = '20px';
const indent = 50;
function Ticker(props: { config: UserConfig }) {
const topRef = useRef<HTMLDivElement>(null);
const leftRef = useRef<HTMLDivElement>(null);
const [topRender, setTopRender] = useState(0);
const [leftRender, setLeftRender] = useState(0);
const scale = props.config.getScaleState().value;
useEffect(() => {
const timer = setTimeout(() => {
if (topRef.current) {
const width = topRef.current.getBoundingClientRect().width;
const renderWidth = Math.ceil(width / 10 / scale);
setTopRender(renderWidth);
}
// left可以不用放但为了更新统一
if (leftRef.current) {
const height = leftRef.current.getBoundingClientRect().height;
const renderHeight = Math.ceil(height / 10 / scale);
setLeftRender(renderHeight);
}
}, 300);
return () => {
clearTimeout(timer);
};
}, [props.config, props.config.collapsed, scale]);
return (
<>
<div
ref={topRef}
style={{
position: 'absolute',
top: 0,
left: indent,
width: '100%',
height: width,
display: 'flex',
justifyContent: 'space-between',
userSelect: 'none',
}}
>
{Array(topRender)
.fill(1)
.map((_, i) => {
if (i % 10 === 0) {
return (
<div
key={i}
style={{
background: 'rgb(204, 204, 204)',
width: '1px',
height: '12px',
position: 'relative',
userSelect: 'none',
}}
>
<div
style={{
position: 'absolute',
top: '20px',
fontSize: '10px',
left: '-2px',
userSelect: 'none',
}}
>
{i}
</div>
</div>
);
} else {
return (
<div
key={i}
style={{ background: 'rgb(204, 204, 204)', width: '1px', height: '6px' }}
></div>
);
}
})}
</div>
<div
ref={leftRef}
style={{
position: 'absolute',
top: indent,
left: 0,
width: width,
height: '100%',
display: 'flex',
justifyContent: 'space-between',
flexDirection: 'column',
userSelect: 'none',
}}
>
{Array(leftRender)
.fill(1)
.map((_, i) => {
if (i % 10 === 0) {
return (
<div
key={i}
style={{
background: 'rgb(204, 204, 204)',
width: '12px',
height: '1px',
position: 'relative',
userSelect: 'none',
}}
>
<div
style={{
position: 'absolute',
left: '20px',
fontSize: '10px',
top: '-2px',
userSelect: 'none',
}}
>
{i}
</div>
</div>
);
} else {
return (
<div
key={i}
style={{
background: 'rgb(204, 204, 204)',
width: '6px',
height: '1px',
userSelect: 'none',
}}
></div>
);
}
})}
</div>
</>
);
}
export default Ticker;

View File

@@ -37,6 +37,7 @@ function Container(props: PropsWithChildren<ContainerProps>) {
return props.state.globalState.containerColor; return props.state.globalState.containerColor;
} }
}; };
return ( return (
<> <>
{props.context === 'edit' && ( {props.context === 'edit' && (

View File

@@ -0,0 +1,184 @@
/*
* @Author: yehuozhili
* @Date: 2021-07-17 10:08:08
* @LastEditors: yehuozhili
* @LastEditTime: 2021-07-17 22:13:51
* @FilePath: \dooringx\packages\dooringx-lib\src\components\iframeContainer.tsx
*/
import { containerDragResolve } from '../core/crossDrag';
import { containerFocusRemove } from '../core/focusHandler';
import { innerContainerDrag } from '../core/innerDrag';
import { NormalMarkLineRender } from '../core/markline';
import { IStoreData } from '../core/store/storetype';
import { wrapperMoveState } from './IframeWrapperMove/event';
import { CSSProperties, PropsWithChildren, useEffect, useMemo, useState } from 'react';
import Blocks from './blocks';
import React from 'react';
import UserConfig, { defaultStore } from '../config';
import styles from '../index.less';
import { getRealHeight } from '../core/transfer';
import { WrapperMoveStateProps } from './IframeWrapperMove/event';
import { onWheelEventIframe } from '../core/scale';
import { selectRangeMouseUp } from '../core/selectRange';
interface ContainerProps {
context: 'edit' | 'preview';
config: UserConfig;
editContainerStyle?: CSSProperties;
previewContainerStyle?: CSSProperties;
}
interface IframeInnerState {
store: IStoreData;
scaleState: {
value: number;
maxValue: number;
minValue: number;
};
isEdit: boolean;
origin: null | IStoreData[];
wrapperState: {
data: any;
iframe: WrapperMoveStateProps;
};
}
function Container(props: PropsWithChildren<ContainerProps>) {
const { editContainerStyle, previewContainerStyle } = props;
const [message, setMessage] = useState<IframeInnerState>({
store: defaultStore,
scaleState: {
value: 0,
maxValue: 0,
minValue: 0,
},
isEdit: false,
wrapperState: props.config.getWrapperMove(),
origin: null,
});
const state = message.store;
const scaleState = message.scaleState;
const isEdit = message.isEdit;
const bgColor = () => {
if (isEdit) {
return 'rgba(255,255,255,1)';
} else {
return state.globalState.containerColor;
}
};
const transform = useMemo(() => {
if (props.context === 'edit') {
return `scale(${scaleState.value}) translate(${wrapperMoveState.needX}px, ${wrapperMoveState.needY}px)`;
} else {
return undefined;
}
}, [props.context, scaleState.value]);
useEffect(() => {
const fn = (e: any) => {
console.log(e, 'ccccccccccccccc');
if (typeof e.data !== 'object') {
return;
}
if (!e.data.store) {
if (e.data.type === 'event') {
if (e.data.column === 'select') {
}
}
return;
}
const data: IframeInnerState = e.data;
console.log(data, 'kkkkkkkkkk', !e.data.store, e.data.store);
setMessage(data);
props.config.resetData([data.store]);
props.config.scaleState = data.scaleState;
};
window.addEventListener('message', fn);
window.parent.postMessage('ready', '*');
return () => {
window.removeEventListener('message', fn);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (
<>
{props.context === 'edit' && (
<>
<div
style={{ display: 'flex' }}
onMouseUp={(e) => {
selectRangeMouseUp(e, props.config);
// props.config.sendParent({
// type: 'event',
// column: 'select',
// data: null,
// });
}}
onMouseLeave={(e) => {
selectRangeMouseUp(e, props.config);
}}
{...onWheelEventIframe(props.config, scaleState)}
>
<div
id="yh-container"
className={styles.yh_container}
style={{
height: `${state.container.height * scaleState.value}px`,
width: `${state.container.width * scaleState.value}px`,
backgroundColor: bgColor(),
position: 'relative',
overflow: 'hidden',
...editContainerStyle,
}}
{...(props.context === 'edit' ? containerDragResolve(props.config) : null)}
{...(props.context === 'edit' ? innerContainerDrag(props.config) : null)}
{...(props.context === 'edit' ? containerFocusRemove(props.config) : null)}
>
{props.context === 'edit' && (
<NormalMarkLineRender config={props.config}></NormalMarkLineRender>
)}
{state.block.map((v) => {
return (
<Blocks
config={props.config}
key={v.id}
data={v}
context={props.context}
></Blocks>
);
})}
</div>
</div>
</>
)}
{props.context === 'preview' && (
<div
id="yh-container-preview"
className={styles.yh_container_preview}
style={{
height: `${getRealHeight(state.container.height)}px`,
width: `100%`,
position: 'relative' as 'absolute' | 'relative',
overflow: 'hidden',
backgroundColor: bgColor(),
transform: transform,
...previewContainerStyle,
}}
>
{state.block.map((v) => {
return (
<Blocks key={v.id} config={props.config} data={v} context={props.context}></Blocks>
);
})}
</div>
)}
</>
);
}
export default Container;

View File

@@ -2,7 +2,7 @@
* @Author: yehuozhili * @Author: yehuozhili
* @Date: 2021-02-25 21:16:58 * @Date: 2021-02-25 21:16:58
* @LastEditors: yehuozhili * @LastEditors: yehuozhili
* @LastEditTime: 2021-07-16 20:22:47 * @LastEditTime: 2021-07-17 20:57:16
* @FilePath: \dooringx\packages\dooringx-lib\src\config\index.tsx * @FilePath: \dooringx\packages\dooringx-lib\src\config\index.tsx
*/ */
import React from 'react'; import React from 'react';
@@ -31,7 +31,8 @@ import ComponentRegister from '../core/components';
import { StoreChanger } from '../core/storeChanger'; import { StoreChanger } from '../core/storeChanger';
import Store from '../core/store'; import Store from '../core/store';
import { VerticalAlignMiddleOutlined } from '@ant-design/icons'; import { VerticalAlignMiddleOutlined } from '@ant-design/icons';
import { wrapperMoveState } from '../components/wrapperMove/event';
import { wrapperMoveState as iframeWrapperMoveState } from '../components/IframeWrapperMove/event';
// 组件部分 // 组件部分
/** /**
@@ -344,6 +345,14 @@ export class UserConfig {
public focusState = focusState; public focusState = focusState;
public collapsed = false; public collapsed = false;
public ticker = true; public ticker = true;
public wrapperMoveState = wrapperMoveState;
public iframeWrapperMoveState = iframeWrapperMoveState;
public refreshIframe = () => {};
public sendParent = (message: any) => {
window.parent.postMessage(message, '*');
};
public iframeOrigin = '';
public iframeId = 'yh-container-iframe';
constructor(initConfig?: Partial<InitConfig>) { constructor(initConfig?: Partial<InitConfig>) {
const mergeConfig = userConfigMerge(defaultConfig, initConfig); const mergeConfig = userConfigMerge(defaultConfig, initConfig);
this.initConfig = mergeConfig; this.initConfig = mergeConfig;
@@ -410,6 +419,13 @@ export class UserConfig {
this.toRegist(); this.toRegist();
} }
getWrapperMove() {
return {
data: this.wrapperMoveState,
iframe: this.iframeWrapperMoveState,
};
}
getFocusState() { getFocusState() {
return this.focusState; return this.focusState;
} }

View File

@@ -6,6 +6,7 @@ import { selectRangeMouseMove, selectData, selectRangeMouseUp } from '../selectR
import { IBlockType } from '../store/storetype'; import { IBlockType } from '../store/storetype';
import { deepCopy, isMac } from '../utils'; import { deepCopy, isMac } from '../utils';
import { wrapperMoveMouseUp } from '../../components/wrapperMove/event'; import { wrapperMoveMouseUp } from '../../components/wrapperMove/event';
import { wrapperMoveMouseUp as iframeWrapperMove } from '../../components/IframeWrapperMove/event';
import { contextMenuState } from '../contextMenu'; import { contextMenuState } from '../contextMenu';
import { innerDragState } from './state'; import { innerDragState } from './state';
import UserConfig from '../../config'; import UserConfig from '../../config';
@@ -102,12 +103,15 @@ export const innerContainerDrag = function (config: UserConfig) {
onMouseMove, onMouseMove,
}; };
}; };
export const innerContainerDragUp = function (config: UserConfig) { export const innerContainerDragUp = function (config: UserConfig, mode = 'normal') {
const store = config.getStore(); const store = config.getStore();
const onMouseUp = (e: React.MouseEvent) => { const onMouseUp = (e: React.MouseEvent) => {
e.preventDefault(); e.preventDefault();
iframeWrapperMove(config);
wrapperMoveMouseUp(config); wrapperMoveMouseUp(config);
selectRangeMouseUp(e, config); selectRangeMouseUp(e, config);
if (mode !== 'normal') {
}
if (innerDragState.ref && innerDragState.ref.current) { if (innerDragState.ref && innerDragState.ref.current) {
innerDragState.ref.current.style.cursor = 'default'; innerDragState.ref.current.style.cursor = 'default';
innerDragState.ref.current.style.willChange = 'auto'; innerDragState.ref.current.style.willChange = 'auto';

View File

@@ -2,7 +2,7 @@
* @Author: yehuozhili * @Author: yehuozhili
* @Date: 2021-03-14 04:29:09 * @Date: 2021-03-14 04:29:09
* @LastEditors: yehuozhili * @LastEditors: yehuozhili
* @LastEditTime: 2021-07-12 20:04:17 * @LastEditTime: 2021-07-17 17:05:13
* @FilePath: \dooringx\packages\dooringx-lib\src\core\scale\index.ts * @FilePath: \dooringx\packages\dooringx-lib\src\core\scale\index.ts
*/ */
import UserConfig from '../../config'; import UserConfig from '../../config';
@@ -23,6 +23,7 @@ export const onWheelEvent = (config: UserConfig) => {
if (scale.value < scale.maxValue) { if (scale.value < scale.maxValue) {
scale.value = scale.value + 0.1; scale.value = scale.value + 0.1;
store.forceUpdate(); store.forceUpdate();
config.refreshIframe();
} }
} else { } else {
scaleCancelFn(); scaleCancelFn();
@@ -30,6 +31,7 @@ export const onWheelEvent = (config: UserConfig) => {
if (scale.value > scale.minValue) { if (scale.value > scale.minValue) {
scale.value = scale.value - 0.1; scale.value = scale.value - 0.1;
store.forceUpdate(); store.forceUpdate();
config.refreshIframe();
} }
} }
}, },
@@ -44,6 +46,7 @@ export const scaleFn = {
scaleCancelFn(); scaleCancelFn();
scaleState.value = scaleState.value + number; scaleState.value = scaleState.value + number;
store.forceUpdate(); store.forceUpdate();
config.refreshIframe();
} }
return scaleState.value; return scaleState.value;
}, },
@@ -54,7 +57,49 @@ export const scaleFn = {
if (scaleState.value > scaleState.minValue) { if (scaleState.value > scaleState.minValue) {
scaleState.value = scaleState.value - number; scaleState.value = scaleState.value - number;
store.forceUpdate(); store.forceUpdate();
config.refreshIframe();
} }
return scaleState.value; return scaleState.value;
}, },
}; };
export const onWheelEventIframe = (
config: UserConfig,
scale: {
value: number;
maxValue: number;
minValue: number;
}
) => {
return {
onWheel: (e: React.WheelEvent<HTMLDivElement>) => {
const dom = document.querySelector('.ant-modal-mask');
if (dom) {
//出现弹窗禁止滚动
return;
}
if (e.deltaY > 0) {
scaleCancelFn();
if (scale.value < scale.maxValue) {
scale.value = scale.value + 0.1;
config.sendParent({
type: 'update',
column: 'scale',
data: scale,
});
}
} else {
scaleCancelFn();
//往上滚缩小
if (scale.value > scale.minValue) {
scale.value = scale.value - 0.1;
config.sendParent({
type: 'update',
column: 'scale',
data: scale,
});
}
}
},
};
};

View File

@@ -1,5 +1,5 @@
import { IStoreData } from '../store/storetype'; import { IStoreData } from '../store/storetype';
import { deepCopy } from '../utils'; import { deepCopy, postMessage } from '../utils';
import style from '../../index.less'; import style from '../../index.less';
import UserConfig from '../../config'; import UserConfig from '../../config';
export interface SelectDataProps { export interface SelectDataProps {
@@ -99,3 +99,32 @@ export function selectRangeMouseUp(e: React.MouseEvent | MouseEvent, config: Use
selectData.selectDiv = null; selectData.selectDiv = null;
} }
} }
export function iframeSelectRangeMouseUp(config: UserConfig) {
postMessage(
{
type: 'event',
column: 'select',
data: null,
},
config.iframeOrigin,
config.iframeId
);
}
export function forceRangeMouseLeave(config: UserConfig) {
if (selectData.selectDiv) {
let left = 0;
let top = 0;
const scaleState = config.getScaleState();
const { width, height } = selectData.selectDiv.getBoundingClientRect();
const scale = scaleState.value;
const wwidth = width / scale;
const wheight = height / scale;
left = selectData.startX;
top = selectData.startY;
selectFocus(left, top, wwidth, wheight, config);
selectData.selectDiv.parentNode!.removeChild(selectData.selectDiv);
selectData.selectDiv = null;
}
}

View File

@@ -279,3 +279,12 @@ export const changeUserValueRecord = (
return {}; return {};
} }
}; };
export function postMessage(value: any, src: string, target = 'yh-container-iframe') {
const iframe = document.querySelector(`#${target}`) as HTMLIFrameElement;
if (iframe) {
iframe.contentWindow?.postMessage(value, src);
} else {
console.warn('can not find iframe');
}
}

View File

@@ -2,13 +2,14 @@
* @Author: yehuozhili * @Author: yehuozhili
* @Date: 2021-03-14 05:35:15 * @Date: 2021-03-14 05:35:15
* @LastEditors: yehuozhili * @LastEditors: yehuozhili
* @LastEditTime: 2021-07-12 15:52:06 * @LastEditTime: 2021-07-17 20:59:26
* @FilePath: \dooringx\packages\dooringx-lib\src\hooks\index.ts * @FilePath: \dooringx\packages\dooringx-lib\src\hooks\index.ts
*/ */
import { useEffect, useMemo, useState } from 'react'; import { useEffect, useMemo, useState } from 'react';
import UserConfig from '../config'; import UserConfig from '../config';
import { ComponentRenderConfigProps } from '../core/components/componentItem'; import { ComponentRenderConfigProps } from '../core/components/componentItem';
import { registCommandFn, unRegistCommandFn } from '../core/command/runtime'; import { registCommandFn, unRegistCommandFn } from '../core/command/runtime';
import { postMessage } from '../core/utils';
export function useStoreState( export function useStoreState(
config: UserConfig, config: UserConfig,
@@ -97,3 +98,55 @@ export function useDynamicAddEventCenter(
}, [displayName, eventCenter, eventName, props.data.eventMap, props.data.id, props.store]); }, [displayName, eventCenter, eventName, props.data.eventMap, props.data.id, props.store]);
return; return;
} }
/**
*
*
* @export
* @param {string} origin iframe地址
* @param {UserConfig} config
* @param {boolean} sign iframe onload
* @param {string} [target] iframeid 默认是yh-container-iframe
* @return {*}
*/
export function useIframePostMessage(
origin: string,
config: UserConfig,
sign: boolean,
target?: string
) {
const store = config.getStore();
const fn = useMemo(() => {
config.iframeId = target || config.iframeId;
config.iframeOrigin = origin;
return () => {
const data = {
store: store.getData(),
scaleState: config.getScaleState(),
origin: config.getStoreChanger().getOrigin(),
isEdit: config.getStoreChanger().isEdit(),
wrapperState: config.getWrapperMove().iframe,
};
postMessage(data, origin, target);
};
}, [config, origin, store, target]);
useEffect(() => {
let unRegister = () => {};
if (sign) {
config.refreshIframe = fn;
unRegister = store.subscribe(() => {
// dom等无法传递
// config由context带去传递store和必要state
fn();
});
}
return () => {
unRegister();
};
}, [config.refreshIframe, fn, sign, store]);
return [fn];
}

View File

@@ -2,7 +2,7 @@
* @Author: yehuozhili * @Author: yehuozhili
* @Date: 2021-03-14 04:22:18 * @Date: 2021-03-14 04:22:18
* @LastEditors: yehuozhili * @LastEditors: yehuozhili
* @LastEditTime: 2021-07-13 14:57:13 * @LastEditTime: 2021-07-17 16:38:22
* @FilePath: \dooringx\packages\dooringx-lib\src\index.tsx * @FilePath: \dooringx\packages\dooringx-lib\src\index.tsx
*/ */
@@ -52,5 +52,9 @@ export { defaultStore } from './config';
//state //state
export { focusState } from './core/focusHandler/state'; export { focusState } from './core/focusHandler/state';
//utils //utils
export { deepCopy, rgba2Obj, swap, createUid, arrayMove } from './core/utils'; export { deepCopy, rgba2Obj, swap, createUid, arrayMove, postMessage } from './core/utils';
export { specialCoList } from './core/utils/special'; export { specialCoList } from './core/utils/special';
// iframe
export { default as IframeContainer } from './components/iframeContainer';
export { default as IframeContainerWrapper } from './components/IframeWrapperMove';
export { useIframePostMessage } from './hooks';