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');
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user