<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>svg editor</title> <style> #toolbox{ position: absolute; top: 0; bottom: 0; left: 0; width: 250px; border-right: 1px solid #CCC; } #toolbox h2{ margin: 0; padding: 0; background: #EEE; font-size: 16px; height: 24px; line-height: 24px; padding: 5px 10px; } #toolbox form{ padding: 10px; } #canvas{ position: absolute; left:260px; top: 10px; bottom: 10px; right: 10px; box-shadow: 2px 2px 10px rgba(0,0,0,.4); border-radius: 5px; } label{ display: inline-block; width: 80px; text-align: right; } </style> </head> <body> <div id="toolbox"> <h2>创建</h2> <form action="" id="create-shape"> <button type="button" create="rect">Rect</button> <button type="button" create="circle">Circle</button> <button type="button" create="ellipse">Ellipse</button> <button type="button" create="line">Line</button> </form> <h2>形状</h2> <form action="" id="shape-attrs"> 请先创建图形 </form> <h2>外观和变换</h2> <form action="" id="look-and-transform" disabled> <p> <label for="" style="display: inline">填充</label> <input type="color" id="fill" value="#ffffff"> </p> <p> <lable style="display: inline">描边</lable> <input type="color" id="stroke" value="#ff0000"> <input type="range" id="strokeWidth" value="1"> </p> <p> <label for="">translateX</label> <input type="range" id="translateX" min="-400" max="400" value="0"> <label for="">translateY</label> <input type="range" id="translateY" min="-400" max="400" value="0"> <label for="">rotate</label> <input type="range" id="rotate" min="-180" max="180" value="0"> <label for="">scale</label> <input type="range" id="scale" min="-1" max="2" step="0.01" value="1"> </p> </form> </div> <div id="canvas"></div> </body> <script> var SVG_NS = 'http://www.w3.org/2000/svg'; // 图形及对应默认属性 var shapeInfo = { rect:'x:10,y:10,200,height:100,rx:0,ry:0', circle:'cx:200,cy:200,r:50', ellipse:'cx:200,cy:200,rx:80,ry:30', line:'x1:10,y1:10,x2:100,y2:100' }; // 默认公共属性 var defaultAttrs = { fill: '#ffffff', stroke: '#ff0000' }; var createForm = document.getElementById('create-shape'); var attrForm = document.getElementById('shape-attrs'); var lookForm = document.getElementById('look-and-transform'); var svg = createSVG(); var selected = null; svg.addEventListener('click',function(e){ if(e.target.tagName.toLowerCase() in shapeInfo){ select(e.target); } }); createForm.addEventListener('click',function(e){ if(e.target.tagName.toLowerCase()=='button'){ create(e.target.getAttribute('create')); } }); attrForm.addEventListener('input',function (e) { if(e.target.tagName.toLowerCase() !='input')return; var handle = e.target; selected.setAttribute(handle.name,handle.value); }); lookForm.addEventListener('input',function(e){ if(e.target.tagName.toLowerCase()!='input')return; if(!selected)return; selected.setAttribute('fill',fill.value); selected.setAttribute('stroke',stroke.value); selected.setAttribute('stroke-width',strokeWidth.value); selected.setAttribute('transform',encodeTranform({ tx:translateY.value, ty:translateY.value, scale:scale.value, rotate:rotate.value })); }); function createSVG () { var svg = document.createElementNS(SVG_NS,'svg'); svg.setAttribute('width','100%'); svg.setAttribute('height','100%'); canvas.appendChild(svg); return svg; } function create (name) { var shape = document.createElementNS(SVG_NS,name); svg.appendChild(shape); select(shape); } function select (shape) { var attrs = shapeInfo[shape.tagName].split(','); var attr,name,value; attrForm.innerHTML = ""; while(attrs.length){ attr = attrs.shift().split(':'); name = attr[0]; value = shape.getAttribute(name)||attr[1]; createHandle(shape,name,value); shape.setAttribute(name,value); } for(name in defaultAttrs){ value = shape.getAttribute(name)||defaultAttrs[name]; shape.setAttribute(name,value); } selected = shape; updateLookHandle(); } function createHandle (shape,name,value) { var label = document.createElement('label'); label.textContent = name; var handle = document.createElement('input'); handle.setAttribute('name',name); handle.setAttribute('type','range'); handle.setAttribute('value',value); handle.setAttribute('min',0); handle.setAttribute('max',800); attrForm.appendChild(label); attrForm.appendChild(handle); } function updateLookHandle () { fill.value = selected.getAttribute('fill'); stroke.value = selected.getAttribute('stroke'); var t = decodeTransform(selected.getAttribute('transform')); translateX.value = t?t.tx:0; translateY.value = t?t.ty:0; rotate.value = t?t.rotate:0; scale.value = t?t.scale:1; } function decodeTransform (transString) { var match = /translate((d+),(d+))srotate((d+))sscale((d+))/.exec(transString); return match?{ tx:+match[1], ty:+match[2], rotate:+match[3], scale:+match[4] }:null; } function encodeTranform (transObject) { return ['translate(',transObject.tx,',',transObject.ty,') ', 'rotate(',transObject.rotate,') ', 'scale(',transObject.scale,')'].join(''); } </script> </html>