├── .gitignore ├── LICENSE ├── README.md ├── index.js ├── octogon.PNG ├── package.json └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Stéphane D. 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 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-line 2 | 3 | > Provide a React component to draw a line. 4 | 5 | Underneath, it's only using a classic `
` that it rotates and positions 6 | where it needs to be. 7 | 8 | ## Why 9 | 10 | Sometimes, you want to draw a line in your page (mostly, a line that is linked to 2 items that can move for instance), not using fancy stuff. A `
` is not a fancy stuff but requires some mathematics to handle the position and rotation properly from 2 coordinates. 11 | 12 | ## Install 13 | 14 | ```shell 15 | npm install --save react-line 16 | ``` 17 | 18 | ## Props 19 | 20 | You need to provide 4 coordinates to draw a line which are the props of the 21 | component : 22 | 23 | ```javascript 24 | static propTypes = { 25 | from: React.PropTypes.shape({ 26 | x: React.PropTypes.number.isRequired, 27 | y: React.PropTypes.number.isRequired, 28 | }), 29 | to: React.PropTypes.shape({ 30 | x: React.PropTypes.number.isRequired, 31 | y: React.PropTypes.number.isRequired, 32 | }), 33 | style: React.PropTypes.string 34 | } 35 | ``` 36 | 37 | `style` is optional and is the css style you want to apply on the line. 38 | The default is `1px solid black`. 39 | 40 | ## Usage 41 | 42 | ```javascript 43 | 48 | ``` 49 | 50 | An octogon : 51 | 52 | ![An octogon using react-line](https://raw.githubusercontent.com/chtefi/react-line/master/octogon.PNG) 53 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class Line extends React.Component { 4 | 5 | static propTypes = { 6 | from: React.PropTypes.shape({ 7 | x: React.PropTypes.number.isRequired, 8 | y: React.PropTypes.number.isRequired, 9 | }), 10 | to: React.PropTypes.shape({ 11 | x: React.PropTypes.number.isRequired, 12 | y: React.PropTypes.number.isRequired, 13 | }), 14 | style: React.PropTypes.string 15 | }; 16 | 17 | render() { 18 | let from = this.props.from; 19 | let to = this.props.to; 20 | if (to.x < from.x) { 21 | from = this.props.to; 22 | to = this.props.from; 23 | } 24 | 25 | const len = Math.sqrt(Math.pow(from.x - to.x, 2) + Math.pow(from.y - to.y, 2)); 26 | const angle = Math.atan((to.y - from.y) / (to.x - from.x)); 27 | 28 | const style = { 29 | position: 'absolute', 30 | transform: `translate(${from.x - .5 * len * (1 - Math.cos(angle))}px, ${from.y + .5 * len * Math.sin(angle)}px) rotate(${angle}rad)`, 31 | width: `${len}px`, 32 | height: `${0}px`, 33 | borderBottom: this.props.style || '1px solid black' 34 | }; 35 | 36 | return
; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /octogon.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sderosiaux/react-line/9848b74cc298a7b30aa5b48a98064d4437b4e010/octogon.PNG -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-line", 3 | "version": "1.0.2", 4 | "description": "Provide a React component to draw a line", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/chtefi/react-line.git" 12 | }, 13 | "keywords": [ 14 | "react", 15 | "line", 16 | "chart", 17 | "dataviz", 18 | "link" 19 | ], 20 | "author": "Stéphane D.", 21 | "license": "MIT", 22 | "bugs": { 23 | "url": "https://github.com/chtefi/react-line/issues" 24 | }, 25 | "homepage": "https://github.com/chtefi/react-line#readme", 26 | "dependencies": { 27 | "react": "^0.13.3" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Line from './index'; 3 | 4 | const LINE_STYLE = '2px dashed blue'; 5 | 6 | // Octogon 7 | const points = [ 8 | { x: 60, y: 0 }, 9 | { x: 120, y: 0 }, 10 | { x: 180, y: 60 }, 11 | { x: 180, y: 120 }, 12 | { x: 120, y: 180 }, 13 | { x: 60, y: 180 }, 14 | { x: 0, y: 120 }, 15 | { x: 0, y: 60 }, 16 | { x: 60, y: 0 }, 17 | ].reduce((lines, p, index, arr) => { 18 | if (index === 0) return lines; 19 | return lines.concat({ 20 | x1: arr[index-1].x, 21 | y1: arr[index-1].y, 22 | x2: p.x, 23 | y2: p.y 24 | }); 25 | }, []); 26 | 27 | export default class App extends React.Component { 28 | render() { 29 | return ( 30 |
31 | { 32 | points.map((p, i) => ) 38 | } 39 |
40 | ); 41 | } 42 | } 43 | --------------------------------------------------------------------------------