master
Mark MacKay 2021-06-02 11:08:43 -05:00
parent 9dd3887fb4
commit ae8fd06e1d
14 changed files with 104 additions and 62 deletions

View File

@ -63,7 +63,8 @@
#workarea.nw-resize * {cursor: nw-resize !important;}
#workarea.sw-resize * {cursor: sw-resize !important;}
#workspace.dragging * {
#workspace.dragging *,
body.dragging * {
cursor: url(../images/dragging.png), move;
cursor: -webkit-grabbing;
cursor: -moz-grabbing;

View File

@ -224,6 +224,11 @@
z-index: 1;
top: 0;
left: 0;
cursor: pointer;
}
.draginput:hover .draginput_cursor {
border-color: var(--d6);
}
.draginput_cursor{
@ -231,7 +236,6 @@
top: 50%;
width: 100%;
border-top: solid var(--d4) 1px;
margin-top: -2px;
z-index: 0;
}

View File

@ -39,6 +39,7 @@
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
opacity: 0.7;
}

View File

@ -57,6 +57,11 @@
right: var(--x2);
}
.draginput:hover #preview_font:after {
border-right-color: var(--z3);
background: linear-gradient(to right, rgba(0,0,0,0), var(--z3));
}
#preview_font:after {
content: '';
position: absolute;

View File

@ -372,7 +372,7 @@
<input id="textPath_offset" class="attr_changer" data-title="Change offset" data-attr="offset" pattern="[0-9]*" />
<span>Offset</span>
</label>
<div class="draginput draginput-button draginput-button-delete" id="tool_textPath_remove" data-title="Remove path">Remove path</div>
<div class="draginput draginput-button draginput-button-delete" id="tool_release_text_on_path" data-title="Remove path">Remove path</div>
</div>
@ -584,6 +584,7 @@
</div>
</div>
<div class="clearfix"></div>
<div class="button full" id="tool_text_on_path" title="Place text on path">Place text on path</div>
</div>

View File

@ -68,13 +68,13 @@ MD.Canvas = function(){
if (w === 'fit' || h === 'fit') state.set("canvasSize", res);
$("#canvas_width").val(w);
$("#canvas_height").val(h);
state.set("canvasContent", svgCanvas.getSvgString());
}
function changeSize(){
function changeSize(attr, val, completed){
const w = $("#canvas_width").val();
const h = $("#canvas_height").val();
state.set("canvasSize", [w,h]);
if (completed) editor.saveCanvas();
}
function update(center, new_ctr) {

View File

@ -79,6 +79,7 @@ MD.Import = function(){
function loadSvgString(str, callback) {
var success = svgCanvas.setSvgString(str) !== false;
callback = callback || $.noop;
if(success) {
callback(true);
@ -96,6 +97,7 @@ MD.Import = function(){
var reader = new FileReader();
reader.onloadend = function(e) {
loadSvgString(e.target.result);
editor.saveCanvas();
editor.canvas.update(true);
};
reader.readAsText(f.files[0]);

View File

@ -1,61 +1,61 @@
MD.Keyboard = function(){
const keys = {
"v": { name: "Select tool", cb: ()=> state.set("canvasMode", "select") },
"q": { name: "Freehand tool", cb: ()=> state.set("canvasMode", "fhpath") },
"l": { name: "Line tool", cb: ()=> state.set("canvasMode", "fhplineath")},
"r": { name: "Rectangle tool", cb: ()=> state.set("canvasMode", "rect")},
"o": { name: "Ellipse tool", cb: ()=> state.set("canvasMode", "ellipse")},
"s": { name: "Shape tool", cb: ()=> state.set("canvasMode", "shapelib")},
"p": { name: "Path tool", cb: ()=> state.set("canvasMode", "path")},
"t": { name: "Text tool", cb: ()=> state.set("canvasMode", "text")},
"z": { name: "Zoom tool", cb: ()=> state.set("canvasMode", "zoom")},
"e": { name: "Eyedropper tool", cb: ()=> state.set("canvasMode", "eyedropper")},
"x": { name: "Focus fill/stroke", cb: ()=> editor.focusPaint()},
"shift_x": { name: "Switch fill/stroke", cb: ()=> editor.switchPaint()},
"v": { name: "Select tool", cb: ()=> state.set("canvasMode", "select") },
"q": { name: "Freehand tool", cb: ()=> state.set("canvasMode", "fhpath") },
"l": { name: "Line tool", cb: ()=> state.set("canvasMode", "fhplineath")},
"r": { name: "Rectangle tool", cb: ()=> state.set("canvasMode", "rect")},
"o": { name: "Ellipse tool", cb: ()=> state.set("canvasMode", "ellipse")},
"s": { name: "Shape tool", cb: ()=> state.set("canvasMode", "shapelib")},
"p": { name: "Path tool", cb: ()=> state.set("canvasMode", "path")},
"t": { name: "Text tool", cb: ()=> state.set("canvasMode", "text")},
"z": { name: "Zoom tool", cb: ()=> state.set("canvasMode", "zoom")},
"e": { name: "Eyedropper tool", cb: ()=> state.set("canvasMode", "eyedropper")},
"x": { name: "Focus fill/stroke", cb: ()=> editor.focusPaint()},
"shift_x": { name: "Switch fill/stroke", cb: ()=> editor.switchPaint()},
"alt": { name: false, cb: ()=> $("#workarea").toggleClass("out", state.get("canvasMode") === "zoom" )},
"cmd_s": { name: "Save SVG File", cb: ()=> editor.save()},
"cmd_z": { name: "Undo", cb: ()=> editor.undo()},
"cmd_y": { name: "Redo", cb: ()=> editor.redo()},
"cmd_shift_z": { name: "Redo", cb: ()=> editor.redo()},
"cmd_c": { name: "Copy", cb: ()=> editor.copySelected()},
"cmd_x": { name: "Cut", cb: ()=> editor.cutSelected()},
"cmd_v": { name: "Paste", cb: ()=> editor.pasteSelected()},
"cmd_d": { name: "Duplicate", cb: ()=> editor.duplicateSelected()},
"cmd_u": { name: "View source", cb: ()=> editor.source()},
"cmd_a": { name: "Select All", cb: ()=> svgCanvas.selectAllInCurrentLayer()},
"cmd_b": { name: "Set bold text", cb: ()=> editor.text.setBold()},
"cmd_i": { name: "Set italic text", cb: ()=> editor.text.setItalic()},
"cmd_g": { name: "Group selected", cb: ()=> editor.groupSelected()},
"cmd_shift_z": { name: "Redo", cb: ()=> editor.redo()},
"cmd_c": { name: "Copy", cb: ()=> editor.copySelected()},
"cmd_x": { name: "Cut", cb: ()=> editor.cutSelected()},
"cmd_v": { name: "Paste", cb: ()=> editor.pasteSelected()},
"cmd_d": { name: "Duplicate", cb: ()=> editor.duplicateSelected()},
"cmd_u": { name: "View source", cb: ()=> editor.source()},
"cmd_a": { name: "Select All", cb: ()=> svgCanvas.selectAllInCurrentLayer()},
"cmd_b": { name: "Set bold text", cb: ()=> editor.text.setBold()},
"cmd_i": { name: "Set italic text", cb: ()=> editor.text.setItalic()},
"cmd_g": { name: "Group selected", cb: ()=> editor.groupSelected()},
"cmd_shift_g": { name: "Ungroup", cb: ()=> editor.ungroupSelected()},
"cmd_o": { name: "Open SVG File", cb: ()=> editor.import.open()},
"cmd_k": { name: "Place image", cb: ()=> editor.import.place()},
"cmd_o": { name: "Open SVG File", cb: ()=> editor.import.open()},
"cmd_k": { name: "Place image", cb: ()=> editor.import.place()},
"backspace": { name: "Delete", cb: ()=> editor.deleteSelected()},
"ctrl_arrowleft": { name: "Rotate -1deg", cb: ()=> editor.rotateSelected(0,1)},
"ctrl_arrowright": { name: "Rotate +1deg", cb: ()=> editor.rotateSelected(1,1)},
"ctrl_shift_arrowleft": { name: "Rotate -5deg", cb: ()=> editor.rotateSelected(0,5)},
"ctrl_shift_arrowright": { name: "Rotate +5deg ", cb: ()=> editor.rotateSelected(1,5)},
"shift_o": { name: "Next item", cb: ()=> svgCanvas.cycleElement(0)},
"shift_p": { name: "Prev item", cb: ()=> svgCanvas.cycleElement(1)},
"shift_r": { name: "Show/hide rulers", cb: ()=> editor.rulers.toggleRulers()},
"cmd_+": { name: "Zoom in", cb: ()=> editor.zoom.multiply(1.5)},
"cmd_-": { name: "Zoom out", cb: ()=> editor.zoom.multiply(0.75)},
"cmd_=": { name: "Actual size", cb: ()=> editor.zoom.reset()},
"arrowleft": { name: "Nudge left", cb: ()=> editor.moveSelected(-1,0)},
"arrowright": { name: "Nudge right", cb: ()=> editor.moveSelected(1,0)},
"arrowup": { name: "Nudge up", cb: ()=> editor.moveSelected(0,-1)},
"arrowdown": { name: "Nudge down", cb: ()=> editor.moveSelected(0,1)},
"shift_arrowleft": {name: "Jump left", cb: () => editor.moveSelected(state.get("canvasSnapStep") * -1, 0)},
"shift_o": { name: "Next item", cb: ()=> svgCanvas.cycleElement(0)},
"shift_p": { name: "Prev item", cb: ()=> svgCanvas.cycleElement(1)},
"shift_r": { name: "Show/hide rulers", cb: ()=> editor.rulers.toggleRulers()},
"cmd_+": { name: "Zoom in", cb: ()=> editor.zoom.multiply(1.5)},
"cmd_-": { name: "Zoom out", cb: ()=> editor.zoom.multiply(0.75)},
"cmd_=": { name: "Actual size", cb: ()=> editor.zoom.reset()},
"arrowleft": { name: "Nudge left", cb: ()=> editor.moveSelected(-1,0)},
"arrowright": { name: "Nudge right", cb: ()=> editor.moveSelected(1,0)},
"arrowup": { name: "Nudge up", cb: ()=> editor.moveSelected(0,-1)},
"arrowdown": { name: "Nudge down", cb: ()=> editor.moveSelected(0,1)},
"shift_arrowleft": {name: "Jump left", cb: () => editor.moveSelected(state.get("canvasSnapStep") * -1, 0)},
"shift_arrowright": {name: "Jump right", cb: () => editor.moveSelected(state.get("canvasSnapStep") * 1, 0)},
"shift_arrowup": {name: "Jump up", cb: () => editor.moveSelected(0, state.get("canvasSnapStep") * -1)},
"shift_arrowdown": {name: "Jump down", cb: () => editor.moveSelected(0, state.get("canvasSnapStep") * 1)},
"cmd_arrowup":{ name: "Bring forward", cb: () => editor.moveUpSelected()},
"shift_arrowup": {name: "Jump up", cb: () => editor.moveSelected(0, state.get("canvasSnapStep") * -1)},
"shift_arrowdown": {name: "Jump down", cb: () => editor.moveSelected(0, state.get("canvasSnapStep") * 1)},
"cmd_arrowup":{ name: "Bring forward", cb: () => editor.moveUpSelected()},
"cmd_arrowdown":{ name: "Send backward", cb: () => editor.moveDownSelected()},
"cmd_shift_arrowup":{ name: "Bring to front", cb: () => editor.moveToTopSelected()},
"cmd_shift_arrowdown":{ name: "Send to back", cb: () => editor.moveToBottomSelected()},
"escape": { name: false, cb: ()=> editor.escapeMode()},
"enter": { name: false, cb: ()=> editor.escapeMode()},
" ": { name: "Pan canvas", cb: (e)=> editor.pan.startPan(e)},
"enter": { name: false, cb: ()=> editor.escapeMode()},
" ": { name: "Pan canvas", cb: (e)=> editor.pan.startPan(e)},
};
document.addEventListener("keydown", function(e){

View File

@ -82,6 +82,8 @@ MD.Panel = function(){
svgCanvas.pathActions.opencloseSubPath();
});
// Text Path
function show(elem) {
$('.context_panel').hide();
if (elem === "canvas") return $('#canvas_panel').show();

View File

@ -146,7 +146,7 @@ MD.Editor = function(){
svgCanvas.leaveContext()
}
else
state.set("canvasContent", svgCanvas.getSvgString())
saveCanvas()
}
// called when we've selected a different element
@ -198,7 +198,7 @@ MD.Editor = function(){
if (!svgCanvas.getContext()) {
state.set("canvasContent", svgCanvas.getSvgString())
saveCanvas();
}
}
@ -206,7 +206,7 @@ MD.Editor = function(){
if (attr === "opacity") value *= 0.01;
if (completed) {
svgCanvas.changeSelectedAttribute(attr, value);
state.set("canvasContent", svgCanvas.getSvgString());
saveCanvas();
}
else svgCanvas.changeSelectedAttributeNoUndo(attr, value);
}
@ -300,6 +300,11 @@ MD.Editor = function(){
}});
};
function saveCanvas(){
console.log("saved")
state.set("canvasContent", svgCanvas.getSvgString());
}
function toggleWireframe() {
editor.menu.flash($('#view_menu'));
$('#tool_wireframe').toggleClass('push_button_pressed');
@ -381,6 +386,7 @@ MD.Editor = function(){
this.shortcuts = shortcuts;
this.donate = donate;
this.source = source;
this.saveCanvas = saveCanvas;
this.export = function(){
if(window.canvg) {

View File

@ -108,7 +108,7 @@ MD.Eyedropper = function() {
changes[attrname] = elem.getAttribute(attrname);
elem.setAttribute(attrname, newvalue);
};
var batchCmd = new S.BatchCommand();
var batchCmd = new svgedit.history.BatchCommand();
opts.selectedElements.forEach(function(element){
if (currentStyle.fillPaint) change(element, "fill", currentStyle.fillPaint);
if (currentStyle.fillOpacity) change(element, "fill-opacity", currentStyle.fillOpacity);

View File

@ -128,6 +128,9 @@ $.each(svgWhiteList_, function(elt,atts){
svgWhiteListNS_[elt] = attNS;
});
svgedit.sanitize.svgWhiteList = function() { return svgWhiteList_; }
// temporarily expose these
svgedit.sanitize.getNSMap = function() { return nsMap_; }

View File

@ -5830,12 +5830,25 @@ this.setSvgString = function(xmlString) {
if (!href) return;
const path = svgcontent.querySelector(href);
const offset = el.getAttribute("startOffset");
el.setAttribute("xml:space", "default");
// convert percentage based to absolute
if (offset.includes("%") && path) {
const totalLength = path.getTotalLength();
const pct = parseFloat(offset) * .01;
el.setAttribute("startOffset", (pct * totalLength).toFixed(0))
}
const tspan = el.querySelector("tspan");
const text = el.closest("text");
if (tspan && text) {
// grab the first tspan and apply it to the text element
svgedit.sanitize.svgWhiteList()["text"].forEach(attr => {
const value = tspan.getAttribute(attr);
if (value) {
tspan.removeAttribute(attr);
text.setAttribute(attr, value);
}
});
}
})
// Set ref element for <use> elements
@ -6044,13 +6057,6 @@ this.importSvgString = function(xmlString) {
var symbol = svgdoc.createElementNS(svgns, "symbol");
var defs = findDefs();
if(svgedit.browser.isGecko()) {
// Move all gradients into root for Firefox, workaround for this bug:
// https://bugzilla.mozilla.org/show_bug.cgi?id=353575
// TODO: Make this properly undo-able.
$(svg).find('linearGradient, radialGradient, pattern').appendTo(defs);
}
while (svg.firstChild) {
var first = svg.firstChild;
symbol.appendChild(first);
@ -7511,10 +7517,7 @@ this.setTextContent = function(val) {
this.textPath = function(){
const text = selectedElements.find(element => element.tagName === "text");
var path = selectedElements.find(element => element.tagName === "path" || element.tagName === "ellipse");
if (path.tagName === "ellipse") {
console.log("ellipse")
}
var path = selectedElements.find(element => element.tagName === "path");
if (!text || !path) return false;
const textPath = svgdoc.createElementNS(svgns, "textPath");
textPath.textContent = text.textContent;
@ -7522,6 +7525,7 @@ this.textPath = function(){
text.setAttribute("text-anchor", "middle");
text.setAttribute("x", 0);
text.setAttribute("y", 0);
textPath.setAttribute("xml:space", "default");
textPath.setAttribute("xlink:href", "#" + path.id);
textPath.setAttribute("href", "#" + path.id);
const offset = (path.getTotalLength()/2).toFixed(0)

View File

@ -10,3 +10,16 @@ utils.findGetParameter = function(parameterName) {
}
return result;
}
utils.throttle = function (callback, limit) {
var waiting = false;
return function () {
if (!waiting) {
callback.apply(this, arguments);
waiting = true;
setTimeout(function () {
waiting = false;
}, limit);
}
}
}