update 0.8.1
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
## changelog
|
## changelog
|
||||||
|
|
||||||
|
## 0.8.1
|
||||||
|
|
||||||
|
新增动画组件timeline。可以更好预览所有动画。
|
||||||
|
|
||||||
## 0.8.0
|
## 0.8.0
|
||||||
|
|
||||||
动画部分重构,可支持多动画同时配置。
|
动画部分重构,可支持多动画同时配置。
|
||||||
|
@@ -4,6 +4,10 @@ order: 1
|
|||||||
---
|
---
|
||||||
## changelog
|
## changelog
|
||||||
|
|
||||||
|
## 0.8.1
|
||||||
|
|
||||||
|
新增动画组件timeline。可以更好预览所有动画。
|
||||||
|
|
||||||
## 0.8.0
|
## 0.8.0
|
||||||
|
|
||||||
动画部分重构,可支持多动画同时配置。
|
动画部分重构,可支持多动画同时配置。
|
||||||
|
@@ -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-20 16:30:12
|
* @LastEditTime: 2021-08-11 16:26:46
|
||||||
* @FilePath: \dooringx\packages\dooringx-example\src\pages\index.tsx
|
* @FilePath: \dooringx\packages\dooringx-example\src\pages\index.tsx
|
||||||
*/
|
*/
|
||||||
import {
|
import {
|
||||||
@@ -31,7 +31,6 @@ export default function IndexPage() {
|
|||||||
}, [config]);
|
}, [config]);
|
||||||
|
|
||||||
const [state] = useStoreState(config, subscribeFn, everyFn);
|
const [state] = useStoreState(config, subscribeFn, everyFn);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div {...innerContainerDragUp(config)}>
|
<div {...innerContainerDragUp(config)}>
|
||||||
<div style={{ height: HeaderHeight }}>
|
<div style={{ height: HeaderHeight }}>
|
||||||
@@ -68,7 +67,7 @@ export default function IndexPage() {
|
|||||||
<>
|
<>
|
||||||
<Control
|
<Control
|
||||||
config={config}
|
config={config}
|
||||||
style={{ position: 'fixed', bottom: '60px', right: '450px', zIndex: 100 }}
|
style={{ position: 'fixed', bottom: '160px', right: '450px', zIndex: 100 }}
|
||||||
></Control>
|
></Control>
|
||||||
<Container state={state} config={config} context="edit"></Container>
|
<Container state={state} config={config} context="edit"></Container>
|
||||||
</>
|
</>
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import React, { useMemo, useState } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { UserConfig, deepCopy, createUid } from 'dooringx-lib';
|
import { UserConfig, deepCopy, createUid } from 'dooringx-lib';
|
||||||
import { Col, Row, Select, InputNumber, Button } from 'antd';
|
import { Col, Row, Select, InputNumber, Button } from 'antd';
|
||||||
import { FormMap, FormBaseType } from '../formTypes';
|
import { FormMap, FormBaseType } from '../formTypes';
|
||||||
@@ -121,9 +121,19 @@ const timeFunction: Record<string, string> = {
|
|||||||
缓入: 'ease in',
|
缓入: 'ease in',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let lastAnimate: AnimateItem[] = [];
|
||||||
|
let isOmit = false;
|
||||||
|
|
||||||
function AnimateControl(props: AnimateControlProps) {
|
function AnimateControl(props: AnimateControlProps) {
|
||||||
const animate = props.current.animate;
|
|
||||||
const store = props.config.getStore();
|
const store = props.config.getStore();
|
||||||
|
|
||||||
|
const animate = useMemo(() => {
|
||||||
|
if (isOmit) {
|
||||||
|
return lastAnimate;
|
||||||
|
}
|
||||||
|
lastAnimate = props.current.animate;
|
||||||
|
return props.current.animate;
|
||||||
|
}, [props.current.animate]);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{animate.map((v, i) => {
|
{animate.map((v, i) => {
|
||||||
@@ -164,6 +174,7 @@ function AnimateControl(props: AnimateControlProps) {
|
|||||||
<Col span={7}>
|
<Col span={7}>
|
||||||
<InputNumber
|
<InputNumber
|
||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
|
step="0.1"
|
||||||
value={animate[i].animationDuration}
|
value={animate[i].animationDuration}
|
||||||
formatter={(value) => `${value}s`}
|
formatter={(value) => `${value}s`}
|
||||||
min={0}
|
min={0}
|
||||||
@@ -191,6 +202,7 @@ function AnimateControl(props: AnimateControlProps) {
|
|||||||
value={animate[i].animationDelay}
|
value={animate[i].animationDelay}
|
||||||
formatter={(value) => `${value}s`}
|
formatter={(value) => `${value}s`}
|
||||||
min={0}
|
min={0}
|
||||||
|
step="0.1"
|
||||||
onChange={(d) => {
|
onChange={(d) => {
|
||||||
const cloneData: IStoreData = deepCopy(store.getData());
|
const cloneData: IStoreData = deepCopy(store.getData());
|
||||||
cloneData.block.forEach((w) => {
|
cloneData.block.forEach((w) => {
|
||||||
@@ -291,6 +303,8 @@ function AnimateControl(props: AnimateControlProps) {
|
|||||||
{animate.length > 0 && (
|
{animate.length > 0 && (
|
||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
if (!isOmit) {
|
||||||
|
isOmit = true;
|
||||||
const cacheProps = animate;
|
const cacheProps = animate;
|
||||||
const data: IStoreData = store.getData();
|
const data: IStoreData = store.getData();
|
||||||
data.block.forEach((v) => {
|
data.block.forEach((v) => {
|
||||||
@@ -298,6 +312,7 @@ function AnimateControl(props: AnimateControlProps) {
|
|||||||
v.animate = [];
|
v.animate = [];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
store.emit();
|
||||||
store.forceUpdate();
|
store.forceUpdate();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
data.block.forEach((v) => {
|
data.block.forEach((v) => {
|
||||||
@@ -305,8 +320,11 @@ function AnimateControl(props: AnimateControlProps) {
|
|||||||
v.animate = cacheProps;
|
v.animate = cacheProps;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
store.emit();
|
||||||
store.forceUpdate();
|
store.forceUpdate();
|
||||||
|
isOmit = false;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
运行动画
|
运行动画
|
||||||
|
@@ -142,7 +142,7 @@ Contributions, issues and feature requests are welcome!.
|
|||||||
|
|
||||||
### 技术交流 | Technical Communication
|
### 技术交流 | Technical Communication
|
||||||
|
|
||||||
<img src="http://cdn.dooring.cn/dr/WechatIMG679.jpeg" width=260 />
|
<a href="http://cdn.dooring.cn/dr/gp.jpeg" target="_blank"><img src="http://cdn.dooring.cn/dr/gp.jpeg" width=260 />dooringx-lib交流群</a>
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "0.8.0",
|
"version": "0.8.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"module": "dist/dooringx-lib.esm.js",
|
"module": "dist/dooringx-lib.esm.js",
|
||||||
|
@@ -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-20 11:24:39
|
* @LastEditTime: 2021-08-11 16:39:24
|
||||||
* @FilePath: \dooringx\packages\dooringx-lib\src\components\IframeWrapperMove\index.tsx
|
* @FilePath: \dooringx\packages\dooringx-lib\src\components\IframeWrapperMove\index.tsx
|
||||||
*/
|
*/
|
||||||
import { AllHTMLAttributes, CSSProperties, PropsWithChildren, ReactNode, useRef } from 'react';
|
import { AllHTMLAttributes, CSSProperties, PropsWithChildren, ReactNode, useRef } from 'react';
|
||||||
@@ -11,6 +11,7 @@ import { onWheelEventIframe } from '../../core/scale';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Ticker from './ticker';
|
import Ticker from './ticker';
|
||||||
import UserConfig from '../../config';
|
import UserConfig from '../../config';
|
||||||
|
import TimeLine from '../timeLine/timeline';
|
||||||
|
|
||||||
export interface ContainerWrapperProps extends AllHTMLAttributes<HTMLDivElement> {
|
export interface ContainerWrapperProps extends AllHTMLAttributes<HTMLDivElement> {
|
||||||
config: UserConfig;
|
config: UserConfig;
|
||||||
@@ -48,6 +49,7 @@ function ContainerWrapper(props: PropsWithChildren<ContainerWrapperProps>) {
|
|||||||
{...onWheelEventIframe(props.config, scaleState)}
|
{...onWheelEventIframe(props.config, scaleState)}
|
||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
|
{config.timeline && <TimeLine config={config}></TimeLine>}
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
|
@@ -128,7 +128,6 @@ function Blocks(props: PropsWithChildren<BlockProps>) {
|
|||||||
});
|
});
|
||||||
return select;
|
return select;
|
||||||
}, [props.data.animate]);
|
}, [props.data.animate]);
|
||||||
console.log(animateProps);
|
|
||||||
|
|
||||||
const render = useMemo(() => {
|
const render = useMemo(() => {
|
||||||
// 如果是编辑模式下,则需要包裹不能选中层,位移层,缩放控制层,平面移动层。
|
// 如果是编辑模式下,则需要包裹不能选中层,位移层,缩放控制层,平面移动层。
|
||||||
|
@@ -8,6 +8,7 @@ import {
|
|||||||
MenuOutlined,
|
MenuOutlined,
|
||||||
SyncOutlined,
|
SyncOutlined,
|
||||||
UnorderedListOutlined,
|
UnorderedListOutlined,
|
||||||
|
VideoCameraOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import { Button, Divider, Form, Input, List, Modal, Popconfirm, Popover } from 'antd';
|
import { Button, Divider, Form, Input, List, Modal, Popconfirm, Popover } from 'antd';
|
||||||
import React, { CSSProperties, PropsWithChildren, useState } from 'react';
|
import React, { CSSProperties, PropsWithChildren, useState } from 'react';
|
||||||
@@ -189,6 +190,13 @@ export function Control(props: PropsWithChildren<ControlProps>) {
|
|||||||
<Button icon={<GatewayOutlined />}></Button>
|
<Button icon={<GatewayOutlined />}></Button>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
icon={<VideoCameraOutlined />}
|
||||||
|
onClick={() => {
|
||||||
|
props.config.timeline = !props.config.timeline;
|
||||||
|
props.config.getStore().forceUpdate();
|
||||||
|
}}
|
||||||
|
></Button>
|
||||||
<Button
|
<Button
|
||||||
icon={<SyncOutlined />}
|
icon={<SyncOutlined />}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
307
packages/dooringx-lib/src/components/timeLine/timeline.tsx
Normal file
307
packages/dooringx-lib/src/components/timeLine/timeline.tsx
Normal file
@@ -0,0 +1,307 @@
|
|||||||
|
/*
|
||||||
|
* @Author: yehuozhili
|
||||||
|
* @Date: 2021-08-09 15:15:25
|
||||||
|
* @LastEditors: yehuozhili
|
||||||
|
* @LastEditTime: 2021-08-11 17:03:54
|
||||||
|
* @FilePath: \dooringx\packages\dooringx-lib\src\components\timeLine\timeline.tsx
|
||||||
|
*/
|
||||||
|
import deepcopy from 'deepcopy';
|
||||||
|
import React, { CSSProperties, useState } from 'react';
|
||||||
|
import { SortableContainer, SortableElement, SortableHandle, SortEnd } from 'react-sortable-hoc';
|
||||||
|
import UserConfig from '../../config';
|
||||||
|
import { IBlockType, IStoreData } from '../../core/store/storetype';
|
||||||
|
import { arrayMove } from '../../core/utils';
|
||||||
|
import { MenuOutlined, PlayCircleOutlined } from '@ant-design/icons';
|
||||||
|
import {
|
||||||
|
TimeLineItem,
|
||||||
|
itemHeight,
|
||||||
|
TimeLineItemMouseMove,
|
||||||
|
TimeLineItemMouseOver,
|
||||||
|
interval,
|
||||||
|
} from './timelineItem';
|
||||||
|
|
||||||
|
export interface TimeLineProps {
|
||||||
|
style?: CSSProperties;
|
||||||
|
classes?: string;
|
||||||
|
config: UserConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
const iter = 500;
|
||||||
|
const animateTicker = new Array(iter).fill(1).map((_, y) => y);
|
||||||
|
|
||||||
|
const DragHandle = SortableHandle(() => <MenuOutlined />);
|
||||||
|
|
||||||
|
const leftWidth = 200;
|
||||||
|
let WAIT = false;
|
||||||
|
|
||||||
|
const widthInterval = interval * 10 + 9;
|
||||||
|
const ruleWidth = (widthInterval * iter) / 10 + 10;
|
||||||
|
const borderColor = '1px solid rgb(204, 204, 204)';
|
||||||
|
|
||||||
|
const SortableItem = SortableElement(
|
||||||
|
({ value }: { value: { value: IBlockType; config: UserConfig } }) => (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
userSelect: 'none',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
width: '100%',
|
||||||
|
zIndex: 101,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
width: leftWidth,
|
||||||
|
overflow: 'auto',
|
||||||
|
minWidth: leftWidth,
|
||||||
|
borderRight: borderColor,
|
||||||
|
borderBottom: borderColor,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ width: 30, cursor: 'move' }}>
|
||||||
|
<DragHandle></DragHandle>
|
||||||
|
</div>
|
||||||
|
<div>{value.config.getComponentRegister().getMap()[value.value.name].display}</div>
|
||||||
|
<div>{value.value.id.slice(-6)}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const SortableList = SortableContainer(
|
||||||
|
({ items }: { items: { data: IBlockType[]; config: UserConfig } }) => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{items.data.map((value, index: number) => (
|
||||||
|
<SortableItem key={value.id} index={index} value={{ value, config: items.config }} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export function TimeLine(props: TimeLineProps) {
|
||||||
|
const store = props.config.getStore();
|
||||||
|
const data = store.getData().block;
|
||||||
|
const forceUpdate = useState(0)[1];
|
||||||
|
const onSortEnd = (sort: SortEnd) => {
|
||||||
|
const { oldIndex, newIndex } = sort;
|
||||||
|
const newblocks: IBlockType[] = arrayMove(data, oldIndex, newIndex);
|
||||||
|
const isEdit = props.config.getStoreChanger().isEdit();
|
||||||
|
if (isEdit) {
|
||||||
|
const firstType = newblocks[0].name;
|
||||||
|
if (firstType !== 'modalMask') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const store = props.config.getStore();
|
||||||
|
const cloneData: IStoreData = deepcopy(store.getData());
|
||||||
|
cloneData.block = newblocks;
|
||||||
|
store.setData(cloneData);
|
||||||
|
};
|
||||||
|
|
||||||
|
const [state, setState] = useState(0);
|
||||||
|
const [scrollx, setScrollx] = useState(0);
|
||||||
|
|
||||||
|
const content = (
|
||||||
|
<div style={{ width: '100%', height: '100%', overflow: 'hidden' }}>
|
||||||
|
<div style={{ transform: `translate(0, -${state}px)` }}>
|
||||||
|
<SortableList
|
||||||
|
distance={2}
|
||||||
|
useDragHandle
|
||||||
|
items={{
|
||||||
|
data,
|
||||||
|
config: props.config,
|
||||||
|
}}
|
||||||
|
onSortEnd={onSortEnd}
|
||||||
|
axis="y"
|
||||||
|
></SortableList>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={props.classes}
|
||||||
|
style={{
|
||||||
|
backgroundColor: 'white',
|
||||||
|
width: '100%',
|
||||||
|
position: 'absolute',
|
||||||
|
height: '150px',
|
||||||
|
bottom: '0',
|
||||||
|
zIndex: 100,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
...props.style,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
lineHeight: '24px',
|
||||||
|
paddingLeft: 10,
|
||||||
|
height: '100%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: leftWidth,
|
||||||
|
borderRight: '1px solid #dadada',
|
||||||
|
minWidth: leftWidth,
|
||||||
|
borderBottom: '1px solid #dadada',
|
||||||
|
height: itemHeight,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
组件名称
|
||||||
|
<span
|
||||||
|
title="play"
|
||||||
|
style={{
|
||||||
|
display: 'inline-block',
|
||||||
|
marginLeft: '20px',
|
||||||
|
cursor: 'pointer',
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
//缓存所有animate后执行
|
||||||
|
if (!WAIT) {
|
||||||
|
WAIT = true;
|
||||||
|
const cache = data.map((v) => {
|
||||||
|
return v.animate;
|
||||||
|
});
|
||||||
|
const cloneData: IStoreData = deepcopy(store.getData());
|
||||||
|
cloneData.block.forEach((v) => {
|
||||||
|
v.animate = [];
|
||||||
|
});
|
||||||
|
store.setData(cloneData);
|
||||||
|
setTimeout(() => {
|
||||||
|
const cloneData: IStoreData = deepcopy(store.getData());
|
||||||
|
cloneData.block.forEach((v, i) => {
|
||||||
|
v.animate = cache[i];
|
||||||
|
});
|
||||||
|
WAIT = false;
|
||||||
|
store.setData(cloneData);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<PlayCircleOutlined />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{content}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: `calc(100% - ${leftWidth}px)`,
|
||||||
|
borderBottom: '1px solid #dadada',
|
||||||
|
overflow: 'hidden',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
height: itemHeight,
|
||||||
|
alignItems: 'flex-end',
|
||||||
|
borderBottom: borderColor,
|
||||||
|
width: ruleWidth,
|
||||||
|
overflow: 'hidden',
|
||||||
|
transform: `translate(-${scrollx}px, 0px)`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{animateTicker.map((v) => {
|
||||||
|
if (v % 10 === 0) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={v}
|
||||||
|
style={{
|
||||||
|
marginLeft: interval,
|
||||||
|
height: '8px',
|
||||||
|
borderLeft: borderColor,
|
||||||
|
position: 'relative',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: '-20px',
|
||||||
|
transform: 'translate(-50%, 0px)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{v}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={v}
|
||||||
|
style={{
|
||||||
|
marginLeft: interval,
|
||||||
|
height: '6px',
|
||||||
|
borderLeft: borderColor,
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
onScroll={(e) => {
|
||||||
|
const target = e.target as HTMLDivElement;
|
||||||
|
setState(target.scrollTop);
|
||||||
|
setScrollx(target.scrollLeft);
|
||||||
|
}}
|
||||||
|
style={{ overflow: 'auto', height: `calc(100% - ${itemHeight}px)` }}
|
||||||
|
>
|
||||||
|
{data.map((v) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={v.id}
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
paddingLeft: interval,
|
||||||
|
borderBottom: borderColor,
|
||||||
|
width: ruleWidth,
|
||||||
|
position: 'relative',
|
||||||
|
overflow: 'hidden',
|
||||||
|
}}
|
||||||
|
onMouseMove={(e) => {
|
||||||
|
TimeLineItemMouseMove(e, v.animate, forceUpdate);
|
||||||
|
}}
|
||||||
|
onMouseLeave={() => TimeLineItemMouseOver()}
|
||||||
|
onMouseUp={() => TimeLineItemMouseOver()}
|
||||||
|
>
|
||||||
|
<TimeLineItem animate={v.animate}></TimeLineItem>
|
||||||
|
{animateTicker.map((v) => {
|
||||||
|
if (v % 10 === 0) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={v}
|
||||||
|
style={{
|
||||||
|
marginRight: widthInterval, // 左右2根线
|
||||||
|
borderLeft: borderColor,
|
||||||
|
position: 'relative',
|
||||||
|
height: itemHeight - 1,
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TimeLine;
|
108
packages/dooringx-lib/src/components/timeLine/timelineItem.tsx
Normal file
108
packages/dooringx-lib/src/components/timeLine/timelineItem.tsx
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* @Author: yehuozhili
|
||||||
|
* @Date: 2021-08-10 20:26:44
|
||||||
|
* @LastEditors: yehuozhili
|
||||||
|
* @LastEditTime: 2021-08-11 15:34:46
|
||||||
|
* @FilePath: \dooringx\packages\dooringx-lib\src\components\timeLine\timelineItem.tsx
|
||||||
|
*/
|
||||||
|
import React from 'react';
|
||||||
|
import { AnimateItem } from '../../core/store/storetype';
|
||||||
|
|
||||||
|
export const itemHeight = 25;
|
||||||
|
const diff = 6;
|
||||||
|
// 需要根据animate属性渲染div
|
||||||
|
|
||||||
|
export interface TimeLineItemProps {
|
||||||
|
animate: AnimateItem[];
|
||||||
|
}
|
||||||
|
const bgColor = [
|
||||||
|
'#4af',
|
||||||
|
'rgb(93, 128, 158)',
|
||||||
|
'rgb(158, 130, 93)',
|
||||||
|
'rgb(219, 72, 34)',
|
||||||
|
'rgb(255, 68, 168)',
|
||||||
|
'#4af',
|
||||||
|
'rgb(93, 128, 158)',
|
||||||
|
'rgb(158, 130, 93)',
|
||||||
|
'rgb(219, 72, 34)',
|
||||||
|
'rgb(255, 68, 168)',
|
||||||
|
];
|
||||||
|
|
||||||
|
interface MoveStateTypes {
|
||||||
|
startX: number;
|
||||||
|
isMove: boolean;
|
||||||
|
uid: string;
|
||||||
|
dom: null | HTMLDivElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
const moveState: MoveStateTypes = {
|
||||||
|
startX: 0,
|
||||||
|
isMove: false,
|
||||||
|
uid: '',
|
||||||
|
dom: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const interval = 19;
|
||||||
|
const times = interval + 1;
|
||||||
|
|
||||||
|
export const TimeLineItemMouseMove = function (
|
||||||
|
e: React.MouseEvent<HTMLDivElement, MouseEvent>,
|
||||||
|
animate: AnimateItem[],
|
||||||
|
forceUpdate: React.Dispatch<React.SetStateAction<number>>
|
||||||
|
) {
|
||||||
|
if (moveState.isMove) {
|
||||||
|
//修改源属性
|
||||||
|
const diff = e.screenX - moveState.startX;
|
||||||
|
animate.forEach((v) => {
|
||||||
|
if (v.uid === moveState.uid) {
|
||||||
|
const f = parseFloat((v.animationDelay + diff / times).toFixed(1));
|
||||||
|
v.animationDelay = f < 0 ? 0 : f;
|
||||||
|
forceUpdate((p) => p + 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
moveState.startX = e.screenX;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export const TimeLineItemMouseOver = function () {
|
||||||
|
moveState.isMove = false;
|
||||||
|
moveState.startX = 0;
|
||||||
|
moveState.uid = '';
|
||||||
|
if (moveState.dom) {
|
||||||
|
moveState.dom.style.cursor = 'default';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export function TimeLineItem(props: TimeLineItemProps) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{props.animate.map((v) => {
|
||||||
|
const left = v.animationDelay * times + interval;
|
||||||
|
const repeat =
|
||||||
|
v.animationIterationCount === 'infinite' ? 500 : parseInt(v.animationIterationCount);
|
||||||
|
const width = v.animationDuration * times * repeat;
|
||||||
|
const index = v.uid.charCodeAt(0) % 10;
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={v.uid}
|
||||||
|
onMouseDown={(e) => {
|
||||||
|
moveState.startX = e.screenX;
|
||||||
|
moveState.uid = v.uid;
|
||||||
|
moveState.isMove = true;
|
||||||
|
const dom = e.target as HTMLDivElement;
|
||||||
|
dom.style.cursor = 'move';
|
||||||
|
moveState.dom = dom;
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: diff / 2,
|
||||||
|
left: left,
|
||||||
|
width: width,
|
||||||
|
height: itemHeight - diff,
|
||||||
|
background: bgColor[index],
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@@ -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-27 10:17:01
|
* @LastEditTime: 2021-08-11 16:16:30
|
||||||
* @FilePath: \dooringx\packages\dooringx-lib\src\components\wrapperMove\index.tsx
|
* @FilePath: \dooringx\packages\dooringx-lib\src\components\wrapperMove\index.tsx
|
||||||
*/
|
*/
|
||||||
import { AllHTMLAttributes, CSSProperties, PropsWithChildren, useRef } from 'react';
|
import { AllHTMLAttributes, CSSProperties, PropsWithChildren, useRef } from 'react';
|
||||||
@@ -11,6 +11,7 @@ import { onWheelEvent } from '../../core/scale';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Ticker from './ticker';
|
import Ticker from './ticker';
|
||||||
import UserConfig from '../../config';
|
import UserConfig from '../../config';
|
||||||
|
import TimeLine from '../timeLine/timeline';
|
||||||
|
|
||||||
export interface ContainerWrapperProps extends AllHTMLAttributes<HTMLDivElement> {
|
export interface ContainerWrapperProps extends AllHTMLAttributes<HTMLDivElement> {
|
||||||
config: UserConfig;
|
config: UserConfig;
|
||||||
@@ -42,6 +43,7 @@ function ContainerWrapper(props: PropsWithChildren<ContainerWrapperProps>) {
|
|||||||
{...onWheelEvent(props.config)}
|
{...onWheelEvent(props.config)}
|
||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
|
{config.timeline && <TimeLine config={config}></TimeLine>}
|
||||||
{children}
|
{children}
|
||||||
{ticker && <Ticker config={props.config}></Ticker>}
|
{ticker && <Ticker config={props.config}></Ticker>}
|
||||||
</div>
|
</div>
|
||||||
|
@@ -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-08-03 23:19:24
|
* @LastEditTime: 2021-08-11 16:16:09
|
||||||
* @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';
|
||||||
@@ -344,6 +344,7 @@ export class UserConfig {
|
|||||||
public focusState = focusState;
|
public focusState = focusState;
|
||||||
public collapsed = false;
|
public collapsed = false;
|
||||||
public ticker = true;
|
public ticker = true;
|
||||||
|
public timeline = false;
|
||||||
public wrapperMoveState = wrapperMoveState;
|
public wrapperMoveState = wrapperMoveState;
|
||||||
public iframeWrapperMoveState = iframeWrapperMoveState;
|
public iframeWrapperMoveState = iframeWrapperMoveState;
|
||||||
public refreshIframe = () => {};
|
public refreshIframe = () => {};
|
||||||
|
Reference in New Issue
Block a user