├── .gitignore ├── .babelrc ├── src ├── index.js ├── elements.js └── utils.js ├── lib ├── index.js ├── utils.js └── elements.js ├── .eslintrc.json ├── LICENSE ├── package.json ├── images └── snapshot.svg └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .DS_Store -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ['es2015', 'stage-2', 'react'] 3 | } -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | const Raphael = require("raphael"); 2 | const Utils = require("./utils"); 3 | 4 | const { 5 | Paper, 6 | Set, 7 | Circle, 8 | Ellipse, 9 | Image, 10 | Path, 11 | Print, 12 | Rect, 13 | Text, 14 | Line, 15 | Element 16 | } = require("./elements"); 17 | 18 | exports.Raphael = Raphael; 19 | exports.Utils = Utils; 20 | exports.Paper = Paper; 21 | exports.Set = Set; 22 | exports.Element = Element; 23 | exports.Circle = Circle; 24 | exports.Ellipse = Ellipse; 25 | exports.Image = Image; 26 | exports.Path = Path; 27 | exports.Print = Print; 28 | exports.Rect = Rect; 29 | exports.Text = Text; 30 | exports.Line = Line; 31 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var Raphael = require("raphael"); 4 | var Utils = require("./utils"); 5 | 6 | var _require = require("./elements"), 7 | Paper = _require.Paper, 8 | Set = _require.Set, 9 | Circle = _require.Circle, 10 | Ellipse = _require.Ellipse, 11 | Image = _require.Image, 12 | Path = _require.Path, 13 | Print = _require.Print, 14 | Rect = _require.Rect, 15 | Text = _require.Text, 16 | Line = _require.Line, 17 | Element = _require.Element; 18 | 19 | exports.Raphael = Raphael; 20 | exports.Utils = Utils; 21 | exports.Paper = Paper; 22 | exports.Set = Set; 23 | exports.Element = Element; 24 | exports.Circle = Circle; 25 | exports.Ellipse = Ellipse; 26 | exports.Image = Image; 27 | exports.Path = Path; 28 | exports.Print = Print; 29 | exports.Rect = Rect; 30 | exports.Text = Text; 31 | exports.Line = Line; -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "commonjs": true, 5 | "es6": true 6 | }, 7 | "extends": ["airbnb", "eslint:recommended"], 8 | "installedESLint": true, 9 | "parserOptions": { 10 | "ecmaFeatures": { 11 | "experimentalObjectRestSpread": true, 12 | "jsx": true 13 | }, 14 | "sourceType": "module" 15 | }, 16 | "plugins": [ 17 | "react" 18 | ], 19 | "rules": { 20 | "import/no-extraneous-dependencies": 1, 21 | "no-case-declarations": 1, 22 | "react/no-did-mount-set-state": 1, 23 | "react/no-string-refs": 1, 24 | "react/no-find-dom-node": 0, 25 | "react/prop-types": 0, 26 | "react/no-multi-comp": 0, 27 | "react/no-unused-prop-types": 1, 28 | "react/jsx-filename-extension": 0, 29 | "react/forbid-prop-types": 0, 30 | "indent": [ 31 | "error", 32 | 4 33 | ], 34 | "linebreak-style": [ 35 | "error", 36 | "unix" 37 | ], 38 | "quotes": [ 39 | "error", 40 | "double" 41 | ], 42 | "semi": [ 43 | "error", 44 | "always" 45 | ] 46 | } 47 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 刘红 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-raphael", 3 | "version": "0.9.0", 4 | "description": "reactify raphael", 5 | "main": "./lib", 6 | "files": [ 7 | "lib" 8 | ], 9 | "scripts": { 10 | "test": "test", 11 | "clean": "rm -rf ./lib", 12 | "build": "npm run clean & NODE_ENV=production babel ./src --out-dir ./lib" 13 | }, 14 | "devDependencies": { 15 | "babel-cli": "^6.24.1", 16 | "babel-loader": "^7.1.0", 17 | "babel-preset-es2015": "^6.24.1", 18 | "babel-preset-react": "^6.24.1", 19 | "babel-preset-stage-2": "^6.24.1", 20 | "eslint": "^3.13.1", 21 | "eslint-config-airbnb": "^14.0.0", 22 | "eslint-plugin-import": "^2.2.0", 23 | "eslint-plugin-jsx-a11y": "^3.0.2", 24 | "eslint-plugin-react": "^6.9.0", 25 | "prop-types": "^15.5.10", 26 | "raphael": "^2.2.6", 27 | "react": "^15.6.1", 28 | "react-dom": "^15.6.1" 29 | }, 30 | "repository": { 31 | "type": "git", 32 | "url": "git+https://github.com/liuhong1happy/react-raphael.git" 33 | }, 34 | "keywords": [ 35 | "react", 36 | "raphael", 37 | "react-raphael", 38 | "react-component" 39 | ], 40 | "author": "Holly Liu", 41 | "license": "MIT", 42 | "bugs": { 43 | "url": "https://github.com/liuhong1happy/react-raphael/issues" 44 | }, 45 | "homepage": "https://github.com/liuhong1happy/react-raphael#readme" 46 | } 47 | -------------------------------------------------------------------------------- /images/snapshot.svg: -------------------------------------------------------------------------------- 1 | Created with Raphaël 2.2.0同一个世界 同一个梦想One World One Dream -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-raphael 2 | 3 | [![Version](https://img.shields.io/npm/v/react-raphael.svg)](https://www.npmjs.com/package/react-raphael) 4 | [![Downloads](https://img.shields.io/npm/dt/react-raphael.svg)](https://www.npmjs.com/package/react-raphael) 5 | 6 | reactify raphael 7 | 8 | ## Install 9 | 10 | # or specify the externals in webpack config 11 | npm install --save raphael 12 | # install react-raphael in your react-raphael project 13 | npm install --save react-raphael 14 | 15 | ## Example 16 | 17 | - [react-raphael-example](https://github.com/liuhong1happy/react-raphael-example) 18 | - [react-raphael-map](https://github.com/liuhong1happy/react-raphael-map) 19 | - [react-raphael-chart](https://github.com/liuhong1happy/react-raphael-chart) 20 | - [react-raphael-workflow](https://github.com/liuhong1happy/react-raphael-workflow) 21 | - [react-raphael-scrawl](https://github.com/liuhong1happy/react-raphael-scrawl) 22 | - [react-raphael-mine-sweeping](https://github.com/liuhong1happy/react-raphael-mine-sweeping) 23 | 24 | ## Quickly Start 25 | 26 | ```js 27 | var React = require('react'); 28 | var ReactDOM = require('react-dom'); 29 | 30 | const {Raphael,Paper,Set,Circle,Ellipse,Image,Rect,Text,Path,Line} = require('react-raphael'); 31 | 32 | class App extends React.Component{ 33 | render(){ 34 | var data = [ 35 | {x:50,y:50,r:40,attr:{"stroke":"#0b8ac9","stroke-width":5},animate:Raphael.animation({cx:60},500,"<>")}, 36 | {x:100,y:100,r:40,attr:{"stroke":"#f0c620","stroke-width":5},animate:Raphael.animation({cx:105},500,"<>")}, 37 | {x:150,y:50,r:40,attr:{"stroke":"#1a1a1a","stroke-width":5}}, 38 | {x:200,y:100,r:40,attr:{"stroke":"#10a54a","stroke-width":5},animate:Raphael.animation({cx:195},500,"<>")}, 39 | {x:250,y:50,r:40,attr:{"stroke":"#e11032","stroke-width":5},animate:Raphael.animation({cx:240},500,"<>")} 40 | ] 41 | return ( 42 | 43 | { 44 | data.map(function(ele,pos){ 45 | return () 46 | }) 47 | } 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | ")} attr={{"stroke":"#fff"}}/> 56 | ")} attr={{"stroke":"#fff"}}/> 57 | 58 | ) 59 | } 60 | } 61 | ``` 62 | 63 | ## Snapshot 64 | 65 | ![snapshot.png](images/snapshot.svg) 66 | 67 | ## API 68 | 69 | #### All Element Props 70 | 71 | - Paper 72 | - width `number` width of the canvas. 73 | - height `number` height of the canvas. 74 | - container `object` props of the canvas's container.`default value: { style:{}, className:"" }` 75 | - Element 76 | - attr `object` Sets the attributes of the element. 77 | - animate `object` Creates and starts animation for given element. 78 | - animateWith `object` Acts similar to Element.animate, but ensure that given animation runs in sync with another given element. 79 | - click `function` Adds event handler for click for the element. 80 | - data `object` Adds or retrieves given value asociated with given key. 81 | - dblclick `function` Adds event handler for double click for the element. 82 | - drag `object` Adds event handlers for drag of the element. `object {move,start,end,mcontext,scontext,econtext}` 83 | - glow `function` Return set of elements that create glow-like effect around given element. 84 | - hover `object` Adds event handlers for hover for the element. `object {in,out,icontext,ocontext}` 85 | - hide `boolean` Makes element invisible. 86 | - mousedown `function` Adds event handler for mousedown for the element. 87 | - mousemove `function` Adds event handler for mousemove for the element. 88 | - mouseout `function` Adds event handler for mouseout for the element. 89 | - mouseover `function` Adds event handler for mouseover for the element. 90 | - mouseup `function` Adds event handler for mouseup for the element. 91 | - load `function` Adds event handler for load for the element. 92 | - rotate `object` Adds rotation by given angle around given point to the list of transformations of the element. 93 | - scale `object` Adds scale by given amount relative to given point to the list of transformations of the element. 94 | - stop `boolen` Stops animation for given element. 95 | - toBack `boolean` Moves the element so it is the furthest from the viewer’s eyes, behind other elements. 96 | - toFront `boolean` Moves the element so it is the closest to the viewer’s eyes, on top of other elements. 97 | - touchcancel `function` Adds event handler for touchcancel for the element. 98 | - touchend `function` Adds event handler for touchend for the element. 99 | - touchmove `function` Adds event handler for touchmove for the element. 100 | - touchstart `function` Adds event handler for touchstart for the element. 101 | - transform `string` or `array` Adds transformation to the element which is separate to other attributes, i.e. translation doesn’t change x or y of the rectange. The format of transformation string is similar to the path string syntax:`"t100,100r30,100,100s2,2,100,100r45s1.5"` 102 | - translate `object` Adds translation by given amount to the list of transformations of the element. 103 | - update `function` Adds event handler for update for the element. 104 | - Set `Extends Element & Container Elements` 105 | - Circle `Extends Element & Draws a circle` 106 | - x `number` x coordinate of the centre 107 | - y `number` y coordinate of the centre 108 | - r `number` radius 109 | - Ellipse `Extends Element & Draws a ellipse` 110 | - x `number` x coordinate of the centre 111 | - y `number` y coordinate of the centre 112 | - rx `number` horizontal radius 113 | - ry `number` vertical radius 114 | - Image `Extends Element & Embeds an image into the surface` 115 | - src `string` URI of the source image 116 | - x `number` x coordinate of the centre 117 | - y `number` y coordinate of the centre 118 | - width `number` width of the image 119 | - height `number` height of the image 120 | - Path `Extends Element & Creates a path element by given path data string` 121 | - d `string` path string in SVG format 122 | - Print `Extends Element & Creates set of shapes to represent given font at given position with given size` 123 | - x `number` x position of the text 124 | - y `number` y position of the text 125 | - text `string` text to print 126 | - font-family `string` family of font object 127 | - font-weight `string` weight of font object 128 | - font-style `string` style of font object 129 | - font-stretch `string` stretch of font object 130 | - font-size `number` size of the font, default is 16 131 | - origin `string` could be "baseline" or "middle", default is "middle" 132 | - letter-spacing `number` number in range -1..1, default is 0 133 | - Rect `Extends Element & Draws a circle` 134 | - x `number` x coordinate of the top left corner 135 | - y `number` y coordinate of the top left corner 136 | - width `number` width of the rect 137 | - height `number` height of the rect 138 | - r `number` radius for rounded corners, default is 0 139 | - Text `Extends Element & Draws a text string & If you need line breaks, put “\n” in the string` 140 | - x `number` x coordinate position 141 | - y `number` y coordinate position 142 | - text `string` The text string to draw 143 | - Line `Extends Path & Draws a line` 144 | - x1 `number` x coordinate of the start point 145 | - y1 `number` y coordinate of the start point 146 | - x2 `number` x coordinate of the end point 147 | - y2 `number` y coordinate of the end point 148 | 149 | #### All Element Ref Function 150 | 151 | - Paper 152 | - getPaper `function` paper of the component 153 | - Set 154 | - getSet `function` set of the component 155 | - Element 156 | - getElement `function` element of the component 157 | 158 | #### Raphael & Utils 159 | 160 | - Raphael `you can see ` [http://dmitrybaranovskiy.github.io/raphael/reference.html#Raphael](http://dmitrybaranovskiy.github.io/raphael/reference.html#Raphael) 161 | - Utils 162 | - createPaper `function` create a paper by `Raphael()` 163 | - updatePaper `function` update a paper 164 | - removePaper `function` remove a paper 165 | - create `function` create elements or a set by `paper.xxx` 166 | - createElement `function` call create to create a element 167 | - createSet `function` call create to create a set 168 | - updateElement `function` update elements or a set 169 | - removeSet `function` remove a set from paper 170 | - removeElement `function` remove a element from paper 171 | - papers `array` all paper instance 172 | - elements `array` all elements or set of the only paper instance 173 | - findParentById `function` find parent of element by id 174 | 175 | # Contact 176 | 177 | Email: [liuhong1.happy@163.com](mailto:liuhong1.happy@163.com) -------------------------------------------------------------------------------- /src/elements.js: -------------------------------------------------------------------------------- 1 | const React = require("react"); 2 | const ReactDOM = require("react-dom"); 3 | const Utils = require("./utils"); 4 | 5 | const PropTypes = require("prop-types"); 6 | 7 | class Paper extends React.Component { 8 | constructor(props){ 9 | super(props); 10 | this.state = { 11 | loaded: false 12 | }; 13 | } 14 | componentDidMount(){ 15 | const container = ReactDOM.findDOMNode(this.refs.container); 16 | const paper = Utils.createPaper(container,this.props); 17 | this.paper = paper; 18 | setTimeout(()=>{ 19 | this.setState({ 20 | loaded: true, 21 | id: paper.id 22 | }); 23 | }); 24 | } 25 | componentDidUpdate() { 26 | Utils.updatePaper(this.paper, this.props); 27 | } 28 | componentWillUnmount(){ 29 | this.paper.remove(); 30 | } 31 | 32 | getPaper(){ 33 | return this.paper; 34 | } 35 | genElementsContainer(){ 36 | if(this.state.loaded){ 37 | return (
38 | {this.props.children} 39 |
); 40 | }else{ 41 | return (
); 42 | } 43 | } 44 | render(){ 45 | const eleContainer = this.genElementsContainer(); 46 | const {style,className,...others} = this.props.container; 47 | return (
48 | {eleContainer} 49 |
50 |
); 51 | } 52 | } 53 | Paper.propTypes = { 54 | x: PropTypes.number, 55 | y: PropTypes.number, 56 | width: PropTypes.number, 57 | height: PropTypes.number, 58 | viewbox: PropTypes.string, 59 | container: PropTypes.object 60 | }; 61 | Paper.defaultProps = { x:0, y: 0,width: 100, height: 100, container:{ style:{}, className:"" }, viewbox: "" }; 62 | 63 | class Set extends React.Component{ 64 | constructor(props){ 65 | super(props); 66 | this.state = { 67 | loaded: false 68 | }; 69 | } 70 | componentDidMount(){ 71 | const root = ReactDOM.findDOMNode(this.refs.root); 72 | const parentId = root.parentElement.getAttribute("data-id"); 73 | const set = Utils.createSet(parentId,this.props,this.handleLoad.bind(this)); 74 | this.set = set; 75 | setTimeout(()=>{ 76 | this.setState({ 77 | loaded: true, 78 | id: set.id 79 | }); 80 | }); 81 | } 82 | getSet(){ 83 | return this.set; 84 | } 85 | handleLoad(set){ 86 | if(this.props.load){ 87 | this.props.load(set); 88 | } 89 | } 90 | componentWillUnmout(){ 91 | Utils.removeSet(this.set); 92 | } 93 | render(){ 94 | if(this.state.loaded){ 95 | return (
{this.props.children}
); 96 | }else{ 97 | return (
); 98 | } 99 | } 100 | } 101 | 102 | class Element extends React.Component{ 103 | constructor(props){ 104 | super(props); 105 | this.state = { 106 | loaded: false 107 | }; 108 | } 109 | componentDidMount(){ 110 | const root = ReactDOM.findDOMNode(this.refs.root); 111 | const parentId = root.parentElement.getAttribute("data-id"); 112 | const element = Utils.createElement(parentId,this.props.type,this.props,this.handleLoad.bind(this)); 113 | this.element = element; 114 | setTimeout(()=>{ 115 | this.setState({ 116 | loaded: true 117 | }); 118 | }); 119 | } 120 | componentDidUpdate(){ 121 | Utils.updateElement(this.element,this.props.type,this.props,this.handleUpdate.bind(this)); 122 | } 123 | componentWillUnmount(){ 124 | Utils.removeElement(this.element); 125 | } 126 | getElement(){ 127 | return this.element; 128 | } 129 | handleLoad(element){ 130 | if(this.props.load){ 131 | this.props.load(element); 132 | } 133 | } 134 | handleUpdate(element){ 135 | if(this.props.update){ 136 | this.props.update(element); 137 | } 138 | } 139 | render(){ 140 | if(this.state.loaded) return null; 141 | return (
); 142 | } 143 | } 144 | 145 | Element.propTypes = { 146 | attr: PropTypes.object, 147 | animate: PropTypes.oneOfType([ 148 | PropTypes.shape({ 149 | anim: PropTypes.shape({ 150 | transform: PropTypes.string 151 | }), 152 | ms: PropTypes.number, 153 | percents: PropTypes.array, 154 | times: PropTypes.number 155 | }), 156 | PropTypes.string 157 | ]), 158 | animateWith: PropTypes.object, 159 | click: PropTypes.func, 160 | data: PropTypes.object, 161 | dblclick: PropTypes.func, 162 | drag: PropTypes.object, 163 | glow: PropTypes.func, 164 | hover: PropTypes.object, 165 | hide: PropTypes.bool, 166 | mousedown: PropTypes.func, 167 | mousemove: PropTypes.func, 168 | mouseout: PropTypes.func, 169 | mouseover: PropTypes.func, 170 | mouseup: PropTypes.func, 171 | load: PropTypes.func, 172 | rotate: PropTypes.object, 173 | scale: PropTypes.object, 174 | stop: PropTypes.bool, 175 | toBack: PropTypes.bool, 176 | toFront: PropTypes.bool, 177 | touchcancel: PropTypes.func, 178 | touchend: PropTypes.func, 179 | touchmove: PropTypes.func, 180 | touchstart: PropTypes.func, 181 | transform: PropTypes.string, 182 | update: PropTypes.func, 183 | }; 184 | 185 | class Circle extends React.Component{ 186 | getElement() { return this.refs.element.getElement(); } 187 | render(){ return (); } 188 | } 189 | Circle.propTypes = { 190 | x: PropTypes.number, 191 | y: PropTypes.number, 192 | r: PropTypes.number, 193 | }; 194 | Circle.defaultProps = { x: 0, y: 0,r: 10 }; 195 | 196 | class Ellipse extends React.Component{ 197 | getElement() { return this.refs.element.getElement(); } 198 | render(){ return (); } 199 | } 200 | 201 | Ellipse.propTypes = { 202 | x: PropTypes.number, 203 | y: PropTypes.number, 204 | rx: PropTypes.number, 205 | ry: PropTypes.number, 206 | }; 207 | Ellipse.defaultProps = { x: 0, y: 0,rx: 10,ry: 20 }; 208 | 209 | class Image extends React.Component{ 210 | getElement() { return this.refs.element.getElement(); } 211 | render(){ return (); } 212 | } 213 | Image.propTypes = { 214 | x: PropTypes.number, 215 | y: PropTypes.number, 216 | src: PropTypes.string, 217 | width: PropTypes.number, 218 | height: PropTypes.number, 219 | }; 220 | Image.defaultProps = { x: 0, y: 0, src: "", width: 0,height: 0 }; 221 | 222 | class Path extends React.Component{ 223 | getElement() { return this.refs.element.getElement(); } 224 | render(){ return (); } 225 | } 226 | Path.propTypes = { 227 | d: PropTypes.oneOfType([PropTypes.string, PropTypes.array]), 228 | }; 229 | Path.defaultProps = { d: "M0,0L0,0Z" }; 230 | 231 | class Rect extends React.Component{ 232 | getElement() { return this.refs.element.getElement(); } 233 | render(){ return (); } 234 | } 235 | Rect.propTypes = { 236 | x: PropTypes.number, 237 | y: PropTypes.number, 238 | width: PropTypes.number, 239 | height: PropTypes.number, 240 | r: PropTypes.number, 241 | }; 242 | Rect.defaultProps = { x: 0, y: 0, width: 0,height: 0, r: 0 }; 243 | 244 | class Print extends React.Component{ 245 | getElement() { return this.refs.element.getElement(); } 246 | render(){ return (); } 247 | } 248 | Print.propTypes = { 249 | x: PropTypes.number, 250 | y: PropTypes.number, 251 | text: PropTypes.string, 252 | fontFamily: PropTypes.string, 253 | }; 254 | Print.defaultProps = { x: 0, y: 0, text: "", fontFamily: "Arial" }; 255 | 256 | class Text extends React.Component{ 257 | getElement() { return this.refs.element.getElement(); } 258 | render(){ return (); } 259 | } 260 | Text.propTypes = { 261 | x: PropTypes.number, 262 | y: PropTypes.number, 263 | text: PropTypes.string, 264 | }; 265 | Text.defaultProps = { x: 0, y: 0, text: "" }; 266 | 267 | class Line extends React.Component{ 268 | getElement() { return this.refs.path.getElement(); } 269 | render(){ 270 | const {x1,x2,y1,y2,animate,attr,...others} = this.props; 271 | if(animate){ 272 | if(animate.anim){ 273 | for(const key in animate.anim) { 274 | animate.anim[key].x1 = animate.anim[key].x1 || x1; 275 | animate.anim[key].x2 = animate.anim[key].x2 || x2; 276 | animate.anim[key].y1 = animate.anim[key].y1 || y1; 277 | animate.anim[key].y2 = animate.anim[key].y2 || y2; 278 | animate.anim[key].path = [ "M",animate.anim[key].x1,animate.anim[key].y1, "L",animate.anim[key].x2,animate.anim[key].y2 ]; 279 | } 280 | }else{ 281 | animate.x1 = animate.x1 || x1; 282 | animate.x2 = animate.x2 || x2; 283 | animate.y1 = animate.y1 || y1; 284 | animate.y2 = animate.y2 || y2; 285 | animate.path = [ "M",animate.x1,animate.y1, "L",animate.x2,animate.y2 ]; 286 | } 287 | } 288 | if(attr){ 289 | attr.x1 = attr.x1 || x1; 290 | attr.x2 = attr.x2 || x2; 291 | attr.y1 = attr.y1 || y1; 292 | attr.y2 = attr.y2 || y2; 293 | attr.path = [ "M",attr.x1,attr.y1, "L",attr.x2,attr.y2 ]; 294 | } 295 | return ; 296 | } 297 | } 298 | Line.propTypes = { 299 | x1: PropTypes.number, 300 | y1: PropTypes.number, 301 | x2: PropTypes.number, 302 | y2: PropTypes.number, 303 | }; 304 | Line.defaultProps = { x1: 0, y1: 0, x2: 0,y2: 0 }; 305 | 306 | module.exports = { 307 | Paper: Paper, 308 | Set: Set, 309 | Element: Element, 310 | Circle: Circle, 311 | Ellipse: Ellipse, 312 | Image: Image, 313 | Path: Path, 314 | Print: Print, 315 | Rect: Rect, 316 | Text: Text, 317 | Line: Line 318 | }; 319 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | const Raphael = require("raphael"); 2 | 3 | const Utils = { 4 | createPaper:function(container,props){ 5 | const { width,height } = props; 6 | const paper = Raphael(container,width,height); 7 | if(props.viewbox) { 8 | const v = props.viewbox.split(" "); 9 | paper.setViewBox(v[0] || 0, v[1] || 0, v[2] || 0, v[3] || 3, true); 10 | } 11 | paper.id = container.id || ("paper-" + new Date().valueOf() +"-"+ Math.random().toFixed(10)); 12 | Utils.papers.push(paper); 13 | return paper; 14 | }, 15 | findParentById: function(id){ 16 | const papers = Utils.papers.filter(function(ele){ 17 | return ele.id == id; 18 | }); 19 | if(papers.length>0){ 20 | return { 21 | parent: papers[0], 22 | paper: papers[0] 23 | }; 24 | }else{ 25 | const sets = Utils.elements.filter(function(ele){ 26 | return ele.element.id == id; 27 | }); 28 | if(sets.length>0){ 29 | if(!sets[0].element) return sets[0].element; 30 | return { 31 | parent: sets[0].element, 32 | paper: sets[0].element.paper 33 | }; 34 | } 35 | } 36 | return { 37 | parent: null, 38 | paper: null 39 | }; 40 | }, 41 | create:function(parentId,type,props){ 42 | let element = null; 43 | const findedParent = Utils.findParentById(parentId); 44 | if(!findedParent.paper) return findedParent.paper; 45 | switch(type){ 46 | case "set":{ 47 | element = findedParent.paper.set(); 48 | element.id = "set-" + new Date().valueOf() +"-"+ Math.random().toFixed(10); 49 | break; 50 | } 51 | case "circle":{ 52 | const {x,y,r} = props; 53 | element = findedParent.paper.circle(x,y,r); 54 | break; 55 | } 56 | case "ellipse":{ 57 | const {x, y, rx, ry} = props; 58 | element = findedParent.paper.ellipse(x, y, rx, ry); 59 | break; 60 | } 61 | case "image":{ 62 | const {src, x, y, width, height} = props; 63 | element = findedParent.paper.image(src, x, y, width, height); 64 | break; 65 | } 66 | case "path":{ 67 | let {d} = props; 68 | if(!d || d.length==0) d="M0,0L0,0Z"; 69 | element = findedParent.paper.path(d); 70 | break; 71 | } 72 | case "print":{ 73 | const {x, y, text, fontFamily,fontWeight,fontStyle,fontStretch,fontSize,letterSpacing} = props; 74 | const font = findedParent.paper.getFont(fontFamily,fontWeight,fontStyle,fontStretch); 75 | element = findedParent.paper.print(x, y, text,font,fontSize,letterSpacing); 76 | break; 77 | } 78 | case "rect":{ 79 | let {x, y, width, height, r} = props; 80 | element = findedParent.paper.rect(x, y, width, height, r); 81 | break; 82 | } 83 | case "text":{ 84 | const {x, y, text} = props; 85 | element = findedParent.paper.text(x, y, text); 86 | break; 87 | } 88 | default: break; 89 | } 90 | 91 | if(element){ 92 | if(findedParent.parent.type=="set"){ 93 | element.set = findedParent.parent; 94 | findedParent.parent.push(element); 95 | } 96 | } 97 | Utils.updateElementProps(element,props); 98 | return element; 99 | }, 100 | createElement:function(parentId,type,props,callback){ 101 | const element = Utils.create(parentId,type,props); 102 | Utils.elements.push({ 103 | type: type, 104 | props: props, 105 | callback: callback, 106 | element: element 107 | }); 108 | if(callback) callback(element); 109 | return element; 110 | }, 111 | createSet:function(parentId,props,callback){ 112 | const set = Utils.create(parentId,"set",props); 113 | Utils.elements.push({ 114 | type: "set", 115 | element: set 116 | }); 117 | if(callback) callback(set); 118 | return set; 119 | }, 120 | updatePaper: function(paper,props){ 121 | const {width,height} = props; 122 | paper.setSize(width, height); 123 | }, 124 | updateElementProps: function(element,props){ 125 | if(element){ 126 | // fix matrix bug 127 | element.matrix = Raphael.matrix(); 128 | element.attr("transform",""); 129 | for(const key in props){ 130 | switch(key){ 131 | case "attr":{ 132 | if(typeof props[key] ==="object") element.attr(props.attr); 133 | break; 134 | } 135 | case "animate":{ 136 | if(typeof props[key] ==="object") element.animate(props.animate); 137 | break; 138 | } 139 | case "animateWith":{ 140 | if(typeof props[key] ==="object") element.animateWith(props.animateWith); 141 | break; 142 | } 143 | case "click": { 144 | if(typeof props[key] ==="function") {element.unclick();element.click(props.click);} 145 | break; 146 | } 147 | case "data": { 148 | if(typeof props[key] ==="object") { 149 | for(const key in props.data) 150 | element.data(key,props.data[key]); 151 | element.items = props.data; 152 | } 153 | break; 154 | } 155 | case "dblclick": { 156 | if(typeof props[key] ==="function") {element.undblclick();element.dblclick(props.dblclick);} 157 | break; 158 | } 159 | case "drag": { 160 | if(typeof props[key] ==="object") { 161 | element.undrag(); 162 | element.drag(props.drag.move, props.drag.start, props.drag.end, props.drag.mcontext, props.drag.scontext, props.drag.econtext ); 163 | } 164 | break; 165 | } 166 | case "glow": { 167 | if(typeof props[key] ==="object") element.glow(props.glow); 168 | break; 169 | } 170 | case "hover": { 171 | if(typeof props[key] ==="object") { 172 | element.unhover(); 173 | element.hover(props.hover.in, props.hover.out, props.hover.icontext, props.hover.ocontext); 174 | } 175 | break; 176 | } 177 | case "hide": { 178 | if(typeof props[key] ==="boolean") props.hide?element.hide():element.show(); 179 | break; 180 | } 181 | case "mousedown": { 182 | if(typeof props[key] ==="function") {element.unmousedown();element.mousedown(props.mousedown);} 183 | break; 184 | } 185 | case "mousemove": { 186 | if(typeof props[key] ==="function") {element.unmousemove();element.mousemove(props.mousemove);} 187 | break; 188 | } 189 | case "mouseout": { 190 | if(typeof props[key] ==="function") {element.unmouseout();element.mouseout(props.mouseout);} 191 | break; 192 | } 193 | case "mouseover": { 194 | if(typeof props[key] ==="function") {element.unmouseover();element.mouseover(props.mouseover);} 195 | break; 196 | } 197 | case "mouseup":{ 198 | if(typeof props[key] ==="function") {element.unmouseup();element.mouseup(props.mouseup);} 199 | break; 200 | } 201 | case "rotate":{ 202 | if(typeof props[key] ==="object") { const {deg, cx, cy} = props.rotate; element.rotate(deg, cx, cy); } 203 | break; 204 | } 205 | case "scale":{ 206 | if(typeof props[key] ==="object") { const {sx,sy,cx,cy} = props.scale; element.scale(sx,sy,cx,cy); } 207 | break; 208 | } 209 | case "stop":{ 210 | if(typeof props[key] ==="boolean" && props.stop) { element.stop(); } 211 | break; 212 | } 213 | case "touchcancel":{ 214 | if(typeof props[key] ==="function") {element.untouchcancel();element.touchcancel(props.touchcancel);} 215 | break; 216 | } 217 | case "touchend":{ 218 | if(typeof props[key] ==="function") {element.untouchend();element.touchend(props.touchend);} 219 | break; 220 | } 221 | case "touchmove":{ 222 | if(typeof props[key] ==="function") {element.untouchmove();element.touchmove(props.touchmove);} 223 | break; 224 | } 225 | case "touchstart":{ 226 | if(typeof props[key] ==="function") {element.untouchstart();element.touchstart(props.touchstart);} 227 | break; 228 | } 229 | case "transform":{ 230 | if(typeof props[key] ==="object") element.transform(props.transform); 231 | break; 232 | } 233 | case "translate":{ 234 | if(typeof props[key] ==="object") element.translate(props.translate.x,props.translate.y); 235 | break; 236 | } 237 | } 238 | } 239 | // fix raphael #491 240 | if(Raphael.svg && element.node && element.node.nodeName=="text" && element.node.childNodes.length>0){ 241 | setTimeout(function(){ 242 | if(element.node){ 243 | const nodeY = element.node.getAttribute("y"); 244 | const childDy = element.node.childNodes[0].getAttribute("dy"); 245 | if(nodeY == childDy){ 246 | element.node.childNodes[0].setAttribute("dy",0); 247 | } 248 | } 249 | }); 250 | } 251 | } 252 | }, 253 | updateElement:function(element,type,props,callback){ 254 | switch(type){ 255 | case "circle":{ 256 | const {x,y,r} = props; 257 | element.attr({cx:x,cy:y,r:r}); 258 | break; 259 | } 260 | case "ellipse":{ 261 | const {x, y, rx, ry} = props; 262 | element.attr({cx:x,cy:y,rx:rx,ry:ry}); 263 | break; 264 | } 265 | case "image":{ 266 | const {src, x, y, width, height} = props; 267 | element.attr({src, x, y, width, height}); 268 | break; 269 | } 270 | case "path":{ 271 | let {d} = props; 272 | if(!d || d.length==0) d="M0,0L0,0Z"; 273 | element.attr({path:d}); 274 | break; 275 | } 276 | case "print":{ 277 | const {x,y,text,fontFamily,fontWeight,fontStyle,fontStretch,fontSize,letterSpacing} = props; 278 | element.attr({x,y,text,"font-style":fontStyle, "font-family":fontFamily,"font-size":fontSize,"font-weight": fontWeight,"font-stretch": fontStretch, "letter-scpacing": letterSpacing}); 279 | break; 280 | } 281 | case "rect":{ 282 | const {x, y, width, height, r} = props; 283 | element.attr({x, y, width, height, r}); 284 | break; 285 | } 286 | case "text":{ 287 | const {x, y, text} = props; 288 | element.attr({x, y, text}); 289 | break; 290 | } 291 | 292 | } 293 | Utils.updateElementProps(element,props); 294 | if(callback) callback(element); 295 | return element; 296 | }, 297 | removePaper: function(paper){ 298 | const papers = Utils.papers.filter(function(ele){ 299 | return ele === paper; 300 | }); 301 | if(papers.length>0){ 302 | papers[0].remove(); 303 | } 304 | }, 305 | removeSet:function(set){ 306 | Utils.removeElement(set); 307 | }, 308 | removeElement:function(element){ 309 | const elements = Utils.elements.filter(function(ele){ 310 | return ele.element === element; 311 | }); 312 | if(elements.length>0){ 313 | elements[0].element.remove(); 314 | } 315 | }, 316 | papers: [], 317 | elements: [] 318 | }; 319 | 320 | module.exports = Utils; 321 | -------------------------------------------------------------------------------- /lib/utils.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; 4 | 5 | var Raphael = require("raphael"); 6 | 7 | var Utils = { 8 | createPaper: function createPaper(container, props) { 9 | var width = props.width, 10 | height = props.height; 11 | 12 | var paper = Raphael(container, width, height); 13 | if (props.viewbox) { 14 | var v = props.viewbox.split(" "); 15 | paper.setViewBox(v[0] || 0, v[1] || 0, v[2] || 0, v[3] || 3, true); 16 | } 17 | paper.id = container.id || "paper-" + new Date().valueOf() + "-" + Math.random().toFixed(10); 18 | Utils.papers.push(paper); 19 | return paper; 20 | }, 21 | findParentById: function findParentById(id) { 22 | var papers = Utils.papers.filter(function (ele) { 23 | return ele.id == id; 24 | }); 25 | if (papers.length > 0) { 26 | return { 27 | parent: papers[0], 28 | paper: papers[0] 29 | }; 30 | } else { 31 | var sets = Utils.elements.filter(function (ele) { 32 | return ele.element.id == id; 33 | }); 34 | if (sets.length > 0) { 35 | if (!sets[0].element) return sets[0].element; 36 | return { 37 | parent: sets[0].element, 38 | paper: sets[0].element.paper 39 | }; 40 | } 41 | } 42 | return { 43 | parent: null, 44 | paper: null 45 | }; 46 | }, 47 | create: function create(parentId, type, props) { 48 | var element = null; 49 | var findedParent = Utils.findParentById(parentId); 50 | if (!findedParent.paper) return findedParent.paper; 51 | switch (type) { 52 | case "set": 53 | { 54 | element = findedParent.paper.set(); 55 | element.id = "set-" + new Date().valueOf() + "-" + Math.random().toFixed(10); 56 | break; 57 | } 58 | case "circle": 59 | { 60 | var x = props.x, 61 | y = props.y, 62 | r = props.r; 63 | 64 | element = findedParent.paper.circle(x, y, r); 65 | break; 66 | } 67 | case "ellipse": 68 | { 69 | var _x = props.x, 70 | _y = props.y, 71 | rx = props.rx, 72 | ry = props.ry; 73 | 74 | element = findedParent.paper.ellipse(_x, _y, rx, ry); 75 | break; 76 | } 77 | case "image": 78 | { 79 | var src = props.src, 80 | _x2 = props.x, 81 | _y2 = props.y, 82 | width = props.width, 83 | height = props.height; 84 | 85 | element = findedParent.paper.image(src, _x2, _y2, width, height); 86 | break; 87 | } 88 | case "path": 89 | { 90 | var d = props.d; 91 | 92 | if (!d || d.length == 0) d = "M0,0L0,0Z"; 93 | element = findedParent.paper.path(d); 94 | break; 95 | } 96 | case "print": 97 | { 98 | var _x3 = props.x, 99 | _y3 = props.y, 100 | text = props.text, 101 | fontFamily = props.fontFamily, 102 | fontWeight = props.fontWeight, 103 | fontStyle = props.fontStyle, 104 | fontStretch = props.fontStretch, 105 | fontSize = props.fontSize, 106 | letterSpacing = props.letterSpacing; 107 | 108 | var font = findedParent.paper.getFont(fontFamily, fontWeight, fontStyle, fontStretch); 109 | element = findedParent.paper.print(_x3, _y3, text, font, fontSize, letterSpacing); 110 | break; 111 | } 112 | case "rect": 113 | { 114 | var _x4 = props.x, 115 | _y4 = props.y, 116 | _width = props.width, 117 | _height = props.height, 118 | _r = props.r; 119 | 120 | element = findedParent.paper.rect(_x4, _y4, _width, _height, _r); 121 | break; 122 | } 123 | case "text": 124 | { 125 | var _x5 = props.x, 126 | _y5 = props.y, 127 | _text = props.text; 128 | 129 | element = findedParent.paper.text(_x5, _y5, _text); 130 | break; 131 | } 132 | default: 133 | break; 134 | } 135 | 136 | if (element) { 137 | if (findedParent.parent.type == "set") { 138 | element.set = findedParent.parent; 139 | findedParent.parent.push(element); 140 | } 141 | } 142 | Utils.updateElementProps(element, props); 143 | return element; 144 | }, 145 | createElement: function createElement(parentId, type, props, callback) { 146 | var element = Utils.create(parentId, type, props); 147 | Utils.elements.push({ 148 | type: type, 149 | props: props, 150 | callback: callback, 151 | element: element 152 | }); 153 | if (callback) callback(element); 154 | return element; 155 | }, 156 | createSet: function createSet(parentId, props, callback) { 157 | var set = Utils.create(parentId, "set", props); 158 | Utils.elements.push({ 159 | type: "set", 160 | element: set 161 | }); 162 | if (callback) callback(set); 163 | return set; 164 | }, 165 | updatePaper: function updatePaper(paper, props) { 166 | var width = props.width, 167 | height = props.height; 168 | 169 | paper.setSize(width, height); 170 | }, 171 | updateElementProps: function updateElementProps(element, props) { 172 | if (element) { 173 | // fix matrix bug 174 | element.matrix = Raphael.matrix(); 175 | element.attr("transform", ""); 176 | for (var key in props) { 177 | switch (key) { 178 | case "attr": 179 | { 180 | if (_typeof(props[key]) === "object") element.attr(props.attr); 181 | break; 182 | } 183 | case "animate": 184 | { 185 | if (_typeof(props[key]) === "object") element.animate(props.animate); 186 | break; 187 | } 188 | case "animateWith": 189 | { 190 | if (_typeof(props[key]) === "object") element.animateWith(props.animateWith); 191 | break; 192 | } 193 | case "click": 194 | { 195 | if (typeof props[key] === "function") { 196 | element.unclick();element.click(props.click); 197 | } 198 | break; 199 | } 200 | case "data": 201 | { 202 | if (_typeof(props[key]) === "object") { 203 | for (var _key in props.data) { 204 | element.data(_key, props.data[_key]); 205 | }element.items = props.data; 206 | } 207 | break; 208 | } 209 | case "dblclick": 210 | { 211 | if (typeof props[key] === "function") { 212 | element.undblclick();element.dblclick(props.dblclick); 213 | } 214 | break; 215 | } 216 | case "drag": 217 | { 218 | if (_typeof(props[key]) === "object") { 219 | element.undrag(); 220 | element.drag(props.drag.move, props.drag.start, props.drag.end, props.drag.mcontext, props.drag.scontext, props.drag.econtext); 221 | } 222 | break; 223 | } 224 | case "glow": 225 | { 226 | if (_typeof(props[key]) === "object") element.glow(props.glow); 227 | break; 228 | } 229 | case "hover": 230 | { 231 | if (_typeof(props[key]) === "object") { 232 | element.unhover(); 233 | element.hover(props.hover.in, props.hover.out, props.hover.icontext, props.hover.ocontext); 234 | } 235 | break; 236 | } 237 | case "hide": 238 | { 239 | if (typeof props[key] === "boolean") props.hide ? element.hide() : element.show(); 240 | break; 241 | } 242 | case "mousedown": 243 | { 244 | if (typeof props[key] === "function") { 245 | element.unmousedown();element.mousedown(props.mousedown); 246 | } 247 | break; 248 | } 249 | case "mousemove": 250 | { 251 | if (typeof props[key] === "function") { 252 | element.unmousemove();element.mousemove(props.mousemove); 253 | } 254 | break; 255 | } 256 | case "mouseout": 257 | { 258 | if (typeof props[key] === "function") { 259 | element.unmouseout();element.mouseout(props.mouseout); 260 | } 261 | break; 262 | } 263 | case "mouseover": 264 | { 265 | if (typeof props[key] === "function") { 266 | element.unmouseover();element.mouseover(props.mouseover); 267 | } 268 | break; 269 | } 270 | case "mouseup": 271 | { 272 | if (typeof props[key] === "function") { 273 | element.unmouseup();element.mouseup(props.mouseup); 274 | } 275 | break; 276 | } 277 | case "rotate": 278 | { 279 | if (_typeof(props[key]) === "object") { 280 | var _props$rotate = props.rotate, 281 | deg = _props$rotate.deg, 282 | cx = _props$rotate.cx, 283 | cy = _props$rotate.cy; 284 | element.rotate(deg, cx, cy); 285 | } 286 | break; 287 | } 288 | case "scale": 289 | { 290 | if (_typeof(props[key]) === "object") { 291 | var _props$scale = props.scale, 292 | sx = _props$scale.sx, 293 | sy = _props$scale.sy, 294 | _cx = _props$scale.cx, 295 | _cy = _props$scale.cy; 296 | element.scale(sx, sy, _cx, _cy); 297 | } 298 | break; 299 | } 300 | case "stop": 301 | { 302 | if (typeof props[key] === "boolean" && props.stop) { 303 | element.stop(); 304 | } 305 | break; 306 | } 307 | case "touchcancel": 308 | { 309 | if (typeof props[key] === "function") { 310 | element.untouchcancel();element.touchcancel(props.touchcancel); 311 | } 312 | break; 313 | } 314 | case "touchend": 315 | { 316 | if (typeof props[key] === "function") { 317 | element.untouchend();element.touchend(props.touchend); 318 | } 319 | break; 320 | } 321 | case "touchmove": 322 | { 323 | if (typeof props[key] === "function") { 324 | element.untouchmove();element.touchmove(props.touchmove); 325 | } 326 | break; 327 | } 328 | case "touchstart": 329 | { 330 | if (typeof props[key] === "function") { 331 | element.untouchstart();element.touchstart(props.touchstart); 332 | } 333 | break; 334 | } 335 | case "transform": 336 | { 337 | if (_typeof(props[key]) === "object") element.transform(props.transform); 338 | break; 339 | } 340 | case "translate": 341 | { 342 | if (_typeof(props[key]) === "object") element.translate(props.translate.x, props.translate.y); 343 | break; 344 | } 345 | } 346 | } 347 | // fix raphael #491 348 | if (Raphael.svg && element.node && element.node.nodeName == "text" && element.node.childNodes.length > 0) { 349 | setTimeout(function () { 350 | if (element.node) { 351 | var nodeY = element.node.getAttribute("y"); 352 | var childDy = element.node.childNodes[0].getAttribute("dy"); 353 | if (nodeY == childDy) { 354 | element.node.childNodes[0].setAttribute("dy", 0); 355 | } 356 | } 357 | }); 358 | } 359 | } 360 | }, 361 | updateElement: function updateElement(element, type, props, callback) { 362 | switch (type) { 363 | case "circle": 364 | { 365 | var x = props.x, 366 | y = props.y, 367 | r = props.r; 368 | 369 | element.attr({ cx: x, cy: y, r: r }); 370 | break; 371 | } 372 | case "ellipse": 373 | { 374 | var _x6 = props.x, 375 | _y6 = props.y, 376 | rx = props.rx, 377 | ry = props.ry; 378 | 379 | element.attr({ cx: _x6, cy: _y6, rx: rx, ry: ry }); 380 | break; 381 | } 382 | case "image": 383 | { 384 | var src = props.src, 385 | _x7 = props.x, 386 | _y7 = props.y, 387 | width = props.width, 388 | height = props.height; 389 | 390 | element.attr({ src: src, x: _x7, y: _y7, width: width, height: height }); 391 | break; 392 | } 393 | case "path": 394 | { 395 | var d = props.d; 396 | 397 | if (!d || d.length == 0) d = "M0,0L0,0Z"; 398 | element.attr({ path: d }); 399 | break; 400 | } 401 | case "print": 402 | { 403 | var _x8 = props.x, 404 | _y8 = props.y, 405 | text = props.text, 406 | fontFamily = props.fontFamily, 407 | fontWeight = props.fontWeight, 408 | fontStyle = props.fontStyle, 409 | fontStretch = props.fontStretch, 410 | fontSize = props.fontSize, 411 | letterSpacing = props.letterSpacing; 412 | 413 | element.attr({ x: _x8, y: _y8, text: text, "font-style": fontStyle, "font-family": fontFamily, "font-size": fontSize, "font-weight": fontWeight, "font-stretch": fontStretch, "letter-scpacing": letterSpacing }); 414 | break; 415 | } 416 | case "rect": 417 | { 418 | var _x9 = props.x, 419 | _y9 = props.y, 420 | _width2 = props.width, 421 | _height2 = props.height, 422 | _r2 = props.r; 423 | 424 | element.attr({ x: _x9, y: _y9, width: _width2, height: _height2, r: _r2 }); 425 | break; 426 | } 427 | case "text": 428 | { 429 | var _x10 = props.x, 430 | _y10 = props.y, 431 | _text2 = props.text; 432 | 433 | element.attr({ x: _x10, y: _y10, text: _text2 }); 434 | break; 435 | } 436 | 437 | } 438 | Utils.updateElementProps(element, props); 439 | if (callback) callback(element); 440 | return element; 441 | }, 442 | removePaper: function removePaper(paper) { 443 | var papers = Utils.papers.filter(function (ele) { 444 | return ele === paper; 445 | }); 446 | if (papers.length > 0) { 447 | papers[0].remove(); 448 | } 449 | }, 450 | removeSet: function removeSet(set) { 451 | Utils.removeElement(set); 452 | }, 453 | removeElement: function removeElement(element) { 454 | var elements = Utils.elements.filter(function (ele) { 455 | return ele.element === element; 456 | }); 457 | if (elements.length > 0) { 458 | elements[0].element.remove(); 459 | } 460 | }, 461 | papers: [], 462 | elements: [] 463 | }; 464 | 465 | module.exports = Utils; -------------------------------------------------------------------------------- /lib/elements.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 4 | 5 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 6 | 7 | function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } 8 | 9 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 10 | 11 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 12 | 13 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 14 | 15 | var React = require("react"); 16 | var ReactDOM = require("react-dom"); 17 | var Utils = require("./utils"); 18 | 19 | var PropTypes = require("prop-types"); 20 | 21 | var Paper = function (_React$Component) { 22 | _inherits(Paper, _React$Component); 23 | 24 | function Paper(props) { 25 | _classCallCheck(this, Paper); 26 | 27 | var _this = _possibleConstructorReturn(this, (Paper.__proto__ || Object.getPrototypeOf(Paper)).call(this, props)); 28 | 29 | _this.state = { 30 | loaded: false 31 | }; 32 | return _this; 33 | } 34 | 35 | _createClass(Paper, [{ 36 | key: "componentDidMount", 37 | value: function componentDidMount() { 38 | var container = ReactDOM.findDOMNode(this.refs.container); 39 | var paper = Utils.createPaper(container, this.props); 40 | this.paper = paper; 41 | this.setState({ 42 | loaded: true, 43 | id: paper.id 44 | }); 45 | } 46 | }, { 47 | key: "componentDidUpdate", 48 | value: function componentDidUpdate() { 49 | Utils.updatePaper(this.paper, this.props); 50 | } 51 | }, { 52 | key: "componentWillUnmount", 53 | value: function componentWillUnmount() { 54 | this.paper.remove(); 55 | } 56 | }, { 57 | key: "getPaper", 58 | value: function getPaper() { 59 | return this.paper; 60 | } 61 | }, { 62 | key: "genElementsContainer", 63 | value: function genElementsContainer() { 64 | if (this.state.loaded) { 65 | return React.createElement( 66 | "div", 67 | { className: "raphael-paper", "data-id": this.state.id }, 68 | this.props.children 69 | ); 70 | } else { 71 | return React.createElement("div", { className: "raphael-paper" }); 72 | } 73 | } 74 | }, { 75 | key: "render", 76 | value: function render() { 77 | var eleContainer = this.genElementsContainer(); 78 | 79 | var _props$container = this.props.container, 80 | style = _props$container.style, 81 | className = _props$container.className, 82 | others = _objectWithoutProperties(_props$container, ["style", "className"]); 83 | 84 | return React.createElement( 85 | "div", 86 | { className: "react-raphael" }, 87 | eleContainer, 88 | React.createElement("div", _extends({ ref: "container", className: "paper-container " + className, style: style }, others)) 89 | ); 90 | } 91 | }]); 92 | 93 | return Paper; 94 | }(React.Component); 95 | 96 | Paper.propTypes = { 97 | x: PropTypes.number, 98 | y: PropTypes.number, 99 | width: PropTypes.number, 100 | height: PropTypes.number, 101 | viewbox: PropTypes.string, 102 | container: PropTypes.object 103 | }; 104 | Paper.defaultProps = { x: 0, y: 0, width: 100, height: 100, container: { style: {}, className: "" }, viewbox: "" }; 105 | 106 | var Set = function (_React$Component2) { 107 | _inherits(Set, _React$Component2); 108 | 109 | function Set(props) { 110 | _classCallCheck(this, Set); 111 | 112 | var _this2 = _possibleConstructorReturn(this, (Set.__proto__ || Object.getPrototypeOf(Set)).call(this, props)); 113 | 114 | _this2.state = { 115 | loaded: false 116 | }; 117 | return _this2; 118 | } 119 | 120 | _createClass(Set, [{ 121 | key: "componentDidMount", 122 | value: function componentDidMount() { 123 | var root = ReactDOM.findDOMNode(this.refs.root); 124 | var parentId = root.parentElement.getAttribute("data-id"); 125 | var set = Utils.createSet(parentId, this.props, this.handleLoad.bind(this)); 126 | this.set = set; 127 | this.setState({ 128 | loaded: true, 129 | id: set.id 130 | }); 131 | } 132 | }, { 133 | key: "getSet", 134 | value: function getSet() { 135 | return this.set; 136 | } 137 | }, { 138 | key: "handleLoad", 139 | value: function handleLoad(set) { 140 | if (this.props.load) { 141 | this.props.load(set); 142 | } 143 | } 144 | }, { 145 | key: "componentWillUnmout", 146 | value: function componentWillUnmout() { 147 | Utils.removeSet(this.set); 148 | } 149 | }, { 150 | key: "render", 151 | value: function render() { 152 | if (this.state.loaded) { 153 | return React.createElement( 154 | "div", 155 | { ref: "root", className: "raphael-set", "data-id": this.state.id }, 156 | this.props.children 157 | ); 158 | } else { 159 | return React.createElement("div", { ref: "root", className: "raphael-set", "data-id": this.state.id }); 160 | } 161 | } 162 | }]); 163 | 164 | return Set; 165 | }(React.Component); 166 | 167 | var Element = function (_React$Component3) { 168 | _inherits(Element, _React$Component3); 169 | 170 | function Element(props) { 171 | _classCallCheck(this, Element); 172 | 173 | var _this3 = _possibleConstructorReturn(this, (Element.__proto__ || Object.getPrototypeOf(Element)).call(this, props)); 174 | 175 | _this3.state = { 176 | loaded: false 177 | }; 178 | return _this3; 179 | } 180 | 181 | _createClass(Element, [{ 182 | key: "componentDidMount", 183 | value: function componentDidMount() { 184 | var root = ReactDOM.findDOMNode(this.refs.root); 185 | var parentId = root.parentElement.getAttribute("data-id"); 186 | var element = Utils.createElement(parentId, this.props.type, this.props, this.handleLoad.bind(this)); 187 | this.element = element; 188 | this.setState({ 189 | loaded: true 190 | }); 191 | } 192 | }, { 193 | key: "componentDidUpdate", 194 | value: function componentDidUpdate() { 195 | Utils.updateElement(this.element, this.props.type, this.props, this.handleUpdate.bind(this)); 196 | } 197 | }, { 198 | key: "componentWillUnmount", 199 | value: function componentWillUnmount() { 200 | Utils.removeElement(this.element); 201 | } 202 | }, { 203 | key: "getElement", 204 | value: function getElement() { 205 | return this.element; 206 | } 207 | }, { 208 | key: "handleLoad", 209 | value: function handleLoad(element) { 210 | if (this.props.load) { 211 | this.props.load(element); 212 | } 213 | } 214 | }, { 215 | key: "handleUpdate", 216 | value: function handleUpdate(element) { 217 | if (this.props.update) { 218 | this.props.update(element); 219 | } 220 | } 221 | }, { 222 | key: "render", 223 | value: function render() { 224 | if (this.state.loaded) return null; 225 | return React.createElement("div", { ref: "root", className: "raphael-" + this.props.type }); 226 | } 227 | }]); 228 | 229 | return Element; 230 | }(React.Component); 231 | 232 | Element.propTypes = { 233 | animate: PropTypes.oneOfType([PropTypes.shape({ 234 | anim: PropTypes.shape({ 235 | transform: PropTypes.string 236 | }), 237 | ms: PropTypes.number, 238 | percents: PropTypes.array, 239 | times: PropTypes.number 240 | }), PropTypes.string]), 241 | stop: PropTypes.bool 242 | }; 243 | 244 | var Circle = function (_React$Component4) { 245 | _inherits(Circle, _React$Component4); 246 | 247 | function Circle() { 248 | _classCallCheck(this, Circle); 249 | 250 | return _possibleConstructorReturn(this, (Circle.__proto__ || Object.getPrototypeOf(Circle)).apply(this, arguments)); 251 | } 252 | 253 | _createClass(Circle, [{ 254 | key: "getElement", 255 | value: function getElement() { 256 | return this.refs.element.getElement(); 257 | } 258 | }, { 259 | key: "render", 260 | value: function render() { 261 | return React.createElement(Element, _extends({ ref: "element", type: "circle" }, this.props)); 262 | } 263 | }]); 264 | 265 | return Circle; 266 | }(React.Component); 267 | 268 | Circle.propTypes = { 269 | x: PropTypes.number, 270 | y: PropTypes.number, 271 | r: PropTypes.number, animate: PropTypes.oneOfType([PropTypes.shape({ anim: PropTypes.shape({ transform: PropTypes.string }), ms: PropTypes.number, percents: PropTypes.array, times: PropTypes.number }), PropTypes.string]), stop: PropTypes.bool 272 | }; 273 | Circle.defaultProps = { x: 0, y: 0, r: 10 }; 274 | 275 | var Ellipse = function (_React$Component5) { 276 | _inherits(Ellipse, _React$Component5); 277 | 278 | function Ellipse() { 279 | _classCallCheck(this, Ellipse); 280 | 281 | return _possibleConstructorReturn(this, (Ellipse.__proto__ || Object.getPrototypeOf(Ellipse)).apply(this, arguments)); 282 | } 283 | 284 | _createClass(Ellipse, [{ 285 | key: "getElement", 286 | value: function getElement() { 287 | return this.refs.element.getElement(); 288 | } 289 | }, { 290 | key: "render", 291 | value: function render() { 292 | return React.createElement(Element, _extends({ ref: "element", type: "ellipse" }, this.props)); 293 | } 294 | }]); 295 | 296 | return Ellipse; 297 | }(React.Component); 298 | 299 | Ellipse.propTypes = { x: PropTypes.number, y: PropTypes.number, rx: PropTypes.number, ry: PropTypes.number, animate: PropTypes.oneOfType([PropTypes.shape({ anim: PropTypes.shape({ transform: PropTypes.string }), ms: PropTypes.number, percents: PropTypes.array, times: PropTypes.number }), PropTypes.string]), stop: PropTypes.bool }; 300 | Ellipse.defaultProps = { x: 0, y: 0, rx: 10, ry: 20 }; 301 | 302 | var Image = function (_React$Component6) { 303 | _inherits(Image, _React$Component6); 304 | 305 | function Image() { 306 | _classCallCheck(this, Image); 307 | 308 | return _possibleConstructorReturn(this, (Image.__proto__ || Object.getPrototypeOf(Image)).apply(this, arguments)); 309 | } 310 | 311 | _createClass(Image, [{ 312 | key: "getElement", 313 | value: function getElement() { 314 | return this.refs.element.getElement(); 315 | } 316 | }, { 317 | key: "render", 318 | value: function render() { 319 | return React.createElement(Element, _extends({ ref: "element", type: "image" }, this.props)); 320 | } 321 | }]); 322 | 323 | return Image; 324 | }(React.Component); 325 | 326 | Image.propTypes = { x: PropTypes.number, y: PropTypes.number, src: PropTypes.string, width: PropTypes.number, height: PropTypes.number, animate: PropTypes.oneOfType([PropTypes.shape({ anim: PropTypes.shape({ transform: PropTypes.string }), ms: PropTypes.number, percents: PropTypes.array, times: PropTypes.number }), PropTypes.string]), stop: PropTypes.bool }; 327 | Image.defaultProps = { x: 0, y: 0, src: "", width: 0, height: 0 }; 328 | 329 | var Path = function (_React$Component7) { 330 | _inherits(Path, _React$Component7); 331 | 332 | function Path() { 333 | _classCallCheck(this, Path); 334 | 335 | return _possibleConstructorReturn(this, (Path.__proto__ || Object.getPrototypeOf(Path)).apply(this, arguments)); 336 | } 337 | 338 | _createClass(Path, [{ 339 | key: "getElement", 340 | value: function getElement() { 341 | return this.refs.element.getElement(); 342 | } 343 | }, { 344 | key: "render", 345 | value: function render() { 346 | return React.createElement(Element, _extends({ ref: "element", type: "path" }, this.props)); 347 | } 348 | }]); 349 | 350 | return Path; 351 | }(React.Component); 352 | 353 | Path.propTypes = { d: PropTypes.oneOfType([PropTypes.string, PropTypes.array]), animate: PropTypes.oneOfType([PropTypes.shape({ anim: PropTypes.shape({ transform: PropTypes.string }), ms: PropTypes.number, percents: PropTypes.array, times: PropTypes.number }), PropTypes.string]), stop: PropTypes.bool }; 354 | Path.defaultProps = { d: "M0,0L0,0Z" }; 355 | 356 | var Rect = function (_React$Component8) { 357 | _inherits(Rect, _React$Component8); 358 | 359 | function Rect() { 360 | _classCallCheck(this, Rect); 361 | 362 | return _possibleConstructorReturn(this, (Rect.__proto__ || Object.getPrototypeOf(Rect)).apply(this, arguments)); 363 | } 364 | 365 | _createClass(Rect, [{ 366 | key: "getElement", 367 | value: function getElement() { 368 | return this.refs.element.getElement(); 369 | } 370 | }, { 371 | key: "render", 372 | value: function render() { 373 | return React.createElement(Element, _extends({ ref: "element", type: "rect" }, this.props)); 374 | } 375 | }]); 376 | 377 | return Rect; 378 | }(React.Component); 379 | 380 | Rect.propTypes = { x: PropTypes.number, y: PropTypes.number, width: PropTypes.number, height: PropTypes.number, r: PropTypes.number, animate: PropTypes.oneOfType([PropTypes.shape({ anim: PropTypes.shape({ transform: PropTypes.string }), ms: PropTypes.number, percents: PropTypes.array, times: PropTypes.number }), PropTypes.string]), stop: PropTypes.bool }; 381 | Rect.defaultProps = { x: 0, y: 0, width: 0, height: 0, r: 0 }; 382 | 383 | var Print = function (_React$Component9) { 384 | _inherits(Print, _React$Component9); 385 | 386 | function Print() { 387 | _classCallCheck(this, Print); 388 | 389 | return _possibleConstructorReturn(this, (Print.__proto__ || Object.getPrototypeOf(Print)).apply(this, arguments)); 390 | } 391 | 392 | _createClass(Print, [{ 393 | key: "getElement", 394 | value: function getElement() { 395 | return this.refs.element.getElement(); 396 | } 397 | }, { 398 | key: "render", 399 | value: function render() { 400 | return React.createElement(Element, _extends({ ref: "element", type: "print" }, this.props)); 401 | } 402 | }]); 403 | 404 | return Print; 405 | }(React.Component); 406 | 407 | Print.propTypes = { x: PropTypes.number, y: PropTypes.number, text: PropTypes.string, fontFamily: PropTypes.string, animate: PropTypes.oneOfType([PropTypes.shape({ anim: PropTypes.shape({ transform: PropTypes.string }), ms: PropTypes.number, percents: PropTypes.array, times: PropTypes.number }), PropTypes.string]), stop: PropTypes.bool }; 408 | Print.defaultProps = { x: 0, y: 0, text: "", fontFamily: "Arial" }; 409 | 410 | var Text = function (_React$Component10) { 411 | _inherits(Text, _React$Component10); 412 | 413 | function Text() { 414 | _classCallCheck(this, Text); 415 | 416 | return _possibleConstructorReturn(this, (Text.__proto__ || Object.getPrototypeOf(Text)).apply(this, arguments)); 417 | } 418 | 419 | _createClass(Text, [{ 420 | key: "getElement", 421 | value: function getElement() { 422 | return this.refs.element.getElement(); 423 | } 424 | }, { 425 | key: "render", 426 | value: function render() { 427 | return React.createElement(Element, _extends({ ref: "element", type: "text" }, this.props)); 428 | } 429 | }]); 430 | 431 | return Text; 432 | }(React.Component); 433 | 434 | Text.propTypes = { x: PropTypes.number, y: PropTypes.number, text: PropTypes.string, animate: PropTypes.oneOfType([PropTypes.shape({ anim: PropTypes.shape({ transform: PropTypes.string }), ms: PropTypes.number, percents: PropTypes.array, times: PropTypes.number }), PropTypes.string]), stop: PropTypes.bool }; 435 | Text.defaultProps = { x: 0, y: 0, text: "" }; 436 | 437 | var Line = function (_React$Component11) { 438 | _inherits(Line, _React$Component11); 439 | 440 | function Line() { 441 | _classCallCheck(this, Line); 442 | 443 | return _possibleConstructorReturn(this, (Line.__proto__ || Object.getPrototypeOf(Line)).apply(this, arguments)); 444 | } 445 | 446 | _createClass(Line, [{ 447 | key: "getElement", 448 | value: function getElement() { 449 | return this.refs.path.getElement(); 450 | } 451 | }, { 452 | key: "render", 453 | value: function render() { 454 | var _props = this.props, 455 | x1 = _props.x1, 456 | x2 = _props.x2, 457 | y1 = _props.y1, 458 | y2 = _props.y2, 459 | animate = _props.animate, 460 | attr = _props.attr, 461 | others = _objectWithoutProperties(_props, ["x1", "x2", "y1", "y2", "animate", "attr"]); 462 | 463 | if (animate) { 464 | if (animate.anim) { 465 | for (var key in animate.anim) { 466 | animate.anim[key].x1 = animate.anim[key].x1 || x1; 467 | animate.anim[key].x2 = animate.anim[key].x2 || x2; 468 | animate.anim[key].y1 = animate.anim[key].y1 || y1; 469 | animate.anim[key].y2 = animate.anim[key].y2 || y2; 470 | animate.anim[key].path = ["M", animate.anim[key].x1, animate.anim[key].y1, "L", animate.anim[key].x2, animate.anim[key].y2]; 471 | } 472 | } else { 473 | animate.x1 = animate.x1 || x1; 474 | animate.x2 = animate.x2 || x2; 475 | animate.y1 = animate.y1 || y1; 476 | animate.y2 = animate.y2 || y2; 477 | animate.path = ["M", animate.x1, animate.y1, "L", animate.x2, animate.y2]; 478 | } 479 | } 480 | if (attr) { 481 | attr.x1 = attr.x1 || x1; 482 | attr.x2 = attr.x2 || x2; 483 | attr.y1 = attr.y1 || y1; 484 | attr.y2 = attr.y2 || y2; 485 | attr.path = ["M", attr.x1, attr.y1, "L", attr.x2, attr.y2]; 486 | } 487 | return React.createElement(Path, _extends({ ref: "path", d: ["M", x1, y1, "L", x2, y2], attr: attr, animate: animate }, others)); 488 | } 489 | }]); 490 | 491 | return Line; 492 | }(React.Component); 493 | 494 | Line.propTypes = { x1: PropTypes.number, y1: PropTypes.number, x2: PropTypes.number, y2: PropTypes.number, animate: PropTypes.oneOfType([PropTypes.shape({ anim: PropTypes.shape({ transform: PropTypes.string }), ms: PropTypes.number, percents: PropTypes.array, times: PropTypes.number }), PropTypes.string]), stop: PropTypes.bool }; 495 | Line.defaultProps = { x1: 0, y1: 0, x2: 0, y2: 0 }; 496 | 497 | module.exports = { 498 | Paper: Paper, 499 | Set: Set, 500 | Element: Element, 501 | Circle: Circle, 502 | Ellipse: Ellipse, 503 | Image: Image, 504 | Path: Path, 505 | Print: Print, 506 | Rect: Rect, 507 | Text: Text, 508 | Line: Line 509 | }; --------------------------------------------------------------------------------