wip reset animate

This commit is contained in:
hufeixiong
2022-01-26 18:04:46 +08:00
parent 83ec24ff7e
commit 5629f2755d
15 changed files with 105 additions and 29 deletions

View File

@@ -15,7 +15,7 @@ import {
Control, Control,
} from 'dooringx-lib'; } from 'dooringx-lib';
import { InsertRowBelowOutlined, UploadOutlined } from '@ant-design/icons'; import { InsertRowBelowOutlined, UploadOutlined } from '@ant-design/icons';
import { useContext, useState } from 'react'; import { useContext, useEffect, useState } from 'react';
import { configContext, LocaleContext } from '@/layouts'; import { configContext, LocaleContext } from '@/layouts';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { PREVIEWSTATE } from '@/constant'; import { PREVIEWSTATE } from '@/constant';

View File

@@ -243,20 +243,22 @@ function ActionButton(props: ActionButtonProps) {
<div> <div>
<Row <Row
style={{ style={{
padding: 20, padding: 10,
justifyContent: 'space-between', justifyContent: 'space-between',
alignItems: 'center', alignItems: 'center',
}} }}
> >
<Col span={8}>ID</Col> <Col span={8}>ID</Col>
<Col span={16}>{props.current.id}</Col> <Col span={16} style={{ textAlign: 'right' }}>
{props.current.id}
</Col>
</Row> </Row>
{currentOption.map((j, i) => { {currentOption.map((j, i) => {
return ( return (
<Row <Row
key={i} key={i}
style={{ style={{
padding: 20, padding: 10,
justifyContent: 'space-between', justifyContent: 'space-between',
alignItems: 'center', alignItems: 'center',
}} }}

View File

@@ -123,6 +123,7 @@ const timeFunction: Record<string, string> = {
let lastAnimate: AnimateItem[] = []; let lastAnimate: AnimateItem[] = [];
let isOmit = false; let isOmit = false;
const padding = 10;
function AnimateControl(props: AnimateControlProps) { function AnimateControl(props: AnimateControlProps) {
const store = props.config.getStore(); const store = props.config.getStore();
@@ -137,8 +138,8 @@ function AnimateControl(props: AnimateControlProps) {
<> <>
{animate.map((v, i) => { {animate.map((v, i) => {
return ( return (
<div key={v.uid}> <div key={v.uid} style={{ borderBottom: '1px dotted #9e9e9e' }}>
<Row style={{ padding: '20px', alignItems: 'center' }}> <Row style={{ padding: padding, alignItems: 'center' }}>
<Col span={5}>:</Col> <Col span={5}>:</Col>
<Col span={7}> <Col span={7}>
<Select <Select
@@ -193,7 +194,7 @@ function AnimateControl(props: AnimateControlProps) {
/> />
</Col> </Col>
</Row> </Row>
<Row style={{ padding: '20px', alignItems: 'center' }}> <Row style={{ padding: padding, alignItems: 'center' }}>
<Col span={5}>:</Col> <Col span={5}>:</Col>
<Col span={7}> <Col span={7}>
<InputNumber <InputNumber
@@ -248,7 +249,7 @@ function AnimateControl(props: AnimateControlProps) {
</Select> </Select>
</Col> </Col>
</Row> </Row>
<Row style={{ padding: '20px', alignItems: 'center' }}> <Row style={{ padding: padding, alignItems: 'center' }}>
<Col span={5}>:</Col> <Col span={5}>:</Col>
<Col span={7}> <Col span={7}>
<Select <Select
@@ -298,7 +299,7 @@ function AnimateControl(props: AnimateControlProps) {
); );
})} })}
<Row style={{ padding: '20px', justifyContent: 'space-around' }}> <Row style={{ padding: padding, justifyContent: 'space-around' }}>
{animate.length > 0 && ( {animate.length > 0 && (
<Button <Button
onClick={() => { onClick={() => {
@@ -325,6 +326,7 @@ function AnimateControl(props: AnimateControlProps) {
store.cleanLast(); store.cleanLast();
store.setData(clone); store.setData(clone);
store.cleanLast(); store.cleanLast();
props.config.timelineNeedleConfig.resetFunc();
}); });
} }
}} }}
@@ -349,6 +351,7 @@ function AnimateControl(props: AnimateControlProps) {
} }
}); });
store.setData(cloneData); store.setData(cloneData);
props.config.timelineNeedleConfig.resetFunc();
}} }}
> >

View File

@@ -25,7 +25,7 @@ function MInput(props: MInputProps) {
}, [props.data]); }, [props.data]);
const store = props.config.getStore(); const store = props.config.getStore();
return ( return (
<Row style={{ padding: '10px 20px' }}> <Row style={{ padding: '10px' }}>
<Col span={6} style={{ lineHeight: '30px' }}> <Col span={6} style={{ lineHeight: '30px' }}>
{option.label || '文字'} {option.label || '文字'}
</Col> </Col>

View File

@@ -24,11 +24,11 @@ const MSwitch = (props: MSwitchProps) => {
}, [props.data]); }, [props.data]);
const store = props.config.getStore(); const store = props.config.getStore();
return ( return (
<Row style={{ padding: '10px 20px' }}> <Row style={{ padding: '10px' }}>
<Col span={8} style={{ lineHeight: '30px' }}> <Col span={8} style={{ lineHeight: '30px' }}>
{(option as any)?.label || '文字'} {(option as any)?.label || '文字'}
</Col> </Col>
<Col span={16}> <Col span={16} style={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center' }}>
<Switch <Switch
checked={props.current.props[(option as any).receive] || ''} checked={props.current.props[(option as any).receive] || ''}
onChange={(checked) => { onChange={(checked) => {

View File

@@ -26,7 +26,7 @@ const LeftRegistMap: LeftRegistComponentMapItem[] = [
{ {
type: 'basic', type: 'basic',
component: 'input', component: 'input',
img: 'icon-anniu', img: 'https://img.guguzhu.com/d/file/android/ico/2021/09/08/rytzi2w34tm.png',
displayName: '输入框', displayName: '输入框',
}, },
]; ];
@@ -59,7 +59,7 @@ export const defaultConfig: Partial<InitConfig> = {
{ {
type: 'style', type: 'style',
icon: ( icon: (
<div className='right-tab-item' style={{ width: 50, textAlign: 'center' }}> <div className="right-tab-item" style={{ width: 50, textAlign: 'center' }}>
</div> </div>
), ),
@@ -67,7 +67,7 @@ export const defaultConfig: Partial<InitConfig> = {
{ {
type: 'animate', type: 'animate',
icon: ( icon: (
<div className='right-tab-item' style={{ width: 50, textAlign: 'center' }}> <div className="right-tab-item" style={{ width: 50, textAlign: 'center' }}>
</div> </div>
), ),
@@ -75,7 +75,7 @@ export const defaultConfig: Partial<InitConfig> = {
{ {
type: 'fn', type: 'fn',
icon: ( icon: (
<div className='right-tab-item' style={{ width: 50, textAlign: 'center' }}> <div className="right-tab-item" style={{ width: 50, textAlign: 'center' }}>
</div> </div>
), ),
@@ -83,7 +83,7 @@ export const defaultConfig: Partial<InitConfig> = {
{ {
type: 'actions', type: 'actions',
icon: ( icon: (
<div className='right-tab-item' style={{ width: 50, textAlign: 'center' }}> <div className="right-tab-item" style={{ width: 50, textAlign: 'center' }}>
</div> </div>
), ),

View File

@@ -129,6 +129,12 @@ function Blocks(props: PropsWithChildren<BlockProps>) {
return select; return select;
}, [props.data.animate]); }, [props.data.animate]);
const animationPlayState: CSSProperties = useMemo(() => {
return {
animationPlayState: props.data.animatePlayState || '',
};
}, [props.data.animatePlayState]);
const render = useMemo(() => { const render = useMemo(() => {
// 如果是编辑模式下,则需要包裹不能选中层,位移层,缩放控制层,平面移动层。 // 如果是编辑模式下,则需要包裹不能选中层,位移层,缩放控制层,平面移动层。
if (state && props.context === 'edit') { if (state && props.context === 'edit') {
@@ -164,7 +170,7 @@ function Blocks(props: PropsWithChildren<BlockProps>) {
> >
{/* 绝对定位元素 */} {/* 绝对定位元素 */}
{props.data.position !== 'static' && ( {props.data.position !== 'static' && (
<div style={{ ...style, ...animateProps }}>{state}</div> <div style={{ ...style, ...animateProps, ...animationPlayState }}>{state}</div>
)} )}
{/* 静态定位 非行内 这里暂不考虑布局影响 */} {/* 静态定位 非行内 这里暂不考虑布局影响 */}
{props.data.position === 'static' && props.data.display !== 'inline' && ( {props.data.position === 'static' && props.data.display !== 'inline' && (
@@ -174,6 +180,7 @@ function Blocks(props: PropsWithChildren<BlockProps>) {
width: '100%', width: '100%',
height: '100%', height: '100%',
...animateProps, ...animateProps,
...animationPlayState,
}} }}
> >
{state} {state}
@@ -181,7 +188,9 @@ function Blocks(props: PropsWithChildren<BlockProps>) {
)} )}
{/* 静态定位 行内 这里暂不考虑布局影响 */} {/* 静态定位 行内 这里暂不考虑布局影响 */}
{props.data.position === 'static' && props.data.display === 'inline' && ( {props.data.position === 'static' && props.data.display === 'inline' && (
<span style={{ pointerEvents: 'none', ...animateProps }}>{state}</span> <span style={{ pointerEvents: 'none', ...animateProps, ...animationPlayState }}>
{state}
</span>
)} )}
<BlockResizer data={props.data} config={props.config} rect={ref}></BlockResizer> <BlockResizer data={props.data} config={props.config} rect={ref}></BlockResizer>
<RotateResizer data={props.data} config={props.config} rect={ref}></RotateResizer> <RotateResizer data={props.data} config={props.config} rect={ref}></RotateResizer>
@@ -201,6 +210,7 @@ function Blocks(props: PropsWithChildren<BlockProps>) {
display: props.data.display, display: props.data.display,
transform: `rotate(${props.data.rotate.value}deg)`, transform: `rotate(${props.data.rotate.value}deg)`,
...animateProps, ...animateProps,
...animationPlayState,
}} }}
> >
{state} {state}
@@ -215,6 +225,7 @@ function Blocks(props: PropsWithChildren<BlockProps>) {
props.config, props.config,
innerDragData, innerDragData,
animateProps, animateProps,
animationPlayState,
previewState.top, previewState.top,
previewState.left, previewState.left,
previewState.width, previewState.width,

View File

@@ -33,13 +33,13 @@ export interface PreviewProps {
* @memberof PreviewProps * @memberof PreviewProps
*/ */
completeFn?: Function; completeFn?: Function;
/** /**
* *
* 预览样式 * 预览样式
* @type {CSSProperties} * @type {CSSProperties}
* @memberof PreviewProps * @memberof PreviewProps
*/ */
previewContainerStyle?: CSSProperties; previewContainerStyle?: CSSProperties;
} }
function Preview(props: PreviewProps): ReactElement { function Preview(props: PreviewProps): ReactElement {
@@ -128,7 +128,7 @@ function Preview(props: PreviewProps): ReactElement {
config={props.config} config={props.config}
context="preview" context="preview"
state={props.config.getStore().getData()} state={props.config.getStore().getData()}
previewContainerStyle={props.previewContainerStyle} previewContainerStyle={props.previewContainerStyle}
></Container> ></Container>
</> </>
); );

View File

@@ -115,7 +115,7 @@ function RightConfig(props: PropsWithChildren<RightConfigProps>) {
const originData = props.config.getStoreChanger().getOrigin()?.now; const originData = props.config.getStoreChanger().getOrigin()?.now;
return ( return (
<div <div
className="ant-menu" className="ant-menu right-pannel-wrap"
style={{ style={{
height: '100%', height: '100%',
width: '400px', width: '400px',
@@ -136,10 +136,12 @@ function RightConfig(props: PropsWithChildren<RightConfigProps>) {
return ( return (
<Tabs.TabPane tab={v.icon} key={i + ''}> <Tabs.TabPane tab={v.icon} key={i + ''}>
<div <div
className="scrollbar" className="scrollbar right-pannel-tabdiv"
style={{ style={{
height: 'calc(100vh - 110px)', height: 'calc(100vh - 110px)',
overflow: 'auto', overflow: 'auto',
position: 'fixed',
width: 380,
}} }}
> >
{v.custom && v.customRender && v.customRender(v.type, current)} {v.custom && v.customRender && v.customRender(v.type, current)}
@@ -151,7 +153,7 @@ function RightConfig(props: PropsWithChildren<RightConfigProps>) {
</Tabs> </Tabs>
)} )}
{!current && !isEdit && !customGlobal && ( {!current && !isEdit && !customGlobal && (
<div style={{ padding: '20px' }}> <div style={{ padding: '10px' }}>
<Row style={{ padding: '10px 0 20px 0', fontWeight: 'bold', userSelect: 'none' }}> <Row style={{ padding: '10px 0 20px 0', fontWeight: 'bold', userSelect: 'none' }}>
{replaceLocale('right.global', '全局设置', props.config)} {replaceLocale('right.global', '全局设置', props.config)}
</Row> </Row>
@@ -259,8 +261,8 @@ function RightConfig(props: PropsWithChildren<RightConfigProps>) {
)} )}
{!current && !isEdit && customGlobal && customGlobal(props.config)} {!current && !isEdit && customGlobal && customGlobal(props.config)}
{!current && isEdit && ( {!current && isEdit && (
<div style={{ padding: '20px' }} className="yh-tcsz"> <div style={{ padding: '10px' }} className="yh-tcsz">
<Row style={{ padding: '10 0 20px 0', fontWeight: 'bold' }}> <Row style={{ padding: '10px 0 20px 0', fontWeight: 'bold' }}>
{replaceLocale('modal.control', '弹窗配置', props.config)} {replaceLocale('modal.control', '弹窗配置', props.config)}
</Row> </Row>
<Row style={{ padding: '10px 0' }}> <Row style={{ padding: '10px 0' }}>

View File

@@ -39,6 +39,11 @@ export interface TimeLineConfigType {
autoFocus: boolean; autoFocus: boolean;
scrollDom: null | HTMLDivElement; scrollDom: null | HTMLDivElement;
} }
export interface TimeLineNeedleConfigType {
status: 'stop' | 'start';
runFunc: Function;
resetFunc: Function;
}
const animateTicker = new Array(iter).fill(1).map((_, y) => y); const animateTicker = new Array(iter).fill(1).map((_, y) => y);
@@ -159,6 +164,9 @@ const SortableList = SortableContainer(
let cacheBlock: IBlockType[] = []; let cacheBlock: IBlockType[] = [];
const needleWidth = 2;
const initialLeft = 20 - needleWidth / 2;
let timer: number | null = null;
export function TimeLine(props: TimeLineProps) { export function TimeLine(props: TimeLineProps) {
const store = props.config.getStore(); const store = props.config.getStore();
const data = store.getData().block; const data = store.getData().block;
@@ -214,6 +222,33 @@ export function TimeLine(props: TimeLineProps) {
} }
}, [props.config]); }, [props.config]);
const [needle, setNeedle] = useState(initialLeft);
const needleStart = () => {
setNeedle(initialLeft);
//每过0.1秒移动2
if (timer) {
window.clearInterval(timer);
}
props.config.timelineNeedleConfig.status = 'start';
timer = window.setInterval(() => {
if (needle < ruleWidth) {
setNeedle((pre) => pre + 2);
}
}, 100);
};
const needleReset = () => {
if (timer) {
window.clearInterval(timer);
}
setNeedle(initialLeft);
props.config.timelineNeedleConfig.status = 'stop';
};
props.config.timelineNeedleConfig.resetFunc = needleReset;
props.config.timelineNeedleConfig.runFunc = needleStart;
return ( return (
<div <div
className={`${props.classes} ant-menu yh-timeline-wrap`} className={`${props.classes} ant-menu yh-timeline-wrap`}
@@ -276,6 +311,7 @@ export function TimeLine(props: TimeLineProps) {
WAIT = false; WAIT = false;
props.config.waitAnimate = false; props.config.waitAnimate = false;
store.setData(cloneData); store.setData(cloneData);
needleStart();
}); });
} }
}} }}
@@ -291,8 +327,22 @@ export function TimeLine(props: TimeLineProps) {
width: `calc(100% - ${leftWidth}px)`, width: `calc(100% - ${leftWidth}px)`,
borderBottom: '1px solid #dadada', borderBottom: '1px solid #dadada',
overflow: 'hidden', overflow: 'hidden',
position: 'relative',
}} }}
> >
<div
style={{
position: 'absolute',
transform: `translate(-${scrollx}px, 0px)`,
width: needleWidth,
height: '100%',
backgroundColor: 'red',
zIndex: 2,
left: needle,
transition: 'left linear',
willChange: 'left',
}}
></div>
<div <div
style={{ style={{
display: 'flex', display: 'flex',

View File

@@ -124,7 +124,7 @@ const commonCss: CSSProperties = {
height: square * 2, height: square * 2,
width: square * 2, width: square * 2,
position: 'absolute', position: 'absolute',
background: '#000000', background: 'rgba(0, 0, 0, 0.85)',
top: (itemHeight - diff) / 2 - square, top: (itemHeight - diff) / 2 - square,
cursor: 'e-resize', cursor: 'e-resize',
}; };

View File

@@ -33,7 +33,7 @@ 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 } from '../components/wrapperMove/event';
import { wrapperMoveState as iframeWrapperMoveState } from '../components/IframeWrapperMove/event'; import { wrapperMoveState as iframeWrapperMoveState } from '../components/IframeWrapperMove/event';
import { TimeLineConfigType } from '../components/timeLine/timeline'; import { TimeLineConfigType, TimeLineNeedleConfigType } from '../components/timeLine/timeline';
// 组件部分 // 组件部分
/** /**
@@ -353,6 +353,11 @@ export class UserConfig {
autoFocus: true, autoFocus: true,
scrollDom: null, scrollDom: null,
}; };
public timelineNeedleConfig: TimeLineNeedleConfigType = {
status: 'stop',
runFunc: () => {},
resetFunc: () => {},
};
public waitAnimate = false; public waitAnimate = false;
public wrapperMoveState = wrapperMoveState; public wrapperMoveState = wrapperMoveState;
public iframeWrapperMoveState = iframeWrapperMoveState; public iframeWrapperMoveState = iframeWrapperMoveState;

View File

@@ -43,5 +43,6 @@ export function createBlock(
value: 0, value: 0,
canRotate: true, canRotate: true,
}, },
animatePlayState: ComponentItem.initData.animatePlayState || '',
}; };
} }

View File

@@ -51,5 +51,6 @@ export interface IBlockType {
canRotate: boolean; canRotate: boolean;
}; };
animate: AnimateItem[]; animate: AnimateItem[];
animatePlayState: string;
fixed: boolean; // 用于制作fixed组件 fixed: boolean; // 用于制作fixed组件
} }

View File

@@ -46,6 +46,7 @@ function createDefaultModalBlock(): IStoreData['block'] {
value: 0, value: 0,
canRotate: false, canRotate: false,
}, },
animatePlayState: '',
}, },
]; ];
} }