Skip to content

Commit

Permalink
optimized rendering raw svg
Browse files Browse the repository at this point in the history
  • Loading branch information
AmKreta committed Apr 16, 2022
1 parent 1548e9f commit 19d40f0
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 252 deletions.
3 changes: 2 additions & 1 deletion src/actions/pages/pages.actionTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,6 @@ export enum PAGES_ACTION_TYPES {
SAVE_FILE_AS = 'SAVE_FILE_AS',
CREATE_NEW_FILE = 'CREATE_NEW_FILE',
OPEN_A_FILE = 'OPEN_A_FILE',
EDIT_SVG_STYLE = 'EDIT_SVG_STYLE'
EDIT_SVG_STYLE = 'EDIT_SVG_STYLE',
UPDATE_CURRENT_PAGE_SNAPSHOT = 'UPDATE_CURRENT_PAGE_SNAPSHOT'
};
4 changes: 4 additions & 0 deletions src/actions/pages/pages.actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,4 +244,8 @@ export const createNewFile = function (json?: CREATE_NEW_FILE_PAYLOAD): CREATE_N

export const editSvgStyle = function (style: EDIT_SVG_STYLE_PAYLOAD): EDIT_SVG_STYLE_ACTION {
return { type: PAGES_ACTION_TYPES.EDIT_SVG_STYLE, payload: style };
}

export function updateCurrentPageSnapshot() {
return { type: PAGES_ACTION_TYPES.UPDATE_CURRENT_PAGE_SNAPSHOT };
}
3 changes: 2 additions & 1 deletion src/actions/pages/pages.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ export interface PAGES {
gradients: { [key: string]: GRADIENT },
images: { [key: string]: string },
name: string,
id: string
id: string,
snapshots: string[]
};

interface ACTION<Type, Payload> {
Expand Down
2 changes: 1 addition & 1 deletion src/components/landingPage/projects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const Projects: React.FC = function () {
</div>
<span data-index={index} onClick={openProject}>
<RenderRawSvg
shapes={pages.pages[0].shapes}
innerHtml={pages.snapshots[0]}
key={pages.id}
width={'22vw'}
style={{ margin: '8px' }}
Expand Down
14 changes: 11 additions & 3 deletions src/components/uiEditor/editorHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { SHAPE_TYPES, ToolBarOptions, TOOLS } from '../../utils/constant';
import Icon from '../icon.component';
import { THEME } from '../../theme/theme';
import { useDispatch, useSelector } from 'react-redux';
import { setActiveTool } from '../../actions/pages/pages.actions';
import { setActiveTool, updateCurrentPageSnapshot } from '../../actions/pages/pages.actions';
import { State } from '../../store/store';
import { getActiveTool } from '../../selector/selector';
import ColorPalette from './colorPalette';
Expand Down Expand Up @@ -44,14 +44,22 @@ const EditorHeader: React.FC<{}> = function () {
setActiveOption(prevSelectedTab.current!);
}

function togglePages() {
if (!showPages) {
dispatch(updateCurrentPageSnapshot());
}

setShowPages(prevState => !prevState);
}

return (
<StyledHeader>
<nav>
<div style={{ position: "relative" }}>
<span onClick={() => setShowPages(prevState => !prevState)} style={{ textDecoration: showPages ? 'underline' : 'none' }}>Pages</span>
<span onClick={togglePages} style={{ textDecoration: showPages ? 'underline' : 'none' }}>Pages</span>
{
showPages
? <Pages closePages={() => setShowPages(prevState => !prevState)}/>
? <Pages closePages={togglePages} />
: null
}
</div>
Expand Down
10 changes: 5 additions & 5 deletions src/components/uiEditor/pages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ import { MdRemoveCircle, MdAddCircle } from 'react-icons/md';
import { useSelector, useDispatch } from 'react-redux';
import { State } from '../../store/store';
import { SHAPE_COLLECTION } from '../../actions/pages/pages.interface';
import { getActivePageIndex, getCurrentPage } from '../../selector/selector';
import { getActivePageIndex, getCurrentDocumentSnapshots, getCurrentPage } from '../../selector/selector';
import RenderRawSvg from './renderRawSvg';
import { addPage, removePage, setActivePage } from '../../actions/pages/pages.actions';

interface props {
closePages: () => void;
}

const Pages: React.FC<props> = function ({ closePages }) {
const pages = useSelector<State, SHAPE_COLLECTION[]>(getCurrentPage);
const actiivePageIndex = useSelector<State, number>(getActivePageIndex);
const snapShots = useSelector(getCurrentDocumentSnapshots);
const dispatch = useDispatch();

const handleAdd = function () {
Expand Down Expand Up @@ -45,10 +45,10 @@ const Pages: React.FC<props> = function ({ closePages }) {
</div>
<div className='pageCollection'>
{
pages.map((page, index) => (
snapShots.map((snapShot, index) => (
<RenderRawSvg
key={page.id}
shapes={page.shapes}
key={index}
innerHtml={snapShot}
isActive={actiivePageIndex === index}
clickHandler={changePage}
index={index}
Expand Down
244 changes: 7 additions & 237 deletions src/components/uiEditor/renderRawSvg.tsx
Original file line number Diff line number Diff line change
@@ -1,229 +1,19 @@
import React, { useRef } from 'react';
import { AVAILABLE_SHAPES } from '../../shapes/availableShapes';
import React from 'react';
import styled, { css } from 'styled-components';
import { THEME } from '../../theme/theme';
import { SHAPE_TYPES } from '../../utils/constant';
import { CIRCLE_SHAPE } from '../../shapes/circle';
import { getBoundingRectMidPoint, getStyleObj, getTransformOrigin } from '../../utils/utils';
import { RECTANGLE_SHAPE } from '../../shapes/rectangle';
import { POLYGON_SHAPE } from '../../shapes/polygon';
import { POLYLINE_SHAPE } from '../../shapes/polyline';
import { IMAGE_SHAPE } from '../../shapes/image';
import { LINE_SHAPE } from '../../shapes/line';
import { ELLIPSE_SHAPE } from '../../shapes/ellipse';
import { TEXT_SHAPE } from '../../shapes/text';
import { PATH_SHAPE } from '../../shapes/path';
import { GROUP_SHAPE } from '../../shapes/group';
import { useSelector } from 'react-redux';
import { State } from '../../store/store';

interface props {
shapes: {
[key: string]: AVAILABLE_SHAPES
},
innerHtml: string
isActive?: boolean,
clickHandler?: React.MouseEventHandler<SVGSVGElement> | undefined;
index?: number;
height?: number | string;
width?: number | string;
viewbox?: string;
style?:any;
style?: any;
}

const RenderRaw: React.FC<{ s: AVAILABLE_SHAPES }> = function ({ s }) {
const ref = useRef<any>(null);
switch (s.type) {
case SHAPE_TYPES.CIRCLE: {
const shape = s as CIRCLE_SHAPE;
return (
<circle
cx={`${shape.x}${shape.x_unit}`}
cy={`${shape.y}${shape.y_unit}`}
r={`${shape.radius}${shape.radius_unit}`}
id={shape.id}
{...getStyleObj(shape.style)}
transform-origin={`${shape.x} ${shape.y}`}
/>
);
}
case SHAPE_TYPES.RECTANGLE: {
const shape = s as RECTANGLE_SHAPE;
return (
<rect
x={shape.x}
y={shape.y}
height={shape.height}
width={shape.width}
{...getStyleObj(shape.style)}
transform-origin={`${shape.x + shape.width / 2} ${shape.y + shape.height / 2}`}
rx={shape.rx}
ry={shape.ry}
/>
);
}

case SHAPE_TYPES.POLYGON: {
const shape = s as POLYGON_SHAPE;
const transformOrigin = getBoundingRectMidPoint(ref.current?.getBBox());
return (
<polygon
id={shape.id}
{...getStyleObj(shape.style)}
points={shape.points.toString()}
transform-origin={`${transformOrigin.x} ${transformOrigin.y}`}
ref={ref}
/>
);
}

case SHAPE_TYPES.POLYLINE: {
const shape = s as POLYLINE_SHAPE;
const transformOrigin = getBoundingRectMidPoint(ref.current?.getBBox());
return (
<polyline
id={shape.id}
{...getStyleObj(shape.style)}
points={shape.points.toString()}
transform-origin={`${transformOrigin.x} ${transformOrigin.y}`}
key={shape.id}
ref={ref}
/>
);
}

case SHAPE_TYPES.IMAGE: {
const shape = s as IMAGE_SHAPE;
return (
<image
x={shape.x}
y={shape.y}
height={shape.height}
width={shape.width}
{...getStyleObj(shape.style)}
transform-origin={`${shape.x + shape.width / 2} ${shape.y + shape.height / 2}`}
href={shape.base64Url}
/>
);
}

case SHAPE_TYPES.LINE: {
const shape = s as LINE_SHAPE;
const [[x1, y1], [x2, y2]] = shape.points;
const transformOrigin = getTransformOrigin(shape.points);
return (
<line
{...getStyleObj(shape.style)}
x1={x1}
y1={y1}
x2={x2}
y2={y2}
transform-origin={transformOrigin}
/>
);
}

case SHAPE_TYPES.ELLIPSE: {
const shape = s as ELLIPSE_SHAPE;
return (
<ellipse
cx={shape.x}
cy={shape.y}
rx={shape.radiusX}
ry={shape.radiusY}
{...getStyleObj(shape.style)}
transform-origin={`${shape.x} ${shape.y}`}
/>
);
}

case SHAPE_TYPES.TEXT: {
const shape = s as TEXT_SHAPE;
const textMidPoint = getBoundingRectMidPoint(ref.current?.getBBox());
return (
<text
x={shape.x}
y={shape.y}
{...getStyleObj(shape.style)}
transform-origin={`${textMidPoint.x} ${textMidPoint.y}`}
fontSize={shape.fontSize}
fontWeight={shape.fontWeight}
fontStyle={shape.fontStyle}
font-family={`${shape.fontFamily}, ${shape.genericFontFamily}`}
ref={ref}
>
{shape.text}
</text>
);
}

case SHAPE_TYPES.PATH: {
const shape = s as PATH_SHAPE;
const transformOrigin = getBoundingRectMidPoint(ref.current?.getBBox());
return (
<path
id={shape.id}
{...getStyleObj(shape.style)}
d={(function () {
let [p1, ...p] = shape.points || [[0, 0], [0, 0]];
if (p1 && p) {
return `M ${p1[0]} ${p1[1]} C ${p.toString()} Z`;
}
return '';
})()}
transform-origin={`${transformOrigin.x} ${transformOrigin.y}`}
ref={ref}
/>
);
}

case SHAPE_TYPES.GROUP: {
const shape = s as GROUP_SHAPE;
const groupMidPoint = getBoundingRectMidPoint(ref.current?.getBBox());
return (
<g
id={shape.id}
{...getStyleObj(shape.style)}
transform-origin={`${groupMidPoint.x} ${groupMidPoint.y}`}
ref={ref}
>

</g>
);
}

default: return null;
}
}

const RenderRawGroup: React.FC<{ s: GROUP_SHAPE }> = function ({ s }) {
const ref = useRef<any>(null);
const groupMidPoint = getBoundingRectMidPoint(ref.current?.getBBox());

const children = useSelector<State, AVAILABLE_SHAPES[]>(state => {
const childrenIds = (state.page.pages[state.page.activePageIndex].shapes[s.id] as GROUP_SHAPE).children;
return childrenIds.map(id => state.page.pages[state.page.activePageIndex].shapes[id]);
});

return (
<g
id={s.id}
{...getStyleObj(s.style)}
transform-origin={`${groupMidPoint.x} ${groupMidPoint.y}`}
ref={ref}
>
{
children.map(child => {
if (child.type === SHAPE_TYPES.GROUP) {
return <RenderRawGroup s={child as GROUP_SHAPE} />
}
return <RenderRaw s={child} />
})
}
</g>
);
}

const RenderRawSvg: React.FC<props> = function ({ shapes, isActive = false, clickHandler, index, height, width, viewbox,style }) {
const RenderRawSvg: React.FC<props> = function ({ innerHtml, isActive = false, clickHandler, index, height, width, viewbox, style }) {
return (
<StyledSvg
viewBox={viewbox || '0 0 1175 580'}
Expand All @@ -233,35 +23,15 @@ const RenderRawSvg: React.FC<props> = function ({ shapes, isActive = false, clic
isActive={isActive}
data-index={index}
style={style}
>
{
(function () {
const shapesToDraw: any = [];
for (let id in shapes) {
if (shapes[id].render) {
if (shapes[id].type === SHAPE_TYPES.GROUP) {
shapesToDraw.push(
<RenderRawGroup s={shapes[id] as GROUP_SHAPE} />
)
}
else {
shapesToDraw.push(
<RenderRaw s={shapes[id]} />
);
}
}
}
return shapesToDraw;
})()
}
</StyledSvg>
dangerouslySetInnerHTML={{ __html: innerHtml }}
/>
);
}

export default RenderRawSvg;


const StyledSvg = styled.svg<{ isActive: boolean, width: number | string |undefined }>`
const StyledSvg = styled.svg<{ isActive: boolean, width: number | string | undefined }>`
${props => {
const theme = props.theme as THEME;
return css`
Expand Down
Loading

0 comments on commit 19d40f0

Please sign in to comment.