Skip to content

Commit

Permalink
Update README, and format the fixture data of examples
Browse files Browse the repository at this point in the history
  • Loading branch information
Fatih Erikli committed Feb 6, 2016
1 parent c1c8bf2 commit 0ccc3ca
Show file tree
Hide file tree
Showing 12 changed files with 238 additions and 60 deletions.
170 changes: 168 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,169 @@
react-designer
=====================
React-designer
==============

Easy to configure, lightweight, editable vector graphics in your react components.

- Supports polygon and shape designing (with bezier curves)
- Implemented default scale, rotate, drag, and arrange actions
- Custom object types and custom panels


Examples and demonstration:
<http://fatiherikli.github.io/react-designer>

![bezier editor](http://i.imgur.com/cqTleWB.gif)

### Component: Designer

This is the main canvas component which holds the all toolset and manages all drawing data. You could use this component to create drawing canvas.

An example with default configuration:

import Designer, {Text, Rectangle} from 'react-designer';

class App() {
state = {
objects: [
{type: "text", x: 10, y: 20, text: "Hello!", fill: "red"},
{type: "rect", x: 50, y: 70, fill: "red"}
]
}

render() {
return (
<Designer width={250} height={350}
objectTypes={{
'text': Text,
'rect': Rect
}}
onUpdate={(objects) => this.setState({objects})}
objects={this.state.objects} />
)
}
}

The `Designer` component expects the following parameters:

| Parameter | Default | |
| :------------- |:------------------------------- | :----- |
| width | 300 | The width of document |
| height | 300 | The height of document |
| canvasWidth | null | The width of canvas. Same with document if it's null. |
| canvasHeight | null | The height of canvas. Same with document if it's null. |
| objects | [] | Your object set. |
| onUpdate | [] | Your update callback. |
| objectTypes | Text, Circle, Rectangle, Path | Mapping of object types. |
| snapToGrid | 1 | Snaps the objects accordingly this multipier. |


Object types are pure react components which are derived from `Vector`.

### Component: Vector

You can create an object type by subclassing `Vector` component. Each object types have static `meta` object which contains `icon` and `initial`, and optionally `editor` value.

Example implementation:

class MyRectangle extends Vector {
static meta = {
icon: <Icon icon={'rectangle'} size={30} />,
initial: {
width: 5,
height: 5,
strokeWidth: 0,
fill: "yellow",
radius: 5,
blendMode: "normal"
}
};

render() {
let {object, index} = this.props;
return (
<rect style={this.getStyle()}
{...this.getObjectAttributes()}
rx={object.radius}
width={object.width}
height={object.height} />
);
}
}

You can register this object type in your `Designer` instance.

<Designer
objectTypes={{rectangle: MyRectangle}}
width={500}
height={500}
onUpdate={...}
objects={...}
onUpdate={...} />

Apart from meta options, the vectors have `panels` static definition which contains the available panels of their.

Here is default panels in Vector component:

static panels = [
SizePanel,
TextPanel,
StylePanel,
ArrangePanel
];

### Component: Panel

You could extend this component to create completely different panel instead of builtins.

It's a pure React component. The component have `object` and `onUpdate` props. You could reach the current state with `object`, and change this state with `onChange` callback. Let's create a dummy panel.

class MyPanel extends Panel {
render() {
let {object, onChange} = this.props;
return (
<PropertyGroup>
<Columns label="Colors">
<Column>
<Button onClick={() => {onChange('color', 'blue')}}>
Make blue
</Button>
</Column>
<Column>
<Button onClick={() => {onChange('color', 'yellow')}}>
Make Yellow
</Button>
</Column>
</Columns>
</PropertyGroup>
);
}
}

### Component: Preview

You can use `Preview` component to disable editing tool set and controllers. This component just renders the SVG output of your data. It may be useful for presenting edited or created graphic, instead of building a SVG file.

The parameters are same with Designer component, except the onUpdate callback is not necessarry.

<Preview
objectTypes={{rectangle: MyRectangle}}
objects={this.state.objects}
height={500}
width={500} />

### To-do

I built this project to create user designed areas in my side project. So, this was a just hobby project, there may be things missing for a svg editor. I'm open to pull requests and feedback, and I need help to maintain.

Here is a todo list that in my mind. You could extend this list.

- Implement `Export` panel
- Export selected object
- Export document
- Write initial tests and setup test environment
- Add a key map to keep the ratio of objects when scaling
- Implement theme support for UI

### Contributors (You can add your name here in your pull-request)

- Fatih Erikli <fatiherikli@gmail.com>

22 changes: 11 additions & 11 deletions examples/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ export default class App extends Component {
<div className={classes.container}>
<div className={classes.landing}>
<h1>react-designer</h1>
<h2>Configurable design component for react</h2>
<h2>Easy to configure, lightweight, editable vector graphics in your react components.</h2>
<ul className={classes.nav}>
<li className={classes.current}><a href="#">usage</a></li>
<li><a href="#">examples</a></li>
<li><a href="#">docs</a></li>
<li><a href="#">show on github</a></li>
<li><a href="#examples">examples</a></li>
<li><a href="http://github.com/fatiherikli/react-designer">docs</a></li>
<li><a href="http://github.com/fatiherikli/react-designer">show on github</a></li>
</ul>
</div>
<div className={classes.usage}>
Expand Down Expand Up @@ -54,15 +54,15 @@ class App() {
}
`}</pre>
</div>
<h4 className={classes.mainTitle}>Examples</h4>
<h4 id="examples" className={classes.mainTitle}>Examples</h4>
<div className={classes.example}>
<div className={classes.info}>
<h3>Mondrian</h3>
<p>Default configuration with initial rectangle objects set on the internal state of
container component.</p>
<p>Enabled all default drawing tool set and panels.</p>
<p>
<a href="#">Show example on github</a>
<a href="https://github.com/fatiherikli/react-deisnger/tree/master/examples/components/">Show example on github</a>
</p>
</div>
<div className={classes.preview}>
Expand All @@ -78,7 +78,7 @@ class App() {

<p>You can double-click to edit shapes.</p>
<p>
<a href="#">Show example on github</a>
<a href="https://github.com/fatiherikli/react-deisnger/tree/master/examples/components/">Show example on github</a>
</p>
</div>
<div className={classes.preview}>
Expand All @@ -93,7 +93,7 @@ class App() {
container component.</p>

<p>
<a href="#">Show example on github</a>
<a href="https://github.com/fatiherikli/react-deisnger/tree/master/examples/components/">Show example on github</a>
</p>
</div>
<div className={classes.preview}>
Expand All @@ -119,7 +119,7 @@ class App() {
<p>You can extend builtin components, or write entirely different objects</p>

<p>
<a href="#">Show example on github</a>
<a href="https://github.com/fatiherikli/react-deisnger/tree/master/examples/components/">Show example on github</a>
</p>
</div>
<div className={classes.preview}>
Expand All @@ -138,8 +138,8 @@ class App() {
For example price is instantly changing while you resizing objects or typing a text.</p>

<p>
<a href="#">Show example on github</a> <br />
<a href="#">Show calculatePrice() function</a>
<a href="https://github.com/fatiherikli/react-deisnger/tree/master/examples/components/">Show example on github</a> <br />
<a href="https://github.com/fatiherikli/react-deisnger/tree/master/examples/components/">Show calculatePrice() function</a>
</p>
</div>
<div className={classes.preview}>
Expand Down
26 changes: 0 additions & 26 deletions examples/components/Malevich.js
Original file line number Diff line number Diff line change
Expand Up @@ -299,32 +299,6 @@ export default class extends Component {
"type": "polygon",
"x": 135,
"y": 120.5625
}, {
"fill": "rgba(178, 115, 33, 1)",
"closed": true,
"rotate": 0,
"moveX": 133,
"moveY": 4.5625,
"path": [{"x1": 133, "y1": 4.5625, "x2": 290, "y2": 338.5625, "x": 290, "y": 338.5625}, {
"x1": 290,
"y1": 338.5625,
"x2": 349,
"y2": 309.5625,
"x": 349,
"y": 309.5625
}, {"x1": 349, "y1": 309.5625, "x2": 349, "y2": 208.5625, "x": 349, "y": 208.5625}, {
"x1": 349,
"y1": 208.5625,
"x2": 255,
"y2": 3.5625,
"x": 255,
"y": 3.5625
}, {"x1": 255, "y1": 3.5625, "x2": 133, "y2": 4.5625, "x": 133, "y": 4.5625}],
"stroke": "gray",
"strokeWidth": "0",
"type": "polygon",
"x": 131,
"y": 1.5625
}, {
"fill": "rgba(133, 34, 8, 1)",
"closed": true,
Expand Down
4 changes: 2 additions & 2 deletions examples/components/MockupDesigner.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export class _Input extends Vector {
};
return (
<g>
<text fill={"black"} x={object.x} y={object.y}
<text fill={"black"} x={object.x} y={object.y}
style={style} textAnchor="left" fontSize={object.fontSize}
fontFamily={object.fontFamily}>{object.text}</text>
<rect style={this.getStyle()}
Expand Down Expand Up @@ -275,7 +275,7 @@ export default class extends Component {
'fieldset': Fieldset
}}
objects={this.state.objects}
onUpdate={this.handleUpdate.bind(this)} />
onUpdate={this.handleUpdate.bind(this)}/>
<p>
<a href="#" onClick={this.download.bind(this)}>Export SVG</a>
</p>
Expand Down
55 changes: 45 additions & 10 deletions examples/components/TshirtDesigner.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, {Component} from 'react';
import Designer, {styles as designerStyles} from '../../src/Designer';
import Designer from '../../src/Designer';
import {styles as canvasStyles} from '../../src/SVGRenderer';
import {Text, Rect, Circle} from '../../src/objects/index';

const priceMap = {
Expand All @@ -8,10 +9,8 @@ const priceMap = {
'circle': ({width, height}) => width * (height || width) * 0.001
};

const calculatePrice = (
objects,
initialCost = 5
) => (
const calculatePrice = (objects,
initialCost = 5) => (
objects.map(
({type, ...rest}) =>
priceMap[type](rest)
Expand All @@ -24,7 +23,7 @@ const calculatePrice = (
const Background = ({style}) => (
<svg width="350" height="400" style={{
position: "absolute",
...designerStyles.grid
...canvasStyles.grid
}}>
<path d="
M 75 80
Expand All @@ -41,15 +40,51 @@ const Background = ({style}) => (
C 74 182.28125, 57 187.28125, 57 187.28125
C 57 187.28125, 21 142.28125, 21 142.28125
C 21 142.28125, 75 80, 75 80
Z" style={style} />
Z" style={style}/>
</svg>
);

export default class extends Component {

state = {
objects: [
{"text":"COME TO THE","rotate":0,"fontWeight":"bold","fontStyle":"normal","textDecoration":"none","fill":"rgba(11, 10, 10, 1)","fontSize":"20","fontFamily":"AmericanTypewriter, Georgia, serif","type":"text","x":175,"y":153},{"text":"REACT","rotate":0,"fontWeight":"bold","fontStyle":"normal","textDecoration":"none","fill":"rgba(0, 0, 0, 1)","fontSize":"47","fontFamily":"AmericanTypewriter, Georgia, serif","type":"text","x":176,"y":183},{"text":"SIDE","rotate":0,"fontWeight":"bold","fontStyle":"normal","textDecoration":"none","fill":"rgba(0, 0, 0, 1)","fontSize":"25","fontFamily":"AmericanTypewriter, Georgia, serif","type":"text","x":171,"y":216}
{
"text": "COME TO THE",
"rotate": 0,
"fontWeight": "bold",
"fontStyle": "normal",
"textDecoration": "none",
"fill": "rgba(11, 10, 10, 1)",
"fontSize": "20",
"fontFamily": "AmericanTypewriter, Georgia, serif",
"type": "text",
"x": 175,
"y": 153
}, {
"text": "FRONT",
"rotate": 0,
"fontWeight": "bold",
"fontStyle": "normal",
"textDecoration": "none",
"fill": "rgba(0, 0, 0, 1)",
"fontSize": "47",
"fontFamily": "AmericanTypewriter, Georgia, serif",
"type": "text",
"x": 176,
"y": 183
}, {
"text": "END",
"rotate": 0,
"fontWeight": "bold",
"fontStyle": "normal",
"textDecoration": "none",
"fill": "rgba(0, 0, 0, 1)",
"fontSize": "25",
"fontFamily": "AmericanTypewriter, Georgia, serif",
"type": "text",
"x": 171,
"y": 216
}
]
};

Expand All @@ -64,7 +99,7 @@ export default class extends Component {
fill: "#fff989",
stroke: "#808080",
strokeWidth: 2
}} />
}}/>
<Designer
width={350} height={400}
objectTypes={{
Expand All @@ -81,7 +116,7 @@ export default class extends Component {
fontFamily: "monaco, monospace",
color: "#494949"
}}>
Price: {calculatePrice(this.state.objects).toFixed(2)}$
Tshirt Price: {calculatePrice(this.state.objects).toFixed(2)}$
</div>
</div>
);
Expand Down
Loading

0 comments on commit 0ccc3ca

Please sign in to comment.