mirror of
https://github.com/idrawjs/idraw
synced 2026-05-24 10:08:34 +00:00
feat: update sketch logic
This commit is contained in:
parent
05ef32667a
commit
6061cffa34
6 changed files with 101 additions and 55 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
7
packages/design/src/css/modules/sketch.less
Normal file
7
packages/design/src/css/modules/sketch.less
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
@import '../variable.less';
|
||||
|
||||
@mod-xxx: ~'@{prefix}-mod-sketch';
|
||||
|
||||
.@{mod-xxx} {
|
||||
border: 1px solid #f0f0f0;
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
68
packages/design/src/modules/sketch/index.tsx
Normal file
68
packages/design/src/modules/sketch/index.tsx
Normal 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>;
|
||||
};
|
||||
|
|
@ -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';
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue