├── LICENSE ├── README.md ├── index.html ├── js ├── Editor.js ├── Selector.js └── Source.js └── screenshot.png /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Mr.doob 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # svg-editor 2 | [![screenshot.png](https://raw.githubusercontent.com/mrdoob/svg-editor/master/screenshot.png)](https://mrdoob.github.io/svg-editor/) 3 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | SVG Editor 4 | 5 | 66 | 67 | 68 | 69 | 70 | outline 71 |
72 | 73 | 74 | 75 |
76 | 77 | 78 | 79 |
80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 222 | 223 | 224 | 225 | -------------------------------------------------------------------------------- /js/Editor.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com 3 | */ 4 | 5 | class Editor { 6 | 7 | constructor( svg ) { 8 | 9 | this.svg = svg; 10 | this.source = null; 11 | 12 | } 13 | 14 | addElement( element ) { 15 | 16 | this.svg.appendChild( element ); 17 | this.svg.appendChild( document.createTextNode( '\n' ) ); 18 | 19 | this.source.setText( this.toString() ); 20 | 21 | } 22 | 23 | setSource( source ) { 24 | 25 | this.source = source; 26 | 27 | } 28 | 29 | setSVG( svg ) { 30 | 31 | this.svg.innerHTML = svg.documentElement.innerHTML; 32 | this.source.setText( this.toString() ); 33 | 34 | } 35 | 36 | clear() { 37 | 38 | this.svg.textContent = ''; 39 | this.source.setText( this.toString() ); 40 | 41 | } 42 | 43 | toString() { 44 | 45 | // TODO Checkbox for auto-formating 46 | 47 | return [ 48 | '\n', 49 | '\n', 50 | this.svg.innerHTML, 51 | '' 52 | ].join( '' ); 53 | 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /js/Selector.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com 3 | */ 4 | 5 | class Selector { 6 | 7 | constructor( stage ) { 8 | 9 | var selection = document.createElement( 'span' ); 10 | selection.style.position = 'absolute'; 11 | selection.style.display = 'block'; 12 | selection.style.outline = 'solid 2px #99f'; 13 | selection.style.pointerEvents = 'none'; 14 | document.body.appendChild( selection ); 15 | 16 | // 17 | 18 | var selected = null; 19 | var offset = { x: 0, y: 0 }; 20 | 21 | function updateSelection( element ) { 22 | 23 | if ( element.isSameNode( stage ) ) { 24 | 25 | selection.style.display = 'none'; 26 | return; 27 | 28 | } 29 | 30 | var rect = element.getBoundingClientRect(); 31 | 32 | selection.style.left = rect.left + 'px'; 33 | selection.style.top = rect.top + 'px'; 34 | selection.style.width = rect.width + 'px'; 35 | selection.style.height = rect.height + 'px'; 36 | 37 | selection.style.display = 'block'; 38 | 39 | } 40 | 41 | // 42 | 43 | stage.addEventListener( 'mouseover', function ( event ) { 44 | 45 | var target = event.target; 46 | updateSelection( target ); 47 | 48 | } ); 49 | 50 | stage.addEventListener( 'mousedown', function ( event ) { 51 | 52 | var target = event.target; 53 | 54 | if ( target.isSameNode( stage ) === false ) { 55 | 56 | if ( target.tagName === 'circle' ) { 57 | 58 | offset.x = parseFloat( target.getAttribute( 'cx' ) ) - event.clientX; 59 | offset.y = parseFloat( target.getAttribute( 'cy' ) ) - event.clientY; 60 | 61 | } else { 62 | 63 | offset.x = parseFloat( target.getAttribute( 'x' ) ) - event.clientX; 64 | offset.y = parseFloat( target.getAttribute( 'y' ) ) - event.clientY; 65 | 66 | } 67 | 68 | selected = target; 69 | 70 | } 71 | 72 | } ); 73 | 74 | stage.addEventListener( 'mouseup', function ( event ) { 75 | 76 | selected = null; 77 | 78 | } ); 79 | 80 | window.addEventListener( 'mousemove', function ( event ) { 81 | 82 | if ( selected ) { 83 | 84 | if ( selected.tagName === 'circle' ) { 85 | 86 | selected.setAttribute( 'cx', event.clientX + offset.x ); 87 | selected.setAttribute( 'cy', event.clientY + offset.y ); 88 | 89 | } else { 90 | 91 | selected.setAttribute( 'x', event.clientX + offset.x ); 92 | selected.setAttribute( 'y', event.clientY + offset.y ); 93 | 94 | } 95 | 96 | updateSelection( selected ); 97 | 98 | } 99 | 100 | } ); 101 | 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /js/Source.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com 3 | */ 4 | 5 | class Source { 6 | 7 | constructor( dom ) { 8 | 9 | this.dom = dom; 10 | 11 | } 12 | 13 | setText( text ) { 14 | 15 | this.dom.textContent = text; 16 | 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrdoob/svg-editor/c25b03dfe1048b50f555df1da0bec97eccaed17b/screenshot.png --------------------------------------------------------------------------------