Vector Graphics Creator
Canvas
Add Shape
Shape Library
Export
No shapes added yet.
'; } shapes.forEach(shape => { const div = document.createElement('div'); div.className = "vgc-shape-item"; let props = ''; if (shape.type === 'rect') { props = `x: ${shape.x}, y: ${shape.y}, w: ${shape.width}, h: ${shape.height}`; } else { props = `cx: ${shape.cx}, cy: ${shape.cy}, r: ${shape.r}`; } div.innerHTML = `
${shape.type}
${props}
`;
ui.shapeList.appendChild(div);
});
// Render Raw Code
ui.rawCode.value = generateSVGMarkup();
}
/**
* Redraws all UI components
*/
function renderAll() {
renderSVGPreview();
renderConfigUI();
}
// --- Event Handlers ---
// Form selection
ui.shapeType.addEventListener('change', () => {
const isRect = ui.shapeType.value === 'rect';
ui.rectProps.style.display = isRect ? 'block' : 'none';
ui.circleProps.style.display = isRect ? 'none' : 'block';
});
// Add Shape
ui.addShapeForm.addEventListener('submit', (e) => {
e.preventDefault();
const type = ui.shapeType.value;
const newShape = {
id: Date.now(),
type: type,
fill: ui.shapeFill.value,
stroke: ui.shapeStroke.value,
strokeWidth: parseInt(ui.strokeWidth.value)
};
if (type === 'rect') {
newShape.x = parseInt(document.getElementById('rect-x').value);
newShape.y = parseInt(document.getElementById('rect-y').value);
newShape.width = parseInt(document.getElementById('rect-w').value);
newShape.height = parseInt(document.getElementById('rect-h').value);
} else {
newShape.cx = parseInt(document.getElementById('circle-cx').value);
newShape.cy = parseInt(document.getElementById('circle-cy').value);
newShape.r = parseInt(document.getElementById('circle-r').value);
}
shapes.push(newShape);
saveState();
renderAll();
});
// Canvas controls
[ui.canvasWidth, ui.canvasHeight, ui.bgColor].forEach(el => {
el.addEventListener('change', () => {
updateCanvasSettings();
saveState();
renderAll();
});
});
// Delete Shape
ui.shapeList.addEventListener('click', (e) => {
if (e.target.tagName === 'BUTTON' && e.target.dataset.id) {
const id = parseInt(e.target.dataset.id);
shapes = shapes.filter(s => s.id !== id);
saveState();
renderAll();
}
});
// --- Download Handlers ---
function download(blob, filename) {
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = filename;
link.click();
URL.revokeObjectURL(link.href);
}
ui.copySvgBtn.addEventListener('click', () => {
ui.rawCode.select();
document.execCommand('copy');
});
ui.downloadSvgBtn.addEventListener('click', () => {
const markup = generateSVGMarkup();
const blob = new Blob([markup], { type: 'image/svg+xml' });
download(blob, 'vector_graphic.svg');
});
ui.downloadPngBtn.addEventListener('click', () => {
const svgElement = ui.svgPreview.querySelector('svg');
if (!svgElement) return;
html2canvas(svgElement, { backgroundColor: null }).then(canvas => {
canvas.toBlob(blob => {
download(blob, 'vector_graphic.png');
});
});
});
ui.downloadPdfBtn.addEventListener('click', () => {
const { jsPDF } = window.jspdf;
if (!jsPDF || !window.html2canvas) {
alert("PDF libraries not loaded!");
return;
}
const svgElement = ui.svgPreview.querySelector('svg');
if (!svgElement) return;
html2canvas(svgElement, { scale: 2, backgroundColor: null }).then(canvas => {
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF({
orientation: canvas.width > canvas.height ? 'landscape' : 'portrait',
unit: 'px',
format: [canvas.width, canvas.height]
});
pdf.addImage(imgData, 'PNG', 0, 0, canvas.width, canvas.height);
pdf.save('vector_graphic.pdf');
});
});
// --- Tab switching ---
ui.tabButtons.forEach(button => {
button.addEventListener('click', () => {
const targetTab = button.dataset.tab;
ui.tabButtons.forEach(btn => btn.classList.remove('active'));
button.classList.add('active');
ui.tabContents.forEach(content => {
content.classList.toggle('active', content.id === `vgc-tab-${targetTab}`);
});
});
});
// --- Nav buttons ---
ui.nextTabBtn.addEventListener('click', () => {
ui.tabButtons.forEach((btn, i) => {
if (btn.classList.contains('active') && i + 1 < ui.tabButtons.length) {
ui.tabButtons[i + 1].click();
}
});
});
ui.prevTabBtn.addEventListener('click', () => {
ui.tabButtons.forEach((btn, i) => {
if (btn.classList.contains('active') && i > 0) {
ui.tabButtons[i - 1].click();
}
});
});
function escapeHTML(str) {
const p = document.createElement('p');
p.textContent = str;
return p.innerHTML;
}
// --- Initial Load ---
loadState();
renderAll();
});
