Integrate symbols/ into main repo
- Added symbols/ folder (previously separate repo) - Removed symbols/ from .gitignore - Updated CLAUDE.md documentation - Deleted separate Symbols repo on Gitea 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
321
symbols/js/text-generator/export.js
Normal file
321
symbols/js/text-generator/export.js
Normal file
@@ -0,0 +1,321 @@
|
||||
/**
|
||||
* Export-Funktionen fuer Text-Symbole
|
||||
*/
|
||||
|
||||
var TextExport = {
|
||||
|
||||
// SVG zu Canvas rendern
|
||||
svgToCanvas: function(svgString, scale) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var img = new Image();
|
||||
var canvas = document.createElement('canvas');
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
var parser = new DOMParser();
|
||||
var svgDoc = parser.parseFromString(svgString, 'image/svg+xml');
|
||||
var svgEl = svgDoc.documentElement;
|
||||
|
||||
var width = parseFloat(svgEl.getAttribute('width')) || 200;
|
||||
var height = parseFloat(svgEl.getAttribute('height')) || 100;
|
||||
|
||||
canvas.width = width * scale;
|
||||
canvas.height = height * scale;
|
||||
|
||||
var blob = new Blob([svgString], { type: 'image/svg+xml' });
|
||||
var url = URL.createObjectURL(blob);
|
||||
|
||||
img.onload = function() {
|
||||
ctx.scale(scale, scale);
|
||||
ctx.drawImage(img, 0, 0);
|
||||
URL.revokeObjectURL(url);
|
||||
resolve(canvas);
|
||||
};
|
||||
|
||||
img.onerror = function(e) {
|
||||
URL.revokeObjectURL(url);
|
||||
reject(e);
|
||||
};
|
||||
|
||||
img.src = url;
|
||||
});
|
||||
},
|
||||
|
||||
// In Zwischenablage kopieren (als PNG)
|
||||
copyAsImage: function(svgString, scale) {
|
||||
var self = this;
|
||||
scale = scale || 3;
|
||||
|
||||
return this.svgToCanvas(svgString, scale).then(function(canvas) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
canvas.toBlob(function(blob) {
|
||||
if (!blob) {
|
||||
reject(new Error('Canvas toBlob failed'));
|
||||
return;
|
||||
}
|
||||
navigator.clipboard.write([
|
||||
new ClipboardItem({ 'image/png': blob })
|
||||
]).then(resolve).catch(reject);
|
||||
}, 'image/png');
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// SVG in Zwischenablage
|
||||
copySvg: function(svgString) {
|
||||
return navigator.clipboard.writeText(svgString);
|
||||
},
|
||||
|
||||
// SVG herunterladen
|
||||
downloadSvg: function(svgString, filename) {
|
||||
var blob = new Blob([svgString], { type: 'image/svg+xml' });
|
||||
var url = URL.createObjectURL(blob);
|
||||
var a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = filename || 'symbol.svg';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
URL.revokeObjectURL(url);
|
||||
},
|
||||
|
||||
// PNG herunterladen
|
||||
downloadPng: function(svgString, filename, scale) {
|
||||
scale = scale || 3;
|
||||
|
||||
return this.svgToCanvas(svgString, scale).then(function(canvas) {
|
||||
var url = canvas.toDataURL('image/png');
|
||||
var a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = filename || 'symbol.png';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
});
|
||||
},
|
||||
|
||||
// JPG herunterladen
|
||||
downloadJpg: function(svgString, filename, scale, bgColor) {
|
||||
scale = scale || 3;
|
||||
bgColor = bgColor || '#ffffff';
|
||||
|
||||
return this.svgToCanvas(svgString, scale).then(function(canvas) {
|
||||
// Neues Canvas mit Hintergrund
|
||||
var bgCanvas = document.createElement('canvas');
|
||||
bgCanvas.width = canvas.width;
|
||||
bgCanvas.height = canvas.height;
|
||||
var ctx = bgCanvas.getContext('2d');
|
||||
ctx.fillStyle = bgColor;
|
||||
ctx.fillRect(0, 0, bgCanvas.width, bgCanvas.height);
|
||||
ctx.drawImage(canvas, 0, 0);
|
||||
|
||||
var url = bgCanvas.toDataURL('image/jpeg', 0.95);
|
||||
var a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = filename || 'symbol.jpg';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
});
|
||||
},
|
||||
|
||||
// DXF generieren (vereinfacht - nur Linien)
|
||||
svgToDxf: function(svgString) {
|
||||
var parser = new DOMParser();
|
||||
var svgDoc = parser.parseFromString(svgString, 'image/svg+xml');
|
||||
var svgEl = svgDoc.documentElement;
|
||||
|
||||
var width = parseFloat(svgEl.getAttribute('width')) || 200;
|
||||
var height = parseFloat(svgEl.getAttribute('height')) || 100;
|
||||
|
||||
var dxf = '0\nSECTION\n2\nENTITIES\n';
|
||||
|
||||
// Rechtecke
|
||||
var rects = svgEl.querySelectorAll('rect');
|
||||
rects.forEach(function(rect) {
|
||||
var x = parseFloat(rect.getAttribute('x')) || 0;
|
||||
var y = parseFloat(rect.getAttribute('y')) || 0;
|
||||
var w = parseFloat(rect.getAttribute('width')) || 0;
|
||||
var h = parseFloat(rect.getAttribute('height')) || 0;
|
||||
var fy = height - y;
|
||||
|
||||
dxf += '0\nLINE\n8\n0\n';
|
||||
dxf += '10\n' + x + '\n20\n' + fy + '\n30\n0\n';
|
||||
dxf += '11\n' + (x + w) + '\n21\n' + fy + '\n31\n0\n';
|
||||
|
||||
dxf += '0\nLINE\n8\n0\n';
|
||||
dxf += '10\n' + (x + w) + '\n20\n' + fy + '\n30\n0\n';
|
||||
dxf += '11\n' + (x + w) + '\n21\n' + (fy - h) + '\n31\n0\n';
|
||||
|
||||
dxf += '0\nLINE\n8\n0\n';
|
||||
dxf += '10\n' + (x + w) + '\n20\n' + (fy - h) + '\n30\n0\n';
|
||||
dxf += '11\n' + x + '\n21\n' + (fy - h) + '\n31\n0\n';
|
||||
|
||||
dxf += '0\nLINE\n8\n0\n';
|
||||
dxf += '10\n' + x + '\n20\n' + (fy - h) + '\n30\n0\n';
|
||||
dxf += '11\n' + x + '\n21\n' + fy + '\n31\n0\n';
|
||||
});
|
||||
|
||||
// Pfade (vereinfacht)
|
||||
var paths = svgEl.querySelectorAll('path');
|
||||
paths.forEach(function(path) {
|
||||
var d = path.getAttribute('d');
|
||||
if (!d) return;
|
||||
|
||||
var points = [];
|
||||
var parts = d.match(/[ML]\s*[\d.-]+\s+[\d.-]+/g);
|
||||
if (parts) {
|
||||
parts.forEach(function(part) {
|
||||
var nums = part.match(/[\d.-]+/g);
|
||||
if (nums && nums.length >= 2) {
|
||||
points.push({ x: parseFloat(nums[0]), y: parseFloat(nums[1]) });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (var i = 0; i < points.length - 1; i++) {
|
||||
dxf += '0\nLINE\n8\n0\n';
|
||||
dxf += '10\n' + points[i].x + '\n20\n' + (height - points[i].y) + '\n30\n0\n';
|
||||
dxf += '11\n' + points[i + 1].x + '\n21\n' + (height - points[i + 1].y) + '\n31\n0\n';
|
||||
}
|
||||
});
|
||||
|
||||
// Text (als Hinweis)
|
||||
var texts = svgEl.querySelectorAll('text');
|
||||
texts.forEach(function(text) {
|
||||
var x = parseFloat(text.getAttribute('x')) || 0;
|
||||
var y = parseFloat(text.getAttribute('y')) || 0;
|
||||
var content = text.textContent || '';
|
||||
|
||||
dxf += '0\nTEXT\n8\n0\n';
|
||||
dxf += '10\n' + x + '\n20\n' + (height - y) + '\n30\n0\n';
|
||||
dxf += '40\n10\n1\n' + content + '\n';
|
||||
});
|
||||
|
||||
dxf += '0\nENDSEC\n0\nEOF\n';
|
||||
return dxf;
|
||||
},
|
||||
|
||||
// DXF herunterladen
|
||||
downloadDxf: function(svgString, filename) {
|
||||
var dxf = this.svgToDxf(svgString);
|
||||
var blob = new Blob([dxf], { type: 'application/dxf' });
|
||||
var url = URL.createObjectURL(blob);
|
||||
var a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = filename || 'symbol.dxf';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
URL.revokeObjectURL(url);
|
||||
},
|
||||
|
||||
// Feedback anzeigen
|
||||
showFeedback: function(message, isError) {
|
||||
var existing = document.querySelector('.export-feedback');
|
||||
if (existing) existing.remove();
|
||||
|
||||
var feedback = document.createElement('div');
|
||||
feedback.className = 'export-feedback';
|
||||
feedback.style.cssText = 'position: fixed; bottom: 20px; right: 20px; padding: 12px 20px; border-radius: 8px; font-size: 14px; z-index: 10000; animation: fadeIn 0.3s;';
|
||||
feedback.style.background = isError ? '#ef4444' : '#10b981';
|
||||
feedback.style.color = 'white';
|
||||
feedback.textContent = message;
|
||||
document.body.appendChild(feedback);
|
||||
|
||||
setTimeout(function() {
|
||||
feedback.style.opacity = '0';
|
||||
feedback.style.transition = 'opacity 0.3s';
|
||||
setTimeout(function() { feedback.remove(); }, 300);
|
||||
}, 2000);
|
||||
}
|
||||
};
|
||||
|
||||
window.TextExport = TextExport;
|
||||
|
||||
// Globale Export-Funktionen fuer onclick-Handler
|
||||
window.copyTextAsImage = function() {
|
||||
var svg = window.SvgGenerator.generate(window.TextGenState.current);
|
||||
window.TextExport.copyAsImage(svg).then(function() {
|
||||
window.TextExport.showFeedback('Als PNG kopiert!');
|
||||
}).catch(function(e) {
|
||||
window.TextExport.showFeedback('Fehler: ' + e.message, true);
|
||||
});
|
||||
};
|
||||
|
||||
window.copyTextSVG = function() {
|
||||
var svg = window.SvgGenerator.generate(window.TextGenState.current);
|
||||
window.TextExport.copySvg(svg).then(function() {
|
||||
window.TextExport.showFeedback('SVG kopiert!');
|
||||
});
|
||||
};
|
||||
|
||||
window.downloadTextPNG = function() {
|
||||
var svg = window.SvgGenerator.generate(window.TextGenState.current);
|
||||
window.TextExport.downloadPng(svg, 'text-symbol.png');
|
||||
};
|
||||
|
||||
window.downloadTextJPG = function() {
|
||||
var svg = window.SvgGenerator.generate(window.TextGenState.current);
|
||||
window.TextExport.downloadJpg(svg, 'text-symbol.jpg');
|
||||
};
|
||||
|
||||
window.downloadTextSVG = function() {
|
||||
var svg = window.SvgGenerator.generate(window.TextGenState.current);
|
||||
window.TextExport.downloadSvg(svg, 'text-symbol.svg');
|
||||
};
|
||||
|
||||
window.downloadTextDXF = function() {
|
||||
var svg = window.SvgGenerator.generate(window.TextGenState.current);
|
||||
window.TextExport.downloadDxf(svg, 'text-symbol.dxf');
|
||||
};
|
||||
|
||||
window.resetToDefaults = function() {
|
||||
window.UiBindings.resetToDefaults();
|
||||
};
|
||||
|
||||
// Standalone-Pfeil Funktionen
|
||||
window.copyStandaloneArrow = function() {
|
||||
var svg = window.SvgGenerator.generateArrowOnly(window.TextGenState.current);
|
||||
if (svg) {
|
||||
window.TextExport.copyAsImage(svg).then(function() {
|
||||
window.TextExport.showFeedback('Pfeil als PNG kopiert!');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
window.copyStandaloneArrowSVG = function() {
|
||||
var svg = window.SvgGenerator.generateArrowOnly(window.TextGenState.current);
|
||||
if (svg) {
|
||||
window.TextExport.copySvg(svg).then(function() {
|
||||
window.TextExport.showFeedback('Pfeil-SVG kopiert!');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
window.downloadStandaloneArrowSVG = function() {
|
||||
var svg = window.SvgGenerator.generateArrowOnly(window.TextGenState.current);
|
||||
if (svg) {
|
||||
window.TextExport.downloadSvg(svg, 'pfeil.svg');
|
||||
}
|
||||
};
|
||||
|
||||
window.downloadStandaloneArrowPNG = function() {
|
||||
var svg = window.SvgGenerator.generateArrowOnly(window.TextGenState.current);
|
||||
if (svg) {
|
||||
window.TextExport.downloadPng(svg, 'pfeil.png');
|
||||
}
|
||||
};
|
||||
|
||||
window.downloadStandaloneArrowJPG = function() {
|
||||
var svg = window.SvgGenerator.generateArrowOnly(window.TextGenState.current);
|
||||
if (svg) {
|
||||
window.TextExport.downloadJpg(svg, 'pfeil.jpg');
|
||||
}
|
||||
};
|
||||
|
||||
window.downloadStandaloneArrowDXF = function() {
|
||||
var svg = window.SvgGenerator.generateArrowOnly(window.TextGenState.current);
|
||||
if (svg) {
|
||||
window.TextExport.downloadDxf(svg, 'pfeil.dxf');
|
||||
}
|
||||
};
|
||||
95
symbols/js/text-generator/state.js
Normal file
95
symbols/js/text-generator/state.js
Normal file
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Text-Generator State Management
|
||||
* Zentrale Zustandsverwaltung für alle Text-Symbol-Einstellungen
|
||||
*/
|
||||
|
||||
const TextGenState = {
|
||||
// Aktuelle Werte
|
||||
current: {
|
||||
text: 'Text',
|
||||
fontSize: 14,
|
||||
textColor: '#000000',
|
||||
frameColor: '#000000',
|
||||
shape: 'rect',
|
||||
frameScale: 120,
|
||||
paddingTop: 10,
|
||||
paddingRight: 10,
|
||||
paddingBottom: 10,
|
||||
paddingLeft: 10,
|
||||
lineStyle: 'solid',
|
||||
lineWeight: 2,
|
||||
arrow: 'none',
|
||||
arrowLength: 40,
|
||||
arrowAngle: 0,
|
||||
arrowBend: 50,
|
||||
arrowSize: 10,
|
||||
arrowTipLength: 15
|
||||
},
|
||||
|
||||
// Standardwerte für Reset
|
||||
defaults: {
|
||||
text: 'Text',
|
||||
fontSize: 14,
|
||||
textColor: '#000000',
|
||||
frameColor: '#000000',
|
||||
shape: 'rect',
|
||||
frameScale: 120,
|
||||
paddingTop: 10,
|
||||
paddingRight: 10,
|
||||
paddingBottom: 10,
|
||||
paddingLeft: 10,
|
||||
lineStyle: 'solid',
|
||||
lineWeight: 2,
|
||||
arrow: 'none',
|
||||
arrowLength: 40,
|
||||
arrowAngle: 0,
|
||||
arrowBend: 50,
|
||||
arrowSize: 10,
|
||||
arrowTipLength: 15
|
||||
},
|
||||
|
||||
// State aktualisieren
|
||||
set(key, value) {
|
||||
if (key in this.current) {
|
||||
this.current[key] = value;
|
||||
this.onChange(key, value);
|
||||
}
|
||||
},
|
||||
|
||||
// Mehrere Werte setzen
|
||||
setMultiple(updates) {
|
||||
Object.entries(updates).forEach(([key, value]) => {
|
||||
if (key in this.current) {
|
||||
this.current[key] = value;
|
||||
}
|
||||
});
|
||||
this.onChange('multiple', updates);
|
||||
},
|
||||
|
||||
// Auf Defaults zurücksetzen
|
||||
reset() {
|
||||
this.current = { ...this.defaults };
|
||||
this.onChange('reset', this.current);
|
||||
},
|
||||
|
||||
// Getter
|
||||
get(key) {
|
||||
return this.current[key];
|
||||
},
|
||||
|
||||
// Alle Werte
|
||||
getAll() {
|
||||
return { ...this.current };
|
||||
},
|
||||
|
||||
// Change-Callback (wird von außen gesetzt)
|
||||
onChange: function(key, value) {
|
||||
// Wird von ui-bindings überschrieben
|
||||
}
|
||||
};
|
||||
|
||||
// Export für ES6 Module und globalen Zugriff
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = TextGenState;
|
||||
}
|
||||
window.TextGenState = TextGenState;
|
||||
371
symbols/js/text-generator/svg-generator.js
Normal file
371
symbols/js/text-generator/svg-generator.js
Normal file
@@ -0,0 +1,371 @@
|
||||
/**
|
||||
* SVG Generator mit SVG.js
|
||||
* Erzeugt Text-Symbole mit Rahmen und Pfeilen
|
||||
*/
|
||||
|
||||
var SvgGenerator = {
|
||||
|
||||
getDashArray: function(style, weight) {
|
||||
switch(style) {
|
||||
case 'dashed': return (weight * 4) + ',' + (weight * 2);
|
||||
case 'dotted': return weight + ',' + (weight * 1.5);
|
||||
default: return null;
|
||||
}
|
||||
},
|
||||
|
||||
measureText: function(text, fontSize) {
|
||||
var lines = text.split('\n');
|
||||
var charWidth = fontSize * 0.6;
|
||||
var lineHeight = fontSize * 1.3;
|
||||
|
||||
var maxLength = 0;
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
if (lines[i].length > maxLength) maxLength = lines[i].length;
|
||||
}
|
||||
if (maxLength === 0) maxLength = 4;
|
||||
|
||||
return {
|
||||
lines: lines,
|
||||
width: maxLength * charWidth,
|
||||
height: lines.length * lineHeight,
|
||||
lineHeight: lineHeight,
|
||||
charWidth: charWidth
|
||||
};
|
||||
},
|
||||
|
||||
createShape: function(draw, shape, x, y, width, height, style) {
|
||||
var shapeEl;
|
||||
var halfW = width / 2;
|
||||
var halfH = height / 2;
|
||||
var cx = x + halfW;
|
||||
var cy = y + halfH;
|
||||
|
||||
switch(shape) {
|
||||
case 'rect':
|
||||
shapeEl = draw.rect(width, height).move(x, y).radius(4);
|
||||
break;
|
||||
case 'rounded':
|
||||
shapeEl = draw.rect(width, height).move(x, y).radius(Math.min(halfW, halfH) * 0.5);
|
||||
break;
|
||||
case 'oval':
|
||||
shapeEl = draw.ellipse(width, height).center(cx, cy);
|
||||
break;
|
||||
case 'diamond':
|
||||
shapeEl = draw.polygon([
|
||||
[cx, y],
|
||||
[x + width, cy],
|
||||
[cx, y + height],
|
||||
[x, cy]
|
||||
]);
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
if (shapeEl) {
|
||||
shapeEl.fill('none').stroke({ color: style.color, width: style.weight });
|
||||
if (style.dashArray) {
|
||||
shapeEl.attr('stroke-dasharray', style.dashArray);
|
||||
}
|
||||
}
|
||||
return shapeEl;
|
||||
},
|
||||
|
||||
calculateArrowHead: function(endX, endY, prevX, prevY, size, tipLength) {
|
||||
// Berechne den Winkel der Pfeilrichtung
|
||||
var angle = Math.atan2(endY - prevY, endX - prevX);
|
||||
|
||||
// Die zwei hinteren Punkte der Pfeilspitze:
|
||||
// - tipLength zurueck in Pfeilrichtung
|
||||
// - size/2 seitlich (links und rechts)
|
||||
var baseX = endX - tipLength * Math.cos(angle);
|
||||
var baseY = endY - tipLength * Math.sin(angle);
|
||||
|
||||
// Senkrecht zur Pfeilrichtung (90 Grad = PI/2)
|
||||
var perpAngle = angle + Math.PI / 2;
|
||||
var halfWidth = size / 2;
|
||||
|
||||
return [
|
||||
[endX, endY], // Spitze
|
||||
[baseX + halfWidth * Math.cos(perpAngle), baseY + halfWidth * Math.sin(perpAngle)], // Links
|
||||
[baseX - halfWidth * Math.cos(perpAngle), baseY - halfWidth * Math.sin(perpAngle)] // Rechts
|
||||
];
|
||||
},
|
||||
|
||||
createArrow: function(draw, direction, frameRect, options) {
|
||||
var length = options.length;
|
||||
var angle = options.angle;
|
||||
var bendPos = options.bendPos;
|
||||
var color = options.color;
|
||||
var weight = options.weight;
|
||||
var dashArray = options.dashArray;
|
||||
var arrowSize = options.arrowSize;
|
||||
var tipLength = options.tipLength;
|
||||
|
||||
var angleRad = angle * Math.PI / 180;
|
||||
var bend = bendPos / 100;
|
||||
|
||||
var startX, startY, midX, midY, endX, endY;
|
||||
var fx = frameRect.x;
|
||||
var fy = frameRect.y;
|
||||
var fw = frameRect.width;
|
||||
var fh = frameRect.height;
|
||||
|
||||
// Fuer Standalone-Pfeile (width=0, height=0) ist fx,fy der Startpunkt
|
||||
var isStandalone = (fw === 0 && fh === 0);
|
||||
var cx = isStandalone ? fx : fx + fw / 2;
|
||||
var cy = isStandalone ? fy : fy + fh / 2;
|
||||
|
||||
switch(direction) {
|
||||
case 'top':
|
||||
startX = cx;
|
||||
startY = isStandalone ? fy : fy;
|
||||
midX = startX; midY = startY - length * bend;
|
||||
endX = midX + Math.sin(angleRad) * (length * (1 - bend));
|
||||
endY = midY - Math.cos(angleRad) * (length * (1 - bend));
|
||||
break;
|
||||
case 'bottom':
|
||||
startX = cx;
|
||||
startY = isStandalone ? fy : fy + fh;
|
||||
midX = startX; midY = startY + length * bend;
|
||||
endX = midX + Math.sin(angleRad) * (length * (1 - bend));
|
||||
endY = midY + Math.cos(angleRad) * (length * (1 - bend));
|
||||
break;
|
||||
case 'left':
|
||||
startX = isStandalone ? fx : fx;
|
||||
startY = cy;
|
||||
midX = startX - length * bend; midY = startY;
|
||||
endX = midX - Math.cos(angleRad) * (length * (1 - bend));
|
||||
endY = midY + Math.sin(angleRad) * (length * (1 - bend));
|
||||
break;
|
||||
case 'right':
|
||||
startX = fx + fw; startY = cy;
|
||||
midX = startX + length * bend; midY = startY;
|
||||
endX = midX + Math.cos(angleRad) * (length * (1 - bend));
|
||||
endY = midY + Math.sin(angleRad) * (length * (1 - bend));
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
var points = (angle !== 0 && bend > 0 && bend < 1)
|
||||
? [[startX, startY], [midX, midY], [endX, endY]]
|
||||
: [[startX, startY], [endX, endY]];
|
||||
|
||||
var pathData = '';
|
||||
for (var i = 0; i < points.length; i++) {
|
||||
pathData += (i === 0 ? 'M' : 'L') + points[i][0] + ' ' + points[i][1] + ' ';
|
||||
}
|
||||
|
||||
var line = draw.path(pathData).fill('none').stroke({ color: color, width: weight });
|
||||
if (dashArray) line.attr('stroke-dasharray', dashArray);
|
||||
|
||||
var lastPoint = points[points.length - 1];
|
||||
var prevPoint = points[points.length - 2];
|
||||
var headPoints = this.calculateArrowHead(lastPoint[0], lastPoint[1], prevPoint[0], prevPoint[1], arrowSize, tipLength);
|
||||
var arrowHead = draw.polygon(headPoints).fill(color).stroke({ color: color, width: 1 });
|
||||
|
||||
return draw.group().add(line).add(arrowHead);
|
||||
},
|
||||
|
||||
createText: function(draw, text, x, y, options) {
|
||||
var fontSize = options.fontSize;
|
||||
var color = options.color;
|
||||
var lines = options.lines;
|
||||
var lineHeight = options.lineHeight;
|
||||
var group = draw.group();
|
||||
|
||||
var totalHeight = lines.length * lineHeight;
|
||||
var startY = y - (totalHeight / 2) + (fontSize * 0.8);
|
||||
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
var lineY = startY + (i * lineHeight);
|
||||
var lineText = lines[i] || ' ';
|
||||
// Verwende plain SVG text element fuer bessere Kontrolle
|
||||
var textEl = draw.plain(lineText)
|
||||
.font({
|
||||
family: 'Arial, sans-serif',
|
||||
size: fontSize,
|
||||
anchor: 'middle'
|
||||
})
|
||||
.fill(color)
|
||||
.attr('x', x)
|
||||
.attr('y', lineY)
|
||||
.attr('text-anchor', 'middle');
|
||||
group.add(textEl);
|
||||
}
|
||||
return group;
|
||||
},
|
||||
|
||||
generate: function(state) {
|
||||
var s = state;
|
||||
var textMetrics = this.measureText(s.text || 'Text', s.fontSize);
|
||||
|
||||
var frameScale = s.frameScale / 100;
|
||||
var frameWidth = (textMetrics.width + s.paddingLeft + s.paddingRight) * frameScale;
|
||||
var frameHeight = (textMetrics.height + s.paddingTop + s.paddingBottom) * frameScale;
|
||||
|
||||
var minWidth = Math.max(frameWidth, 40);
|
||||
var minHeight = Math.max(frameHeight, 30);
|
||||
|
||||
// Pfeil-Raum berechnen inkl. Winkel-Abweichung
|
||||
var arrowSpace = 0;
|
||||
var arrowSideSpace = 0;
|
||||
if (s.arrow !== 'none') {
|
||||
var angleRad = Math.abs(s.arrowAngle) * Math.PI / 180;
|
||||
var bendFactor = s.arrowBend / 100;
|
||||
var effectiveLength = s.arrowLength * (1 - bendFactor);
|
||||
|
||||
// Hauptrichtung: volle Laenge + Spitze + Puffer
|
||||
arrowSpace = s.arrowLength + s.arrowTipLength + 20;
|
||||
|
||||
// Seitliche Abweichung durch Winkel
|
||||
arrowSideSpace = Math.abs(Math.sin(angleRad) * effectiveLength) + s.arrowSize + 10;
|
||||
}
|
||||
|
||||
var svgWidth = minWidth;
|
||||
var svgHeight = minHeight;
|
||||
var offsetX = 0, offsetY = 0;
|
||||
|
||||
switch(s.arrow) {
|
||||
case 'left':
|
||||
svgWidth += arrowSpace;
|
||||
svgHeight = Math.max(svgHeight, minHeight + arrowSideSpace * 2);
|
||||
offsetX = arrowSpace;
|
||||
offsetY = (svgHeight - minHeight) / 2;
|
||||
break;
|
||||
case 'right':
|
||||
svgWidth += arrowSpace;
|
||||
svgHeight = Math.max(svgHeight, minHeight + arrowSideSpace * 2);
|
||||
offsetY = (svgHeight - minHeight) / 2;
|
||||
break;
|
||||
case 'top':
|
||||
svgHeight += arrowSpace;
|
||||
svgWidth = Math.max(svgWidth, minWidth + arrowSideSpace * 2);
|
||||
offsetY = arrowSpace;
|
||||
offsetX = (svgWidth - minWidth) / 2;
|
||||
break;
|
||||
case 'bottom':
|
||||
svgHeight += arrowSpace;
|
||||
svgWidth = Math.max(svgWidth, minWidth + arrowSideSpace * 2);
|
||||
offsetX = (svgWidth - minWidth) / 2;
|
||||
break;
|
||||
}
|
||||
|
||||
var draw = SVG().size(svgWidth, svgHeight);
|
||||
|
||||
var frameX = offsetX;
|
||||
var frameY = offsetY;
|
||||
var frameCx = frameX + minWidth / 2;
|
||||
var frameCy = frameY + minHeight / 2;
|
||||
|
||||
// Text-Verschiebung basierend auf asymmetrischem Padding
|
||||
// Wenn links mehr Padding ist, verschiebt sich der Text nach rechts
|
||||
var textOffsetX = (s.paddingLeft - s.paddingRight) / 2;
|
||||
var textOffsetY = (s.paddingTop - s.paddingBottom) / 2;
|
||||
var textCx = frameCx + textOffsetX;
|
||||
var textCy = frameCy + textOffsetY;
|
||||
|
||||
var dashArray = this.getDashArray(s.lineStyle, s.lineWeight);
|
||||
var strokeStyle = { color: s.frameColor, weight: s.lineWeight, dashArray: dashArray };
|
||||
|
||||
if (s.shape !== 'none') {
|
||||
this.createShape(draw, s.shape, frameX, frameY, minWidth, minHeight, strokeStyle);
|
||||
}
|
||||
|
||||
if (s.arrow !== 'none') {
|
||||
this.createArrow(draw, s.arrow, {
|
||||
x: frameX, y: frameY, width: minWidth, height: minHeight
|
||||
}, {
|
||||
length: s.arrowLength, angle: s.arrowAngle, bendPos: s.arrowBend,
|
||||
color: s.frameColor, weight: s.lineWeight, dashArray: dashArray,
|
||||
arrowSize: s.arrowSize, tipLength: s.arrowTipLength
|
||||
});
|
||||
}
|
||||
|
||||
this.createText(draw, s.text, textCx, textCy, {
|
||||
fontSize: s.fontSize, color: s.textColor,
|
||||
lines: textMetrics.lines, lineHeight: textMetrics.lineHeight
|
||||
});
|
||||
|
||||
return draw.svg();
|
||||
},
|
||||
|
||||
generateArrowOnly: function(state) {
|
||||
var s = state;
|
||||
if (s.arrow === 'none') return null;
|
||||
|
||||
var length = s.arrowLength;
|
||||
var tipLength = s.arrowTipLength;
|
||||
var arrowSize = s.arrowSize;
|
||||
var padding = 40;
|
||||
|
||||
// Berechne die tatsaechlichen Endpunkte des Pfeils
|
||||
var angleRad = s.arrowAngle * Math.PI / 180;
|
||||
var bendFactor = s.arrowBend / 100;
|
||||
var straightPart = length * bendFactor;
|
||||
var angledPart = length * (1 - bendFactor);
|
||||
|
||||
// Seitliche Ausdehnung durch den Winkel (mit Vorzeichen)
|
||||
var sideExtent = Math.sin(angleRad) * angledPart;
|
||||
var mainExtent = Math.cos(angleRad) * angledPart;
|
||||
|
||||
// Mindestgroesse fuer die seitliche Ausdehnung
|
||||
var minSideSpace = Math.abs(sideExtent) + arrowSize + tipLength + padding;
|
||||
|
||||
var width, height, startX, startY;
|
||||
|
||||
switch(s.arrow) {
|
||||
case 'right':
|
||||
width = straightPart + mainExtent + tipLength + padding * 2;
|
||||
height = Math.max(arrowSize * 4, minSideSpace * 2);
|
||||
startX = padding;
|
||||
// Bei positivem Winkel geht der Pfeil nach unten, also Start weiter oben
|
||||
startY = height / 2 - sideExtent / 2;
|
||||
break;
|
||||
case 'left':
|
||||
width = straightPart + mainExtent + tipLength + padding * 2;
|
||||
height = Math.max(arrowSize * 4, minSideSpace * 2);
|
||||
startX = width - padding;
|
||||
startY = height / 2 + sideExtent / 2;
|
||||
break;
|
||||
case 'bottom':
|
||||
width = Math.max(arrowSize * 4, minSideSpace * 2);
|
||||
height = straightPart + mainExtent + tipLength + padding * 2;
|
||||
startX = width / 2 - sideExtent / 2;
|
||||
startY = padding;
|
||||
break;
|
||||
case 'top':
|
||||
width = Math.max(arrowSize * 4, minSideSpace * 2);
|
||||
height = straightPart + mainExtent + tipLength + padding * 2;
|
||||
startX = width / 2 + sideExtent / 2;
|
||||
startY = height - padding;
|
||||
break;
|
||||
}
|
||||
|
||||
// Stelle sicher, dass alle Werte positiv sind
|
||||
width = Math.max(width, 80);
|
||||
height = Math.max(height, 60);
|
||||
|
||||
var draw = SVG().size(width, height);
|
||||
|
||||
// Simuliere einen Rahmen-Punkt als Startpunkt
|
||||
var frameRect = {
|
||||
x: startX,
|
||||
y: startY,
|
||||
width: 0,
|
||||
height: 0
|
||||
};
|
||||
|
||||
this.createArrow(draw, s.arrow, frameRect, {
|
||||
length: s.arrowLength, angle: s.arrowAngle, bendPos: s.arrowBend,
|
||||
color: s.frameColor, weight: s.lineWeight,
|
||||
dashArray: this.getDashArray(s.lineStyle, s.lineWeight),
|
||||
arrowSize: s.arrowSize, tipLength: s.arrowTipLength
|
||||
});
|
||||
|
||||
return draw.svg();
|
||||
}
|
||||
};
|
||||
|
||||
window.SvgGenerator = SvgGenerator;
|
||||
344
symbols/js/text-generator/ui-bindings.js
Normal file
344
symbols/js/text-generator/ui-bindings.js
Normal file
@@ -0,0 +1,344 @@
|
||||
/**
|
||||
* UI Bindings - Verbindet HTML-Elemente mit dem State
|
||||
*/
|
||||
|
||||
var UiBindings = {
|
||||
elements: {},
|
||||
|
||||
init: function() {
|
||||
this.cacheElements();
|
||||
this.bindEvents();
|
||||
this.syncFromState();
|
||||
this.updateVisibility();
|
||||
this.updatePreview();
|
||||
this.updateStandaloneArrowPreview();
|
||||
},
|
||||
|
||||
cacheElements: function() {
|
||||
var e = this.elements;
|
||||
|
||||
// Text & Farben
|
||||
e.textInput = document.getElementById('textInput');
|
||||
e.fontSizeInput = document.getElementById('fontSize');
|
||||
e.fontSizeValue = document.getElementById('fontSizeValue');
|
||||
e.textColorInput = document.getElementById('textColor');
|
||||
e.frameColorInput = document.getElementById('frameColor');
|
||||
|
||||
// Rahmen
|
||||
e.frameScaleInput = document.getElementById('frameScale');
|
||||
e.frameScaleValue = document.getElementById('frameScaleValue');
|
||||
e.frameScaleRow = document.getElementById('frameScaleRow');
|
||||
|
||||
// Padding
|
||||
e.paddingAllInput = document.getElementById('framePaddingAll');
|
||||
e.paddingAllValue = document.getElementById('framePaddingAllValue');
|
||||
e.paddingTopInput = document.getElementById('framePaddingTop');
|
||||
e.paddingTopValue = document.getElementById('framePaddingTopValue');
|
||||
e.paddingRightInput = document.getElementById('framePaddingRight');
|
||||
e.paddingRightValue = document.getElementById('framePaddingRightValue');
|
||||
e.paddingBottomInput = document.getElementById('framePaddingBottom');
|
||||
e.paddingBottomValue = document.getElementById('framePaddingBottomValue');
|
||||
e.paddingLeftInput = document.getElementById('framePaddingLeft');
|
||||
e.paddingLeftValue = document.getElementById('framePaddingLeftValue');
|
||||
e.paddingAllRow = document.getElementById('framePaddingAllRow');
|
||||
e.paddingRow = document.getElementById('framePaddingRow');
|
||||
|
||||
// Pfeil
|
||||
e.arrowLengthInput = document.getElementById('arrowLength');
|
||||
e.arrowLengthValue = document.getElementById('arrowLengthValue');
|
||||
e.arrowAngleInput = document.getElementById('arrowAngle');
|
||||
e.arrowAngleValue = document.getElementById('arrowAngleValue');
|
||||
e.arrowBendInput = document.getElementById('arrowBend');
|
||||
e.arrowBendValue = document.getElementById('arrowBendValue');
|
||||
e.arrowSizeInput = document.getElementById('arrowSize');
|
||||
e.arrowSizeValue = document.getElementById('arrowSizeValue');
|
||||
e.arrowTipLengthInput = document.getElementById('arrowTipLength');
|
||||
e.arrowTipLengthValue = document.getElementById('arrowTipLengthValue');
|
||||
e.arrowDetailsRow = document.getElementById('arrowDetailsRow');
|
||||
e.arrowDetailsRow2 = document.getElementById('arrowDetailsRow2');
|
||||
|
||||
// Vorschau
|
||||
e.textPreview = document.getElementById('textPreview');
|
||||
e.standaloneArrowPreview = document.getElementById('standaloneArrowPreview');
|
||||
|
||||
// Buttons
|
||||
e.shapeButtons = document.querySelectorAll('.shape-btn');
|
||||
e.arrowButtons = document.querySelectorAll('.arrow-btn');
|
||||
e.lineStyleButtons = document.querySelectorAll('.line-style-btn');
|
||||
e.lineWeightButtons = document.querySelectorAll('.line-weight-btn');
|
||||
},
|
||||
|
||||
bindEvents: function() {
|
||||
var self = this;
|
||||
var e = this.elements;
|
||||
var state = window.TextGenState;
|
||||
|
||||
// Text-Input
|
||||
if (e.textInput) {
|
||||
e.textInput.addEventListener('input', function(ev) {
|
||||
state.set('text', ev.target.value);
|
||||
self.updatePreview();
|
||||
});
|
||||
}
|
||||
|
||||
// Schriftgroesse
|
||||
if (e.fontSizeInput) {
|
||||
e.fontSizeInput.addEventListener('input', function(ev) {
|
||||
var val = parseInt(ev.target.value);
|
||||
state.set('fontSize', val);
|
||||
if (e.fontSizeValue) e.fontSizeValue.textContent = val + 'px';
|
||||
self.updatePreview();
|
||||
});
|
||||
}
|
||||
|
||||
// Farben
|
||||
if (e.textColorInput) {
|
||||
e.textColorInput.addEventListener('input', function(ev) {
|
||||
state.set('textColor', ev.target.value);
|
||||
self.updatePreview();
|
||||
});
|
||||
}
|
||||
if (e.frameColorInput) {
|
||||
e.frameColorInput.addEventListener('input', function(ev) {
|
||||
state.set('frameColor', ev.target.value);
|
||||
self.updatePreview();
|
||||
});
|
||||
}
|
||||
|
||||
// Rahmen-Skalierung
|
||||
if (e.frameScaleInput) {
|
||||
e.frameScaleInput.addEventListener('input', function(ev) {
|
||||
var val = parseInt(ev.target.value);
|
||||
state.set('frameScale', val);
|
||||
if (e.frameScaleValue) e.frameScaleValue.textContent = val + '%';
|
||||
self.updatePreview();
|
||||
});
|
||||
}
|
||||
|
||||
// Gesamt-Padding
|
||||
if (e.paddingAllInput) {
|
||||
e.paddingAllInput.addEventListener('input', function(ev) {
|
||||
var val = parseInt(ev.target.value);
|
||||
state.setMultiple({
|
||||
paddingTop: val,
|
||||
paddingRight: val,
|
||||
paddingBottom: val,
|
||||
paddingLeft: val
|
||||
});
|
||||
if (e.paddingAllValue) e.paddingAllValue.textContent = val + 'px';
|
||||
// Einzelne Slider synchronisieren
|
||||
if (e.paddingTopInput) e.paddingTopInput.value = val;
|
||||
if (e.paddingTopValue) e.paddingTopValue.textContent = val + 'px';
|
||||
if (e.paddingRightInput) e.paddingRightInput.value = val;
|
||||
if (e.paddingRightValue) e.paddingRightValue.textContent = val + 'px';
|
||||
if (e.paddingBottomInput) e.paddingBottomInput.value = val;
|
||||
if (e.paddingBottomValue) e.paddingBottomValue.textContent = val + 'px';
|
||||
if (e.paddingLeftInput) e.paddingLeftInput.value = val;
|
||||
if (e.paddingLeftValue) e.paddingLeftValue.textContent = val + 'px';
|
||||
self.updatePreview();
|
||||
});
|
||||
}
|
||||
|
||||
// Einzelne Paddings
|
||||
this.bindPaddingSlider('paddingTopInput', 'paddingTopValue', 'paddingTop');
|
||||
this.bindPaddingSlider('paddingRightInput', 'paddingRightValue', 'paddingRight');
|
||||
this.bindPaddingSlider('paddingBottomInput', 'paddingBottomValue', 'paddingBottom');
|
||||
this.bindPaddingSlider('paddingLeftInput', 'paddingLeftValue', 'paddingLeft');
|
||||
|
||||
// Pfeil-Slider
|
||||
this.bindSlider('arrowLengthInput', 'arrowLengthValue', 'arrowLength', 'px');
|
||||
this.bindSlider('arrowAngleInput', 'arrowAngleValue', 'arrowAngle', '\u00B0');
|
||||
this.bindSlider('arrowBendInput', 'arrowBendValue', 'arrowBend', '%');
|
||||
this.bindSlider('arrowSizeInput', 'arrowSizeValue', 'arrowSize', 'px');
|
||||
this.bindSlider('arrowTipLengthInput', 'arrowTipLengthValue', 'arrowTipLength', 'px');
|
||||
|
||||
// Shape-Buttons
|
||||
e.shapeButtons.forEach(function(btn) {
|
||||
btn.addEventListener('click', function() {
|
||||
e.shapeButtons.forEach(function(b) { b.classList.remove('active'); });
|
||||
btn.classList.add('active');
|
||||
state.set('shape', btn.dataset.shape);
|
||||
self.updateVisibility();
|
||||
self.updatePreview();
|
||||
});
|
||||
});
|
||||
|
||||
// Arrow-Buttons
|
||||
e.arrowButtons.forEach(function(btn) {
|
||||
btn.addEventListener('click', function() {
|
||||
e.arrowButtons.forEach(function(b) { b.classList.remove('active'); });
|
||||
btn.classList.add('active');
|
||||
state.set('arrow', btn.dataset.arrow);
|
||||
self.updateVisibility();
|
||||
self.updatePreview();
|
||||
self.updateStandaloneArrowPreview();
|
||||
});
|
||||
});
|
||||
|
||||
// Line-Style-Buttons
|
||||
e.lineStyleButtons.forEach(function(btn) {
|
||||
btn.addEventListener('click', function() {
|
||||
e.lineStyleButtons.forEach(function(b) { b.classList.remove('active'); });
|
||||
btn.classList.add('active');
|
||||
state.set('lineStyle', btn.dataset.style);
|
||||
self.updatePreview();
|
||||
});
|
||||
});
|
||||
|
||||
// Line-Weight-Buttons
|
||||
e.lineWeightButtons.forEach(function(btn) {
|
||||
btn.addEventListener('click', function() {
|
||||
e.lineWeightButtons.forEach(function(b) { b.classList.remove('active'); });
|
||||
btn.classList.add('active');
|
||||
state.set('lineWeight', parseInt(btn.dataset.weight));
|
||||
self.updatePreview();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
bindSlider: function(inputKey, valueKey, stateKey, unit) {
|
||||
var self = this;
|
||||
var input = this.elements[inputKey];
|
||||
var valueEl = this.elements[valueKey];
|
||||
var state = window.TextGenState;
|
||||
|
||||
if (input) {
|
||||
input.addEventListener('input', function(ev) {
|
||||
var val = parseInt(ev.target.value);
|
||||
state.set(stateKey, val);
|
||||
if (valueEl) valueEl.textContent = val + unit;
|
||||
self.updatePreview();
|
||||
if (stateKey.indexOf('arrow') === 0) {
|
||||
self.updateStandaloneArrowPreview();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
bindPaddingSlider: function(inputKey, valueKey, stateKey) {
|
||||
var self = this;
|
||||
var input = this.elements[inputKey];
|
||||
var valueEl = this.elements[valueKey];
|
||||
var state = window.TextGenState;
|
||||
|
||||
if (input) {
|
||||
input.addEventListener('input', function(ev) {
|
||||
var val = parseInt(ev.target.value);
|
||||
state.set(stateKey, val);
|
||||
if (valueEl) valueEl.textContent = val + 'px';
|
||||
self.updatePreview();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
syncFromState: function() {
|
||||
var e = this.elements;
|
||||
var s = window.TextGenState.current;
|
||||
|
||||
if (e.textInput) e.textInput.value = s.text;
|
||||
if (e.fontSizeInput) e.fontSizeInput.value = s.fontSize;
|
||||
if (e.fontSizeValue) e.fontSizeValue.textContent = s.fontSize + 'px';
|
||||
if (e.textColorInput) e.textColorInput.value = s.textColor;
|
||||
if (e.frameColorInput) e.frameColorInput.value = s.frameColor;
|
||||
if (e.frameScaleInput) e.frameScaleInput.value = s.frameScale;
|
||||
if (e.frameScaleValue) e.frameScaleValue.textContent = s.frameScale + '%';
|
||||
|
||||
// Padding
|
||||
if (e.paddingAllInput) e.paddingAllInput.value = s.paddingTop;
|
||||
if (e.paddingAllValue) e.paddingAllValue.textContent = s.paddingTop + 'px';
|
||||
if (e.paddingTopInput) e.paddingTopInput.value = s.paddingTop;
|
||||
if (e.paddingTopValue) e.paddingTopValue.textContent = s.paddingTop + 'px';
|
||||
if (e.paddingRightInput) e.paddingRightInput.value = s.paddingRight;
|
||||
if (e.paddingRightValue) e.paddingRightValue.textContent = s.paddingRight + 'px';
|
||||
if (e.paddingBottomInput) e.paddingBottomInput.value = s.paddingBottom;
|
||||
if (e.paddingBottomValue) e.paddingBottomValue.textContent = s.paddingBottom + 'px';
|
||||
if (e.paddingLeftInput) e.paddingLeftInput.value = s.paddingLeft;
|
||||
if (e.paddingLeftValue) e.paddingLeftValue.textContent = s.paddingLeft + 'px';
|
||||
|
||||
// Pfeil
|
||||
if (e.arrowLengthInput) e.arrowLengthInput.value = s.arrowLength;
|
||||
if (e.arrowLengthValue) e.arrowLengthValue.textContent = s.arrowLength + 'px';
|
||||
if (e.arrowAngleInput) e.arrowAngleInput.value = s.arrowAngle;
|
||||
if (e.arrowAngleValue) e.arrowAngleValue.textContent = s.arrowAngle + '\u00B0';
|
||||
if (e.arrowBendInput) e.arrowBendInput.value = s.arrowBend;
|
||||
if (e.arrowBendValue) e.arrowBendValue.textContent = s.arrowBend + '%';
|
||||
if (e.arrowSizeInput) e.arrowSizeInput.value = s.arrowSize;
|
||||
if (e.arrowSizeValue) e.arrowSizeValue.textContent = s.arrowSize + 'px';
|
||||
if (e.arrowTipLengthInput) e.arrowTipLengthInput.value = s.arrowTipLength;
|
||||
if (e.arrowTipLengthValue) e.arrowTipLengthValue.textContent = s.arrowTipLength + 'px';
|
||||
|
||||
// Buttons aktivieren
|
||||
this.activateButton(e.shapeButtons, 'shape', s.shape);
|
||||
this.activateButton(e.arrowButtons, 'arrow', s.arrow);
|
||||
this.activateButton(e.lineStyleButtons, 'style', s.lineStyle);
|
||||
this.activateButtonByValue(e.lineWeightButtons, 'weight', s.lineWeight);
|
||||
},
|
||||
|
||||
activateButton: function(buttons, dataAttr, value) {
|
||||
buttons.forEach(function(btn) {
|
||||
btn.classList.remove('active');
|
||||
if (btn.dataset[dataAttr] === value) {
|
||||
btn.classList.add('active');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
activateButtonByValue: function(buttons, dataAttr, value) {
|
||||
buttons.forEach(function(btn) {
|
||||
btn.classList.remove('active');
|
||||
if (parseInt(btn.dataset[dataAttr]) === value) {
|
||||
btn.classList.add('active');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
updateVisibility: function() {
|
||||
var e = this.elements;
|
||||
var s = window.TextGenState.current;
|
||||
var hasShape = s.shape !== 'none';
|
||||
var hasArrow = s.arrow !== 'none';
|
||||
|
||||
if (e.frameScaleRow) e.frameScaleRow.style.display = hasShape ? 'flex' : 'none';
|
||||
if (e.paddingAllRow) e.paddingAllRow.style.display = hasShape ? 'flex' : 'none';
|
||||
if (e.paddingRow) e.paddingRow.style.display = hasShape ? 'flex' : 'none';
|
||||
if (e.arrowDetailsRow) e.arrowDetailsRow.style.display = hasArrow ? 'flex' : 'none';
|
||||
if (e.arrowDetailsRow2) e.arrowDetailsRow2.style.display = hasArrow ? 'flex' : 'none';
|
||||
},
|
||||
|
||||
updatePreview: function() {
|
||||
var e = this.elements;
|
||||
if (e.textPreview && window.SvgGenerator) {
|
||||
var svg = window.SvgGenerator.generate(window.TextGenState.current);
|
||||
e.textPreview.innerHTML = svg;
|
||||
}
|
||||
},
|
||||
|
||||
updateStandaloneArrowPreview: function() {
|
||||
var e = this.elements;
|
||||
var s = window.TextGenState.current;
|
||||
|
||||
if (!e.standaloneArrowPreview) return;
|
||||
|
||||
if (s.arrow === 'none') {
|
||||
e.standaloneArrowPreview.innerHTML = '<p style="color: #9ca3af; font-size: 0.9rem;">Waehle einen Pfeil aus</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
if (window.SvgGenerator) {
|
||||
var svg = window.SvgGenerator.generateArrowOnly(s);
|
||||
if (svg) {
|
||||
e.standaloneArrowPreview.innerHTML = svg;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
resetToDefaults: function() {
|
||||
window.TextGenState.reset();
|
||||
this.syncFromState();
|
||||
this.updateVisibility();
|
||||
this.updatePreview();
|
||||
this.updateStandaloneArrowPreview();
|
||||
}
|
||||
};
|
||||
|
||||
window.UiBindings = UiBindings;
|
||||
Reference in New Issue
Block a user