diff --git a/editor/svg-editor.css b/editor/svg-editor.css index 5b293d51..e3c41a28 100644 --- a/editor/svg-editor.css +++ b/editor/svg-editor.css @@ -137,6 +137,10 @@ div.color_block { display: none; } +#svg_editor #image_panel { + display: none; +} + #svg_editor #text_panel { display: none; } @@ -157,6 +161,10 @@ div.color_block { vertical-align: 12px; } +#svg_editor #image_panel .image_tool { + vertical-align: 12px; +} + #svg_editor #circle_panel .circle_tool { vertical-align:12px; } diff --git a/editor/svg-editor.html b/editor/svg-editor.html index 61f6b5b8..88c147b5 100644 --- a/editor/svg-editor.html +++ b/editor/svg-editor.html @@ -117,6 +117,21 @@ +
+ | + + + + + + + + + + +
+ +
| @@ -195,6 +210,7 @@ Circle
+ Image Text Poly
diff --git a/editor/svg-editor.js b/editor/svg-editor.js index 554b3725..87c2b4e4 100644 --- a/editor/svg-editor.js +++ b/editor/svg-editor.js @@ -81,7 +81,7 @@ function svg_edit_setup() { // updates the toolbar (colors, opacity, etc) based on the selected element var updateToolbar = function() { - if (selectedElement != null) { + if (selectedElement != null) { //the image thing might be a hack. // get opacity values var fillOpacity = parseFloat(selectedElement.getAttribute("fill-opacity")); if (isNaN(fillOpacity)) { @@ -168,7 +168,7 @@ function svg_edit_setup() { } $('#selected_panel, #multiselected_panel, #rect_panel, #circle_panel,\ - #ellipse_panel, #line_panel, #text_panel').hide(); + #ellipse_panel, #line_panel, #text_panel, #image_panel').hide(); if (elem != null) { $('#angle').val(svgCanvas.getRotationAngle(elem)); $('#selected_panel').show(); @@ -176,6 +176,7 @@ function svg_edit_setup() { // update contextual tools here var panels = { rect: ['radius','x','y','width','height'], + image: ['x','y','width','height'], circle: ['cx','cy','r'], ellipse: ['cx','cy','rx','ry'], line: ['x1','y1','x2','y2'], @@ -215,7 +216,13 @@ function svg_edit_setup() { if (svgCanvas.addedNew) { $('#text').focus().select(); } - } + }else if(el_name == 'image') { + var xlinkNS="http://www.w3.org/1999/xlink"; + $('#image_url').val(elem.getAttributeNS(xlinkNS, "href")); + + } + + } } // if (elem != null) else if (multiselected) { @@ -242,6 +249,8 @@ function svg_edit_setup() { $('#text').focus( function(){ textBeingEntered = true; } ); $('#text').blur( function(){ textBeingEntered = false; } ); + $('#image_url').blur(function(){ svgCanvas.setImageURL(this.value); }); + // bind the selected event to our function that handles updates to the UI svgCanvas.bind("selected", selectedChanged); svgCanvas.bind("changed", elementChanged); @@ -296,6 +305,7 @@ function svg_edit_setup() { $('#text').keyup(function(){ svgCanvas.setTextContent(this.value); }); + $('.attr_changer').change(function() { var attr = this.getAttribute("alt"); @@ -423,6 +433,12 @@ function svg_edit_setup() { $('#tools_rect_show').attr('src', 'images/rect.png'); }; + var clickImage = function(){ + if (toolButtonClick('#tool_image')) { + svgCanvas.setMode('image'); + } + }; + var clickFHRect = function(){ if (toolButtonClick('#tools_rect_show')) { svgCanvas.setMode('fhrect'); @@ -623,6 +639,7 @@ function svg_edit_setup() { $('#tool_circle').mouseup(clickCircle); $('#tool_ellipse').mouseup(clickEllipse); $('#tool_fhellipse').mouseup(clickFHEllipse); + $('#tool_image').mouseup(clickImage); $('#tool_text').click(clickText); $('#tool_poly').click(clickPoly); $('#tool_clear').click(clickClear); diff --git a/editor/svgcanvas.js b/editor/svgcanvas.js index 5e506af4..8693fac1 100644 --- a/editor/svgcanvas.js +++ b/editor/svgcanvas.js @@ -22,6 +22,7 @@ var svgWhiteList = { "rect": ["fill", "fill-opacity", "height", "id", "opacity", "rx", "ry", "stroke", "stroke-dasharray", "stroke-linecap", "stroke-linejoin", "stroke-opacity", "stroke-width", "transform", "width", "x", "y"], "stop": ["id", "offset", "stop-color", "stop-opacity"], "svg": ["id", "height", "transform", "width", "xmlns"], + "image": ["id","width","height","opacity","x","y"], "text": ["fill", "fill-opacity", "font-family", "font-size", "font-style", "font-weight", "id", "opacity", "stroke", "stroke-dasharray", "stroke-linecap", "stroke-linejoin", "stroke-opacity", "stroke-width", "transform", "text-anchor", "x", "y"], }; @@ -1116,6 +1117,20 @@ function BatchCommand(text) { 'y': pt.y }, 1000); break; + + case "image": + changes["x"] = selected.getAttribute("x"); + changes["y"] = selected.getAttribute("y"); + changes["width"] = selected.getAttribute("width"); + changes["height"] = selected.getAttribute("height"); + var pt = remap(changes["x"], changes["y"]); + assignAttributes(selected, { + 'x': pt.x, + 'y': pt.y, + 'width': scalew(changes["width"]), + 'height': scaleh(changes["height"]) + }, 1000); + break; case "rect": changes["x"] = selected.getAttribute("x"); changes["y"] = selected.getAttribute("y"); @@ -1220,6 +1235,8 @@ function BatchCommand(text) { var x = evt.pageX - container.parentNode.offsetLeft + container.parentNode.scrollLeft; var y = evt.pageY - container.parentNode.offsetTop + container.parentNode.scrollTop; + evt.preventDefault() + if($.inArray(current_mode, ['select', 'resize']) == -1) { addGradient(); } @@ -1290,6 +1307,24 @@ function BatchCommand(text) { freehand_min_y = y; freehand_max_y = y; break; + case "image": + started = true; + start_x = x; + start_y = y; + var newImage = addSvgElementFromJson({ + "element": "image", + "attr": { + "x": x, + "y": y, + "width": 0, + "height": 0, + "id": getNextId(), + "opacity": cur_shape.opacity / 2 + } + }); + var xlinkNS="http://www.w3.org/1999/xlink"; + newImage.setAttributeNS(xlinkNS, "href", "images/logo.png") + break; case "square": // FIXME: once we create the rect, we lose information that this was a square // (for resizing purposes this could be important) @@ -1447,6 +1482,10 @@ function BatchCommand(text) { var x = evt.pageX - container.parentNode.offsetLeft + container.parentNode.scrollLeft; var y = evt.pageY - container.parentNode.offsetTop + container.parentNode.scrollTop; var shape = svgdoc.getElementById(getId()); + + evt.preventDefault() + + switch (current_mode) { case "select": @@ -1649,6 +1688,14 @@ function BatchCommand(text) { 'y': Math.min(start_y,y) },1000); break; + case "image": + assignAttributes(shape,{ + 'width': Math.abs(x-start_x), + 'height': Math.abs(y-start_y), + 'x': Math.min(start_x,x), + 'y': Math.min(start_y,y) + },1000); + break; case "circle": var cx = shape.getAttributeNS(null, "cx"); var cy = shape.getAttributeNS(null, "cy"); @@ -1929,6 +1976,10 @@ function BatchCommand(text) { keep = (element.getAttribute('width') != 0 || element.getAttribute('height') != 0); break; + case "image": + keep = (element.getAttribute('width') != 0 || + element.getAttribute('height') != 0); + break; case "circle": keep = (element.getAttribute('r') != 0); break; @@ -2714,6 +2765,10 @@ function BatchCommand(text) { this.changeSelectedAttribute("#text", val); }; + this.setImageURL = function(val) { + this.changeSelectedAttribute("#href", val); + }; + this.setRectRadius = function(val) { var selected = selectedElements[0]; if (selected != null && selected.tagName == "rect") { @@ -2780,7 +2835,10 @@ function BatchCommand(text) { if (attr == "#text") { elem.textContent = newValue; elem = canvas.quickClone(elem); - } + } else if (attr == "#href") { + var xlinkNS="http://www.w3.org/1999/xlink"; + elem.setAttributeNS(xlinkNS, "href", val); + } else elem.setAttribute(attr, newValue); selectedBBoxes[i] = this.getBBox(elem); // Use the Firefox quickClone hack for text elements with gradients or