merging textpath
parent
d1941d7dde
commit
187ce276d2
|
@ -16,6 +16,14 @@
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
.draginput.button {
|
||||
text-align: center;
|
||||
color: #999;
|
||||
padding-top: 10px;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.draginput .caret {
|
||||
border: solid transparent 5px;
|
||||
border-top-color: var(--z9);
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
#tool_save,
|
||||
#tool_source,
|
||||
#tool_export,
|
||||
#tool_wireframe + .separator {
|
||||
display: none;
|
||||
}
|
||||
*/
|
Binary file not shown.
|
@ -1,4 +1,4 @@
|
|||
<svg viewBox="0 0 16 16" width="16" height="16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M-.1 16.1L16 .04V16.1H-.1z" fill="#ccc"></path>
|
||||
<path d="M0 16.1V.1l16 16H0z" fill="#666"></path>
|
||||
<svg width="16" height="15" viewBox="0 0 16 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M16 0H11L8 6V0H4V15H8V9.5L11 15H16L11.517 7.49007L16 0Z" fill="#1EB5E8"></path>
|
||||
<path d="M0 0H4H8V3H4V6H8V9H4V15H0V9V6V3V0Z" fill="white"></path>
|
||||
</svg>
|
Before Width: | Height: | Size: 201 B After Width: | Height: | Size: 261 B |
|
@ -6,9 +6,9 @@
|
|||
<link rel="icon" href="images/favicon.svg" sizes="any" type="image/svg+xml">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes"/>
|
||||
<title>Method Draw Vector Editor</title>
|
||||
<title>Fujikohsan Vector Editor</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="description" content="Method Draw is an open source SVG editor for the web, you can use it online without signing up.">
|
||||
<meta name="description" content="Fujikohsan Vector Editor">
|
||||
|
||||
<!-- build:css all.css -->
|
||||
<link rel="stylesheet" href="css/base.css" type="text/css"/>
|
||||
|
@ -28,6 +28,7 @@
|
|||
<link rel="stylesheet" href="css/keyboard.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="css/dialog.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="css/method-draw.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="css/fve.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="css/app.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="css/tools.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="css/button.css" type="text/css"/>
|
||||
|
@ -55,9 +56,9 @@
|
|||
<div id="menu_bar">
|
||||
<a class="menu">
|
||||
<div class="menu_title" id="logo">
|
||||
<svg viewBox="0 0 16 16" width="16" height="16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M-.1 16.1L16 .04V16.1H-.1z" fill="var(--z12)"></path>
|
||||
<path d="M0 16.1V.1l16 16H0z" fill="var(--z6)"></path>
|
||||
<svg width="16" height="15" viewBox="0 0 16 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M16 0H11L8 6V0H4V15H8V9.5L11 15H16L11.517 7.49007L16 0Z" fill="#1EB5E8"></path>
|
||||
<path d="M0 0H4H8V3H4V6H8V9H4V15H0V9V6V3V0Z" fill="white"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="menu_list">
|
||||
|
@ -122,7 +123,7 @@
|
|||
<div class="menu_item push_button_pressed" id="tool_rulers">View Rulers <span class="shortcut">⇧R</span></div>
|
||||
<div class="menu_item" id="tool_wireframe">View Wireframe</div>
|
||||
<div class="separator"></div>
|
||||
<div class="menu_item" id="tool_source" data-action="source">Source... <span class="shortcut">⌘U</span></div>
|
||||
<div class="menu_item" id="tool_source" data-action="source">View Source... <span class="shortcut">⌘U</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -362,7 +363,7 @@
|
|||
<div class="toolset draginput twocol" id="tool_font_family">
|
||||
<!-- Font family -->
|
||||
<span>Font</span>
|
||||
<div id="preview_font" style="font-family: sans-serif">sans-serif</div>
|
||||
<div id="preview_font"></div>
|
||||
<div class="caret"></div>
|
||||
<input id="font_family" data-title="Change Font Family" size="12" type="hidden" />
|
||||
<select id="font_family_dropdown">
|
||||
|
@ -549,9 +550,12 @@
|
|||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
|
||||
<div class="tool_button" id="tool_text_on_path" title="Place text on path">Place text on path</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="stroke_panel" class="context_panel">
|
||||
|
@ -735,6 +739,7 @@
|
|||
<script type="text/javascript" src="js/lib/jquery.jgraduate.js"></script>
|
||||
<script type="text/javascript" src="js/lib/jquery.contextMenu.js"></script>
|
||||
<script type="text/javascript" src="js/lib/jquery-ui-1.8.17.custom.min.js"></script>
|
||||
<script type="text/javascript" src="js/lib/css.min.js"></script>
|
||||
<script type="text/javascript" src="js/jquery.attr.js"></script>
|
||||
<script type="text/javascript" src="js/lib/jquery-draginput.js"></script>
|
||||
<script type="text/javascript" src="js/utils.js"></script>
|
||||
|
@ -765,6 +770,7 @@
|
|||
<script type="text/javascript" src="js/Import.js"></script>
|
||||
<script type="text/javascript" src="js/PaintBox.js"></script>
|
||||
<script type="text/javascript" src="js/Palette.js"></script>
|
||||
<script type="text/javascript" src="js/Textonpath.js"></script>
|
||||
<script type="text/javascript" src="js/Zoom.js"></script>
|
||||
<script type="text/javascript" src="js/Modal.js"></script>
|
||||
<script type="text/javascript" src="js/ContextMenu.js"></script>
|
||||
|
@ -775,7 +781,6 @@
|
|||
<script type="text/javascript" src="js/lib/jpicker.min.js"></script>
|
||||
<script type="text/javascript" src="js/lib/mousewheel.js"></script>
|
||||
<script type="text/javascript" src="js/eyedropper.js"></script>
|
||||
<!--<script type="text/javascript" src="js/grid.js"></script>-->
|
||||
<script type="text/javascript" src="js/lib/requestanimationframe.js"></script>
|
||||
<script type="text/javascript" src="js/lib/taphold.js"></script>
|
||||
<script type="text/javascript" src="js/lib/filesaver.js"></script>
|
||||
|
|
|
@ -33,12 +33,12 @@ MD.Panel = function(){
|
|||
$('#text_x') .dragInput({ min: null, max: null, step: 1, callback: editor.changeAttribute, cursor: false });
|
||||
$('#image_y') .dragInput({ min: null, max: null, step: 1, callback: editor.changeAttribute, cursor: false });
|
||||
$('#rect_rx') .dragInput({ min: 0, max: 100, step: 1, callback: editor.changeAttribute, cursor: true });
|
||||
$('#stroke_width') .dragInput({ min: 0, max: 99, step: 1, callback: editor.changeAttribute, cursor: true, smallStep: 0.1, start: 1.5 });
|
||||
$('#stroke_width') .dragInput({ min: 0, max: 99, step: 1, callback: editor.changeAttribute, cursor: true, smallStep: 0.1, start: 1.5 });
|
||||
$('#angle') .dragInput({ min: -180, max: 180, step: 1, callback: editor.changeRotationAngle, cursor: false, dragAdjust: 0.5 });
|
||||
$('#font_size') .dragInput({ min: 1, max: 250, step: 1, callback: editor.text.changeFontSize, cursor: true, stepfunc: editor.stepFontSize, dragAdjust: .15 });
|
||||
$('#font_size') .dragInput({ min: 1, max: 250, step: 1, callback: editor.text.changeFontSize, cursor: true, stepfunc: editor.stepFontSize, dragAdjust: .15 });
|
||||
$('#group_opacity').dragInput({ min: 0, max: 100, step: 5, callback: editor.changeAttribute, cursor: true, start: 100 });
|
||||
$('#blur') .dragInput({ min: 0, max: 10, step: .1, callback: editor.changeBlur, cursor: true, start: 0 });
|
||||
|
||||
$('#textPath_offset').dragInput({ min: 0, max: null, step: 1, callback: editor.text.setTextPathAttr,cursor: true, start: 0 });
|
||||
|
||||
// Align
|
||||
|
||||
|
@ -82,7 +82,6 @@ MD.Panel = function(){
|
|||
svgCanvas.pathActions.opencloseSubPath();
|
||||
});
|
||||
|
||||
|
||||
function show(elem) {
|
||||
$('.context_panel').hide();
|
||||
if (elem === "canvas") return $('#canvas_panel').show();
|
||||
|
@ -100,8 +99,42 @@ MD.Panel = function(){
|
|||
$.fn.dragInput.updateCursor($('#blur')[0])
|
||||
}
|
||||
|
||||
function pathEditContext(){
|
||||
$('.context_panel').hide();
|
||||
$('#path_node_panel').show();
|
||||
$('#stroke_panel').hide();
|
||||
var point = svgCanvas.pathActions.getNodePoint();
|
||||
$('#tool_add_subpath').removeClass('push_button_pressed').addClass('tool_button');
|
||||
$('#tool_node_delete').toggleClass('disabled', !svgCanvas.pathActions.canDeleteNodes);
|
||||
if(point) {
|
||||
var seg_type = $('#seg_type');
|
||||
point.x = svgedit.units.convertUnit(point.x);
|
||||
point.y = svgedit.units.convertUnit(point.y);
|
||||
$('#path_node_x').val(Math.round(point.x));
|
||||
$('#path_node_y').val(Math.round(point.y));
|
||||
if(point.type) {
|
||||
seg_type.val(point.type).removeAttr('disabled');
|
||||
$("#seg_type_label").html(point.type === 4 ? "Straight" : "Curve")
|
||||
} else {
|
||||
seg_type.val(4).attr('disabled','disabled');
|
||||
}
|
||||
}
|
||||
$("#panels").removeClass("multiselected")
|
||||
$("#stroke_panel").hide();
|
||||
$("#canvas_panel").hide();
|
||||
return;
|
||||
}
|
||||
|
||||
function canPutTextOnPath(elems) {
|
||||
if (elems.length !== 2) return false;
|
||||
const text = elems.find(elem => elem.tagName === "text");
|
||||
const path = elems.find(elem => ["ellipse", "circle", "line", "polyline", "polygon", "rect", "path"].indexOf(elem.tagName) > -1);
|
||||
return (!!text && !!path);
|
||||
}
|
||||
|
||||
|
||||
function updateContextPanel(elems) {
|
||||
if (!elems) elems = editor.selected;
|
||||
if (!elems) elems = editor.selected;
|
||||
var elem = elems[0] || editor.selected[0];
|
||||
const isNode = svgCanvas.pathActions.getNodePoint()
|
||||
// If element has just been deleted, consider it null
|
||||
|
@ -122,7 +155,9 @@ MD.Panel = function(){
|
|||
if (multiselected) {
|
||||
const multi = elems.filter(Boolean);
|
||||
elem = (svgCanvas.elementsAreSame(multi)) ? multi[0] : null
|
||||
if (elem) $("#panels").addClass("multiselected")
|
||||
if (elem) $("#panels").addClass("multiselected");
|
||||
const canTextPath = canPutTextOnPath(multi);
|
||||
$("#tool_text_on_path").toggle(canTextPath);
|
||||
}
|
||||
|
||||
if (!elem && !multiselected) {
|
||||
|
@ -132,6 +167,7 @@ MD.Panel = function(){
|
|||
}
|
||||
|
||||
if (elem !== null) {
|
||||
|
||||
$("#stroke_panel").show();
|
||||
var elname = elem.nodeName;
|
||||
var angle = svgCanvas.getRotationAngle(elem);
|
||||
|
@ -151,8 +187,10 @@ MD.Panel = function(){
|
|||
y = bb.y;
|
||||
}
|
||||
}
|
||||
|
||||
x = svgedit.units.convertUnit(x);
|
||||
y = svgedit.units.convertUnit(y);
|
||||
|
||||
$("#" + elname +"_x").val(Math.round(x))
|
||||
$("#" + elname +"_y").val(Math.round(y))
|
||||
if (elname === "polyline") {
|
||||
|
@ -222,10 +260,18 @@ MD.Panel = function(){
|
|||
if(el_name === "rect") $("#cornerRadiusLabel").show()
|
||||
else $("#cornerRadiusLabel").hide()
|
||||
|
||||
$.each(cur_panel, function(i, item) {
|
||||
var attrVal = elem.getAttribute(item);
|
||||
cur_panel.forEach((item, i) => {
|
||||
var attrVal = elem.getAttribute(item);
|
||||
//update the draginput cursors
|
||||
var name_item = document.getElementById(el_name + '_' + item);
|
||||
// find a textPath to put correct x and y
|
||||
if (el_name === "text") {
|
||||
const textPath = elem.querySelector("textPath");
|
||||
if (textPath) {
|
||||
var bb = elem.getBBox();
|
||||
if (bb) attrVal = bb[item];
|
||||
}
|
||||
}
|
||||
name_item.value = Math.round(attrVal) || 0;
|
||||
if (name_item.getAttribute("data-cursor") === "true") {
|
||||
$.fn.dragInput.updateCursor(name_item );
|
||||
|
@ -233,7 +279,7 @@ MD.Panel = function(){
|
|||
});
|
||||
|
||||
if(el_name === 'text') {
|
||||
var font_family = elem.getAttribute("font-family") || "serif";
|
||||
var font_family = elem.getAttribute("font-family") || "default";
|
||||
var cleanFontFamily = font_family.split(",")[0].replace(/'/g, "");
|
||||
var select = document.getElementById("font_family_dropdown");
|
||||
$('#text_panel').css("display", "inline");
|
||||
|
@ -246,6 +292,9 @@ MD.Panel = function(){
|
|||
$('#font_size').val(elem.getAttribute("font-size"));
|
||||
$('#text').val(elem.textContent);
|
||||
$('#preview_font').text(cleanFontFamily).css('font-family', font_family);
|
||||
const textPath = elem.querySelector("textPath");
|
||||
document.getElementById("text_panel").classList.toggle("text-path", textPath);
|
||||
$("#textPath_offset").val(textPath ? textPath.getAttribute("startOffset") : 0);
|
||||
} // text
|
||||
else if(el_name === 'image') {
|
||||
const url = svgCanvas.getHref(elem)
|
||||
|
@ -289,7 +338,7 @@ MD.Panel = function(){
|
|||
|
||||
if ( (elem && !isNode) || multiselected) {
|
||||
// update the selected elements' layer
|
||||
$('#selLayerNames').removeAttr('disabled').val(currentLayerName);
|
||||
$('#selLayerNames').removeAttr('disabled').val(svgCanvas.getCurrentDrawing().getCurrentLayerName());
|
||||
|
||||
// Enable regular menu options
|
||||
$("#cmenu_canvas").enableContextMenuItems('#delete,#cut,#copy,#move_front,#move_up,#move_down,#move_back');
|
||||
|
|
|
@ -1,5 +1,27 @@
|
|||
MD.Text = function(){
|
||||
|
||||
function placeTextOnPath(){
|
||||
const elems = editor.selected;
|
||||
const needsConversion = elems.find(elem => ["ellipse", "circle", "line", "polyline", "polygon", "rect"].indexOf(elem.tagName) > -1);
|
||||
if (needsConversion) {
|
||||
const path = svgCanvas.convertToPath(needsConversion);
|
||||
const text = elems.find(elem => elem.tagName === "text");
|
||||
svgCanvas.addToSelection([path, text]);
|
||||
}
|
||||
|
||||
const text = svgCanvas.textPath();
|
||||
svgCanvas.clearSelection();
|
||||
svgCanvas.addToSelection([text]);
|
||||
editor.selectedChanged(window, [text]);
|
||||
}
|
||||
|
||||
function releaseTextOnPath(){
|
||||
const text = svgCanvas.releaseTextPath();
|
||||
const selector = svgCanvas.selectorManager.requestSelector(text);
|
||||
selector.resize();
|
||||
editor.selectedChanged(window, [text]);
|
||||
}
|
||||
|
||||
function setBold(){
|
||||
if ($(this).hasClass("disabled")) return;
|
||||
svgCanvas.setBold( !svgCanvas.getBold() );
|
||||
|
@ -16,6 +38,9 @@ MD.Text = function(){
|
|||
svgCanvas.setFontFamily(this.value);
|
||||
});
|
||||
|
||||
$('#tool_text_on_path').click(placeTextOnPath);
|
||||
$('#tool_release_text_on_path').click(releaseTextOnPath);
|
||||
|
||||
$("#tool_bold").on("click", setBold);
|
||||
$("#tool_italic").on("click", setItalic);
|
||||
|
||||
|
@ -43,8 +68,8 @@ MD.Text = function(){
|
|||
document.fonts.onloadingdone = function (fontFaceSetEvent) {
|
||||
const els = svgCanvas.getSelectedElems();
|
||||
els.forEach(el => {
|
||||
var selector = svgCanvas.selectorManager.requestSelector(el);
|
||||
selector.resize();
|
||||
var selector = svgCanvas.selectorManager.requestSelector(el);
|
||||
selector.resize();
|
||||
})
|
||||
};
|
||||
|
||||
|
@ -67,8 +92,15 @@ MD.Text = function(){
|
|||
svgCanvas.setFontSize($("#font_size").val());
|
||||
}
|
||||
|
||||
function setTextPathAttr(a, val){
|
||||
svgCanvas.setTextPathAttr('startOffset', val);
|
||||
var elems = svgCanvas.getSelectedElems();
|
||||
svgCanvas.selectorManager.requestSelector(elems[0]).reset(elems[0]);
|
||||
}
|
||||
|
||||
this.setBold = setBold;
|
||||
this.setItalic = setItalic;
|
||||
this.changeFontSize = changeFontSize;
|
||||
this.setTextPathAttr = setTextPathAttr;
|
||||
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
MD.TextOnPath = function(){
|
||||
console.log("hi")
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
function exportHandler(window, data) {
|
||||
var issues = data.issues;
|
||||
|
||||
if(!$('#export_canvas').length) {
|
||||
$('<canvas>', {id: 'export_canvas'}).hide().appendTo('body');
|
||||
}
|
||||
var c = $('#export_canvas')[0];
|
||||
|
||||
c.width = svgCanvas.contentW;
|
||||
c.height = svgCanvas.contentH;
|
||||
canvg(c, data.svg, {renderCallback: function() {
|
||||
var datauri = c.toDataURL('image/png');
|
||||
if (!datauri) return false;
|
||||
var filename = "Method Draw Image";
|
||||
var type = 'image/png';
|
||||
var file = svgedit.utilities.dataURItoBlob(datauri, type);
|
||||
if (window.navigator.msSaveOrOpenBlob) // IE10+
|
||||
window.navigator.msSaveOrOpenBlob(file, filename);
|
||||
else { // Others
|
||||
var a = document.createElement("a"),
|
||||
url = URL.createObjectURL(file);
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
setTimeout(function() {
|
||||
document.body.removeChild(a);
|
||||
window.URL.revokeObjectURL(url);
|
||||
}, 0);
|
||||
}
|
||||
}});
|
||||
}
|
1453
src/js/fonts.js
1453
src/js/fonts.js
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -7,8 +7,8 @@ editor.modal = {
|
|||
about: new MD.Modal({
|
||||
html: `
|
||||
<h1>About this application</h1>
|
||||
<p>Method Draw is a simple <a href="https://github.com/methodofaction/Method-Draw">open source</a> vector drawing application. Method Draw was forked from <a href="https://github.com/SVG-Edit/svgedit">SVG-Edit</a> several years ago with the goal of improving and modernizing the interface.</p>
|
||||
<p>At this time (2021), the author (<a href="http://method.ac/writing">Mark MacKay</a>) is working on improving stability and improving the codebase, which contains a lot of legacy practices. The goal is to create a vector editor suitable for simple graphic design tasks.</p>
|
||||
<p>Fujikohsan Vector Editor is a vector drawing application by Fuji Kosan Co., Ltd. from Tokyo, Japan. Fujikohsan specializes in uniforms, safety clothes, and promotional goods.</p>
|
||||
<p>Visit our website at <a target="_blank" href="https://fujikohsan.co.jp/">fujikohsan.co.jp</a>
|
||||
`
|
||||
}),
|
||||
source: new MD.Modal({
|
||||
|
|
|
@ -49,7 +49,8 @@ var curConfig = {
|
|||
initFill: {color: 'fff', opacity: 1},
|
||||
initStroke: {width: 1, color: '000', opacity: 1},
|
||||
imgPath: 'images/',
|
||||
baseUnit: 'px'
|
||||
baseUnit: 'px',
|
||||
defaultFont: "Noto Sans JP"
|
||||
};
|
||||
|
||||
// Update config with new one if given
|
||||
|
@ -146,7 +147,7 @@ $.extend(all_properties.text, {
|
|||
fill: "#000000",
|
||||
stroke_width: 0,
|
||||
font_size: 24,
|
||||
font_family: 'sans-serif'
|
||||
font_family: curConfig.defaultFont
|
||||
});
|
||||
|
||||
// Current shape style properties
|
||||
|
@ -569,15 +570,11 @@ getStrokedBBox = this.getStrokedBBox = function(elems) {
|
|||
var angle = svgedit.utilities.getRotationAngle(elem);
|
||||
if ((angle && angle % 90) ||
|
||||
svgedit.math.hasMatrixTransform(svgedit.transformlist.getTransformList(elem))) {
|
||||
// Accurate way to get BBox of rotated element in Firefox:
|
||||
// Put element in group and get its BBox
|
||||
|
||||
var good_bb = false;
|
||||
|
||||
// Get the BBox from the raw path for these elements
|
||||
var elemNames = ['ellipse','path','line','polyline','polygon'];
|
||||
if(elemNames.indexOf(elem.tagName) >= 0) {
|
||||
bb = good_bb = canvas.convertToPath(elem, true);
|
||||
bb = canvas.convertToPath(elem, true);
|
||||
} else if(elem.tagName == 'rect') {
|
||||
// Look for radius
|
||||
var rx = elem.getAttribute('rx');
|
||||
|
@ -586,51 +583,6 @@ getStrokedBBox = this.getStrokedBBox = function(elems) {
|
|||
bb = good_bb = canvas.convertToPath(elem, true);
|
||||
}
|
||||
}
|
||||
|
||||
if(!good_bb) {
|
||||
// Must use clone else FF freaks out
|
||||
var clone = elem.cloneNode(true);
|
||||
var g = document.createElementNS(svgns, "g");
|
||||
var parent = elem.parentNode;
|
||||
parent.appendChild(g);
|
||||
g.appendChild(clone);
|
||||
bb = svgedit.utilities.bboxToObj(g.getBBox());
|
||||
parent.removeChild(g);
|
||||
}
|
||||
|
||||
|
||||
// Old method: Works by giving the rotated BBox,
|
||||
// this is (unfortunately) what Opera and Safari do
|
||||
// natively when getting the BBox of the parent group
|
||||
// var angle = angle * Math.PI / 180.0;
|
||||
// var rminx = Number.MAX_VALUE, rminy = Number.MAX_VALUE,
|
||||
// rmaxx = Number.MIN_VALUE, rmaxy = Number.MIN_VALUE;
|
||||
// var cx = round(bb.x + bb.width/2),
|
||||
// cy = round(bb.y + bb.height/2);
|
||||
// var pts = [ [bb.x - cx, bb.y - cy],
|
||||
// [bb.x + bb.width - cx, bb.y - cy],
|
||||
// [bb.x + bb.width - cx, bb.y + bb.height - cy],
|
||||
// [bb.x - cx, bb.y + bb.height - cy] ];
|
||||
// var j = 4;
|
||||
// while (j--) {
|
||||
// var x = pts[j][0],
|
||||
// y = pts[j][1],
|
||||
// r = Math.sqrt( x*x + y*y );
|
||||
// var theta = Math.atan2(y,x) + angle;
|
||||
// x = round(r * Math.cos(theta) + cx);
|
||||
// y = round(r * Math.sin(theta) + cy);
|
||||
//
|
||||
// // now set the bbox for the shape after it's been rotated
|
||||
// if (x < rminx) rminx = x;
|
||||
// if (y < rminy) rminy = y;
|
||||
// if (x > rmaxx) rmaxx = x;
|
||||
// if (y > rmaxy) rmaxy = y;
|
||||
// }
|
||||
//
|
||||
// bb.x = rminx;
|
||||
// bb.y = rminy;
|
||||
// bb.width = rmaxx - rminx;
|
||||
// bb.height = rmaxy - rminy;
|
||||
}
|
||||
return bb;
|
||||
} catch(e) {
|
||||
|
@ -856,6 +808,7 @@ var getId, getNextId, call;
|
|||
// Parameters:
|
||||
// newDoc - The SVG DOM document
|
||||
this.prepareSvg = function(newDoc) {
|
||||
|
||||
this.sanitizeSvg(newDoc.documentElement);
|
||||
|
||||
// convert paths into absolute commands
|
||||
|
@ -865,6 +818,7 @@ this.prepareSvg = function(newDoc) {
|
|||
path.setAttribute('d', pathActions.convertPath(path));
|
||||
pathActions.fixEnd(path);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Function getRefElem
|
||||
|
@ -1286,8 +1240,18 @@ var updateClipPath = function(attr, tx, ty) {
|
|||
// Undo command object with the resulting change
|
||||
var recalculateDimensions = this.recalculateDimensions = function(selected) {
|
||||
if (selected == null) return null;
|
||||
|
||||
var tlist = getTransformList(selected);
|
||||
|
||||
// apply transformation to path and to text if is textpath
|
||||
const textPath = selected.querySelector("textPath");
|
||||
if (textPath) {
|
||||
return false;
|
||||
const href = textPath.getAttribute("href");
|
||||
const id = href.replace("#", "");
|
||||
const path = svgroot.getElementById(id);
|
||||
//recalculateDimensions(selected, true);
|
||||
if (path) selected = path;
|
||||
}
|
||||
|
||||
// remove any unnecessary transforms
|
||||
if (tlist && tlist.numberOfItems > 0) {
|
||||
|
@ -1313,7 +1277,7 @@ var recalculateDimensions = this.recalculateDimensions = function(selected) {
|
|||
// End here if all it has is a rotation
|
||||
if(tlist.numberOfItems === 1 && getRotationAngle(selected)) return null;
|
||||
}
|
||||
|
||||
|
||||
// if this element had no transforms, we are done
|
||||
if (!tlist || tlist.numberOfItems == 0) {
|
||||
selected.removeAttribute("transform");
|
||||
|
@ -1399,6 +1363,7 @@ var recalculateDimensions = this.recalculateDimensions = function(selected) {
|
|||
case "use":
|
||||
case "text":
|
||||
case "tspan":
|
||||
case "textPath":
|
||||
attrs = ["x", "y"];
|
||||
break;
|
||||
case "polygon":
|
||||
|
@ -2263,7 +2228,7 @@ var getMouseTarget = this.getMouseTarget = function(evt) {
|
|||
if(mouse_target.tagName === 'a' && mouse_target.childNodes.length === 1) {
|
||||
mouse_target = mouse_target.firstChild;
|
||||
}
|
||||
|
||||
|
||||
// real_x/y ignores grid-snap value
|
||||
var real_x = r_start_x = start_x = x;
|
||||
var real_y = r_start_y = start_y = y;
|
||||
|
@ -2339,10 +2304,6 @@ var getMouseTarget = this.getMouseTarget = function(evt) {
|
|||
}
|
||||
r_start_x *= current_zoom;
|
||||
r_start_y *= current_zoom;
|
||||
// console.log('p',[evt.pageX, evt.pageY]);
|
||||
// console.log('c',[evt.clientX, evt.clientY]);
|
||||
// console.log('o',[evt.offsetX, evt.offsetY]);
|
||||
// console.log('s',[start_x, start_y]);
|
||||
|
||||
assignAttributes(rubberBox, {
|
||||
'x': r_start_x,
|
||||
|
@ -3104,7 +3065,7 @@ var getMouseTarget = this.getMouseTarget = function(evt) {
|
|||
case "select":
|
||||
if (selectedElements[0] != null) {
|
||||
// if we only have one selected element
|
||||
if (selectedElements.length == 1) {
|
||||
if (selectedElements.length === 1) {
|
||||
// set our current stroke/fill properties to the element's
|
||||
var selected = selectedElements[0];
|
||||
switch ( selected.tagName ) {
|
||||
|
@ -3556,7 +3517,7 @@ var textActions = canvas.textActions = function() {
|
|||
selblock = document.createElementNS(svgns, "path");
|
||||
assignAttributes(selblock, {
|
||||
'id': "text_selectblock",
|
||||
'fill': "green",
|
||||
'fill': "blue",
|
||||
'opacity': .5,
|
||||
'style': "pointer-events:none"
|
||||
});
|
||||
|
@ -5128,13 +5089,6 @@ this.svgCanvasToString = function() {
|
|||
|
||||
pathActions.clear(true);
|
||||
|
||||
// Keep SVG-Edit comment on top
|
||||
$.each(svgcontent.childNodes, function(i, node) {
|
||||
if(i && node.nodeType === 8 && node.data.indexOf('Created with') >= 0) {
|
||||
svgcontent.insertBefore(node, svgcontent.firstChild);
|
||||
}
|
||||
});
|
||||
|
||||
// Move out of in-group editing mode
|
||||
if(current_group) {
|
||||
leaveContext();
|
||||
|
@ -5162,6 +5116,7 @@ this.svgCanvasToString = function() {
|
|||
$(this).replaceWith(svg);
|
||||
}
|
||||
});
|
||||
|
||||
var output = this.svgToString(svgcontent, 0);
|
||||
|
||||
// Rewrap gsvg
|
||||
|
@ -5171,6 +5126,8 @@ this.svgCanvasToString = function() {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
return output;
|
||||
};
|
||||
|
||||
|
@ -5202,17 +5159,6 @@ this.svgToString = function(elem, indent) {
|
|||
var res = getResolution();
|
||||
|
||||
var vb = "";
|
||||
// TODO: Allow this by dividing all values by current baseVal
|
||||
// Note that this also means we should properly deal with this on import
|
||||
// if(curConfig.baseUnit !== "px") {
|
||||
// var unit = curConfig.baseUnit;
|
||||
// var unit_m = svgedit.units.getTypeMap()[unit];
|
||||
// res.w = svgedit.units.shortFloat(res.w / unit_m)
|
||||
// res.h = svgedit.units.shortFloat(res.h / unit_m)
|
||||
// vb = ' viewBox="' + [0, 0, res.w, res.h].join(' ') + '"';
|
||||
// res.w += unit;
|
||||
// res.h += unit;
|
||||
// }
|
||||
|
||||
if(unit !== "px") {
|
||||
res.w = svgedit.units.convertUnit(res.w, unit) + unit;
|
||||
|
@ -5220,7 +5166,7 @@ this.svgToString = function(elem, indent) {
|
|||
}
|
||||
|
||||
out.push(' width="' + res.w + '" height="' + res.h + '"' + vb + ' xmlns="'+svgns+'"');
|
||||
|
||||
|
||||
var nsuris = {};
|
||||
|
||||
// Check elements for namespaces, add if found
|
||||
|
@ -5401,9 +5347,11 @@ this.save = function() {
|
|||
|
||||
// no need for doctype, see http://jwatt.org/svg/authoring/#doctype-declaration
|
||||
var str = this.svgCanvasToString();
|
||||
if (str.includes(" href=")) str = str.replace(" href=", " xlink:href=");
|
||||
console.log(str)
|
||||
var blob = new Blob([ str ], {type: "image/svg+xml;charset=utf-8"});
|
||||
var dropAutoBOM = true;
|
||||
saveAs(blob, "method-draw-image.svg", dropAutoBOM);
|
||||
saveAs(blob, "FVE-image.svg", dropAutoBOM);
|
||||
};
|
||||
|
||||
// Function: rasterExport
|
||||
|
@ -5780,6 +5728,23 @@ var convertToGroup = this.convertToGroup = function(elem) {
|
|||
}
|
||||
}
|
||||
|
||||
this.styleToAttr = function(doc) {
|
||||
const docEl = doc.documentElement;
|
||||
const styles = docEl.querySelectorAll("style");
|
||||
var parser = new cssjs();
|
||||
styles.forEach(style =>{
|
||||
var parsed = parser.parseCSS(style.textContent);
|
||||
parsed.forEach(ruleset => {
|
||||
const els = docEl.querySelectorAll(ruleset.selector);
|
||||
els.forEach(el => {
|
||||
ruleset.rules.forEach(rule => el.setAttribute(rule.directive, rule.value));
|
||||
})
|
||||
})
|
||||
});
|
||||
styles.forEach(style => {style.parentNode.removeChild(style)});
|
||||
return doc;
|
||||
}
|
||||
|
||||
//
|
||||
// Function: setSvgString
|
||||
// This function sets the current drawing as the input SVG XML.
|
||||
|
@ -5793,6 +5758,7 @@ this.setSvgString = function(xmlString) {
|
|||
try {
|
||||
// convert string into XML document
|
||||
var newDoc = svgedit.utilities.text2xml(xmlString);
|
||||
this.styleToAttr(newDoc);
|
||||
this.prepareSvg(newDoc);
|
||||
|
||||
var batchCmd = new BatchCommand("Change Source");
|
||||
|
@ -7176,6 +7142,25 @@ this.setStrokeAttr = function(attr, val) {
|
|||
}
|
||||
};
|
||||
|
||||
this.setTextPathAttr = function(attr, val) {
|
||||
cur_shape[attr.replace('-','_')] = val;
|
||||
var elems = [];
|
||||
var i = selectedElements.length;
|
||||
while (i--) {
|
||||
var elem = selectedElements[i];
|
||||
if (elem) {
|
||||
if (elem.tagName === "text") {
|
||||
const textPath = elem.querySelector("textPath");
|
||||
if (textPath) elems.push(textPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (elems.length > 0) {
|
||||
changeSelectedAttribute(attr, val, elems);
|
||||
call("changed", selectedElements);
|
||||
}
|
||||
};
|
||||
|
||||
// Function: getStyle
|
||||
// Returns current style options
|
||||
this.getStyle = function() {
|
||||
|
@ -7505,11 +7490,65 @@ this.getText = function() {
|
|||
// Parameters:
|
||||
// val - String with the new text
|
||||
this.setTextContent = function(val) {
|
||||
changeSelectedAttribute("#text", val);
|
||||
const selected = selectedElements[0];
|
||||
const textPath = selected.querySelector("textPath");
|
||||
changeSelectedAttribute("#text", val, textPath ? [textPath] : null);
|
||||
textActions.init(val);
|
||||
textActions.setCursor();
|
||||
};
|
||||
|
||||
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")
|
||||
}
|
||||
if (!text || !path) return false;
|
||||
const textPath = svgdoc.createElementNS(svgns, "textPath");
|
||||
textPath.textContent = text.textContent;
|
||||
text.textContent = "";
|
||||
text.setAttribute("text-anchor", "middle");
|
||||
text.setAttribute("x", 0);
|
||||
text.setAttribute("y", 0);
|
||||
textPath.setAttribute("xlink:href", "#" + path.id);
|
||||
textPath.setAttribute("href", "#" + path.id);
|
||||
const offset = (path.getTotalLength()/2).toFixed(0)
|
||||
textPath.setAttribute("startOffset", offset);
|
||||
text.appendChild(textPath);
|
||||
findDefs().appendChild(path);
|
||||
selectorManager.releaseSelector(path);
|
||||
selectorManager.requestSelector(text).resize();
|
||||
call("changed", [textPath]);
|
||||
return text;
|
||||
}
|
||||
|
||||
this.releaseTextPath = function(){
|
||||
const text = selectedElements.find(element => element.tagName === "text");
|
||||
const textPath = text.querySelector("textPath");
|
||||
const content = textPath.textContent;
|
||||
if (!text) return false;
|
||||
const path = svgCanvas.getTextPath(text);
|
||||
if (!text || !path) return false;
|
||||
text.removeChild(textPath);
|
||||
text.textContent = content;
|
||||
getCurrentDrawing().getCurrentLayer().appendChild(path);
|
||||
const bb = path.getBBox();
|
||||
text.setAttribute("x", bb.x);
|
||||
text.setAttribute("y", bb.y);
|
||||
return text;
|
||||
}
|
||||
|
||||
this.getTextPath = function(elem){
|
||||
const textPath = elem.querySelector("textPath");
|
||||
var path = null;
|
||||
if (textPath) {
|
||||
const href = textPath.getAttribute("href");
|
||||
const id = href.replace("#", "");
|
||||
path = svgroot.getElementById(id);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
// Function: setImageURL
|
||||
// Sets the new image URL for the selected image element. Updates its size if
|
||||
// a new URL is given
|
||||
|
@ -7743,15 +7782,24 @@ this.convertToPath = function(elem, getBBox) {
|
|||
if(elem.tagName == 'circle') {
|
||||
rx = ry = $(elem).attr('r');
|
||||
}
|
||||
|
||||
|
||||
joinSegs([
|
||||
['M',[(cx-rx),(cy)]],
|
||||
['M',[(cx),(cy+ry)]], //
|
||||
['C',[(cx-rx/num),(cy+ry), (cx-rx),(cy+ry/num), (cx-rx),(cy)]],
|
||||
['C',[(cx-rx),(cy-ry/num), (cx-rx/num),(cy-ry), (cx),(cy-ry)]],
|
||||
['C',[(cx+rx/num),(cy-ry), (cx+rx),(cy-ry/num), (cx+rx),(cy)]],
|
||||
['C',[(cx+rx),(cy+ry/num), (cx+rx/num),(cy+ry), (cx),(cy+ry)]],
|
||||
['C',[(cx-rx/num),(cy+ry), (cx-rx),(cy+ry/num), (cx-rx),(cy)]],
|
||||
['Z',[]]
|
||||
]);
|
||||
|
||||
//joinSegs([
|
||||
// ['M',[(cx-rx),(cy)]], //
|
||||
// ['C',[(cx-rx),(cy-ry/num), (cx-rx/num),(cy-ry), (cx),(cy-ry)]],
|
||||
// ['C',[(cx+rx/num),(cy-ry), (cx+rx),(cy-ry/num), (cx+rx),(cy)]],
|
||||
// ['C',[(cx+rx),(cy+ry/num), (cx+rx/num),(cy+ry), (cx),(cy+ry)]],
|
||||
// ['C',[(cx-rx/num),(cy+ry), (cx-rx),(cy+ry/num), (cx-rx),(cy)]],
|
||||
// ['Z',[]]
|
||||
//]);
|
||||
break;
|
||||
case 'path':
|
||||
d = elem.getAttribute('d');
|
||||
|
@ -7857,6 +7905,19 @@ var changeSelectedAttributeNoUndo = this.changeSelectedAttributeNoUndo = functio
|
|||
pathActions.moveNode(attr, newValue);
|
||||
}
|
||||
var elems = elems || selectedElements;
|
||||
|
||||
// get the path instead of text if is textPath
|
||||
//elems = elems.map((elem) => {
|
||||
// if (elem.tagName === 'text') {
|
||||
// const path = svgCanvas.getTextPath(elem);
|
||||
// console.log(path)
|
||||
// if (path) elem = path;
|
||||
// }
|
||||
// return elem;
|
||||
//});
|
||||
|
||||
|
||||
|
||||
var i = elems.length;
|
||||
var no_xy_elems = ['g', 'polyline', 'path'];
|
||||
var good_g_attrs = ['transform', 'opacity', 'filter'];
|
||||
|
@ -7880,7 +7941,7 @@ var changeSelectedAttributeNoUndo = this.changeSelectedAttributeNoUndo = functio
|
|||
var oldval = attr === "#text" ? elem.textContent : elem.getAttribute(attr);
|
||||
if (oldval == null) oldval = "";
|
||||
if (oldval !== String(newValue)) {
|
||||
if (attr == "#text") {
|
||||
if (attr === "#text") {
|
||||
var old_w = svgedit.utilities.getBBox(elem).width;
|
||||
elem.textContent = newValue;
|
||||
|
||||
|
|
|
@ -482,9 +482,11 @@ function groupBBFix(selected) {
|
|||
// elem - Optional DOM element to get the BBox for
|
||||
svgedit.utilities.getBBox = function(elem) {
|
||||
var selected = elem || editorContext_.getSelectedElements()[0];
|
||||
if (selected.nodeName === "textPath") selected = elem.parentNode;
|
||||
if (elem.nodeType != 1) return null;
|
||||
var ret = null;
|
||||
var elname = selected.nodeName;
|
||||
|
||||
|
||||
switch ( elname ) {
|
||||
case 'text':
|
||||
|
|
Loading…
Reference in New Issue