feat: update sketch logic

This commit is contained in:
chenshenhai 2023-06-03 16:07:38 +08:00
parent 05ef32667a
commit 6061cffa34
6 changed files with 101 additions and 55 deletions

View file

@ -1,5 +1,6 @@
import { createContext } from 'react';
import { DesignData, DesignState, DesignAction, DesignContext } from './types';
import type { Data } from '@idraw/types';
import { DesignData, DesignState, DesignAction, DesignContext, DesignDrawDataType } from './types';
import { parseComponentsToDrawData } from './util/view-data';
export function createDesignData(): DesignData {
@ -10,12 +11,24 @@ export function createDesignData(): DesignData {
};
}
function parseDrawData(drawDataType: DesignDrawDataType, designData: DesignData | null): Data {
let drawData: Data = { elements: [] };
if (drawDataType === 'component') {
drawData = parseComponentsToDrawData(designData?.components || []);
}
return drawData;
}
export function createDesignContextState(opts?: Partial<DesignState>): DesignState {
const activeDrawDataType: DesignDrawDataType = 'component';
const designData: DesignData = opts?.designData || createDesignData();
const viewDrawData = parseDrawData(activeDrawDataType, designData);
return {
designData: opts?.designData || createDesignData(),
activeDrawDataType: 'component', // TODO
designData: designData,
activeDrawDataType: activeDrawDataType,
themeMode: opts?.themeMode || 'light',
viewDrawData: null,
viewDrawData: viewDrawData,
viewDrawUUID: null
};
}
@ -48,19 +61,13 @@ export function createDesignReducer(state: DesignState, action: DesignAction): D
if (!action?.payload?.activeDrawDataType) {
return state;
}
let newState = {
const newState = {
...state,
...{
activeDrawDataType: action?.payload.activeDrawDataType
activeDrawDataType: action?.payload.activeDrawDataType,
viewDrawData: parseDrawData(action?.payload?.activeDrawDataType, state.designData)
}
};
if (action.payload.activeDrawDataType === 'component') {
newState = {
...newState,
viewDrawData: parseComponentsToDrawData(state.designData?.components || [])
};
}
return newState;
}

View file

@ -5,6 +5,7 @@
@import './modules/header.less';
@import './modules/dashboard.less';
@import './modules/sketch.less';
@import './modules/toolbar.less';
@import './modules/panel-layer.less';
@import './modules/split-pane.less';

View file

@ -0,0 +1,7 @@
@import '../variable.less';
@mod-xxx: ~'@{prefix}-mod-sketch';
.@{mod-xxx} {
border: 1px solid #f0f0f0;
}

View file

@ -1,11 +1,9 @@
import React, { useEffect, useRef, useState } from 'react';
import React, { useEffect, useState } from 'react';
import classnames from 'classnames';
import { Core, MiddlewareScroller, MiddlewareSelector } from '@idraw/core';
import { calcElementsContextSize } from '@idraw/util';
import { getData } from '../../data';
import { Toolbar } from '../toolbar';
import { PanelLayer } from '../panel-layer';
import { Header } from '../header';
import { Sketch } from '../sketch';
import type { CSSProperties } from 'react';
import { createPrefixName } from '../../css';
import { HEADER_HEIGHT } from './layout';
@ -25,11 +23,7 @@ export interface DashboardProps {
}
export const Dashboard = (props: DashboardProps) => {
const ref = useRef<HTMLDivElement>(null);
const refCore = useRef<Core | null>(null);
const { className, style, width, height } = props;
const data = getData();
const devicePixelRatio = window.devicePixelRatio;
const [openLeftSider, setOpenLeftSider] = useState<boolean>(true);
const [openRightSider, setOpenRightSider] = useState<boolean>(false);
@ -38,23 +32,6 @@ export const Dashboard = (props: DashboardProps) => {
const [rightWidth, setRightWidth] = useState<number>(openRightSider ? rightSiderDefaultWidth : 0);
const [centerWidth, setCenterWidth] = useState<number>(width - leftWidth - rightWidth);
useEffect(() => {
if (ref?.current) {
if (!refCore?.current) {
const options = {
width: centerWidth,
height: height - HEADER_HEIGHT,
devicePixelRatio
};
const core = new Core(ref.current, options);
core.use(MiddlewareScroller);
core.use(MiddlewareSelector);
core.setData(data);
refCore.current = core;
}
}
}, []);
useEffect(() => {
const prevWidth = leftWidth + centerWidth + rightWidth;
let newLeftWidth = Math.floor(width * (leftWidth / prevWidth));
@ -69,20 +46,6 @@ export const Dashboard = (props: DashboardProps) => {
setCenterWidth(newCenterWidth);
}, [height, width]);
useEffect(() => {
if (!refCore?.current) {
return;
}
const core = refCore.current;
const contextSize = calcElementsContextSize(data.elements, { viewWidth: width, viewHeight: height });
core.resize({
width: centerWidth,
height: height - HEADER_HEIGHT,
devicePixelRatio,
...contextSize
});
}, [height, centerWidth]);
return (
<div className={classnames(prefixName(), className)} style={{ ...style, ...{ width, height, padding: 0 } }}>
<div className={prefixName('header')} style={{ height: HEADER_HEIGHT }}>
@ -108,7 +71,7 @@ export const Dashboard = (props: DashboardProps) => {
<PanelLayer className={prefixName('left')} />
</div>
<div style={{ width: centerWidth + rightWidth, display: 'flex', flexDirection: 'row' }}>
<div ref={ref} className={prefixName('center')} style={{ width: centerWidth, height: height - HEADER_HEIGHT }}></div>
<Sketch className={prefixName('center')} width={centerWidth} height={height - HEADER_HEIGHT} />
<div className={prefixName('right')} style={{ width: rightWidth, height: height - HEADER_HEIGHT }}>
Right
</div>

View file

@ -0,0 +1,68 @@
import React, { useEffect, useRef, useContext } from 'react';
import classnames from 'classnames';
import { Core, MiddlewareScroller, MiddlewareSelector } from '@idraw/core';
import { calcElementsContextSize } from '@idraw/util';
import { createPrefixName } from '../../css';
import { Context } from '../../context';
import type { CSSProperties } from 'react';
const modName = 'mod-sketch';
const prefixName = createPrefixName(modName);
export interface DashboardProps {
className?: string;
style?: CSSProperties;
width: number;
height: number;
}
export const Sketch = (props: DashboardProps) => {
const ref = useRef<HTMLDivElement>(null);
const refCore = useRef<Core | null>(null);
const { className, style, width, height } = props;
const devicePixelRatio = window.devicePixelRatio;
const { state } = useContext(Context);
useEffect(() => {
if (ref?.current) {
if (!refCore?.current) {
const options = {
width,
height,
devicePixelRatio
};
const core = new Core(ref.current, options);
core.use(MiddlewareScroller);
core.use(MiddlewareSelector);
core.setData(state.viewDrawData);
refCore.current = core;
}
}
}, []);
useEffect(() => {
if (!refCore?.current) {
return;
}
const core = refCore.current;
const contextSize = calcElementsContextSize(state.viewDrawData.elements, { viewWidth: width, viewHeight: height });
core.resize({
width,
height,
devicePixelRatio,
...contextSize
});
}, [height, width]);
useEffect(() => {
if (!refCore?.current || !state.viewDrawData) {
return;
}
const core = refCore.current;
core.setData(state.viewDrawData);
}, [state.viewDrawData]);
return <div ref={ref} className={classnames(prefixName(), className)} style={{ ...style, ...{ width, height, padding: 0 } }}></div>;
};

View file

@ -4,8 +4,8 @@ import { DesignData, DesignDrawDataType } from './data';
export interface DesignState {
activeDrawDataType: DesignDrawDataType;
designData: DesignData | null;
viewDrawData: Data | null;
designData: DesignData;
viewDrawData: Data;
viewDrawUUID: string | null;
themeMode: 'light' | 'dark';
}