Create Your Own Micro-Vector Editor: Simple Steps to Build a Small SVG Graphics Tool
- realcode4you
- Mar 3
- 8 min read
Creating vector graphics is a valuable skill for designers, developers, and hobbyists alike. While professional tools like Adobe Illustrator or Inkscape offer powerful features, sometimes you need a lightweight, custom solution tailored to your specific needs. Building a micro-vector editor that works with SVG (Scalable Vector Graphics) files can be a rewarding project that deepens your understanding of graphics programming and web technologies.
This guide walks you through the essential steps to build a small SVG graphics editor. You will learn how to create, manipulate, and save vector shapes using simple web technologies. By the end, you will have a functional micro-vector editor that you can expand or customize further.

Understanding SVG and Its Advantages
SVG is an XML-based format for describing two-dimensional vector graphics. Unlike raster images, SVG graphics scale without losing quality, making them ideal for responsive designs and high-resolution displays.
Why Choose SVG for Your Vector Editor?
Scalability: SVG images maintain crispness at any size.
Text-based: Easy to read, edit, and manipulate with code.
Browser support: Modern browsers render SVG natively.
Interactivity: SVG supports animations and event handling.
Lightweight: SVG files are often smaller than raster images.
By building a micro-vector editor around SVG, you leverage these benefits while keeping your tool lightweight and accessible.
Setting Up the Project Environment
Start by creating a simple HTML page that will host your vector editor. You will need:
An HTML container (like a `<div>` or `<svg>` element) to display and edit graphics.
Basic CSS for layout and styling.
JavaScript to handle user interactions and SVG manipulation.
Here’s a minimal setup:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Micro-Vector Editor</title>
<style>
border: 1px solid #ccc;
width: 800px;
height: 600px;
background-color: #f9f9f9;
cursor: crosshair;
}
.toolbar {
margin-bottom: 10px;
}
button {
margin-right: 5px;
}
</style>
</head>
<body>
<div class="toolbar">
<button id="drawRect">Rectangle</button>
<button id="drawCircle">Circle</button>
<button id="select">Select</button>
<button id="delete">Delete</button>
</div>
<svg id="svgCanvas"></svg>
<script src="editor.js"></script>
</body>
</html>
```
This structure includes a toolbar with buttons for drawing shapes and selecting or deleting them, plus an SVG canvas where shapes will appear.
Drawing Basic Shapes
The first feature to implement is drawing simple shapes like rectangles and circles.
Drawing Rectangles
When the user clicks the "Rectangle" button, the editor should allow them to click and drag on the SVG canvas to create a rectangle.
Key steps:
Listen for mouse events on the SVG canvas.
On mouse down, record the starting point.
On mouse move, update the rectangle’s width and height based on the cursor position.
On mouse up, finalize the rectangle.
Example JavaScript snippet:
```js
const svgCanvas = document.getElementById('svgCanvas');
let drawing = false;
let currentShape = null;
let startX, startY;
document.getElementById('drawRect').addEventListener('click', () => {
svgCanvas.style.cursor = 'crosshair';
svgCanvas.onmousedown = (e) => {
drawing = true;
startX = e.offsetX;
startY = e.offsetY;
currentShape = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
currentShape.setAttribute('x', startX);
currentShape.setAttribute('y', startY);
currentShape.setAttribute('width', 0);
currentShape.setAttribute('height', 0);
currentShape.setAttribute('fill', 'rgba(0, 120, 215, 0.5)');
currentShape.setAttribute('stroke', '#0078d7');
svgCanvas.appendChild(currentShape);
};
svgCanvas.onmousemove = (e) => {
if (!drawing) return;
const width = e.offsetX - startX;
const height = e.offsetY - startY;
currentShape.setAttribute('width', Math.abs(width));
currentShape.setAttribute('height', Math.abs(height));
currentShape.setAttribute('x', width < 0 ? e.offsetX : startX);
currentShape.setAttribute('y', height < 0 ? e.offsetY : startY);
};
svgCanvas.onmouseup = () => {
drawing = false;
svgCanvas.onmousedown = null;
svgCanvas.onmousemove = null;
};
});
```
Drawing Circles
Similarly, implement circle drawing by calculating the radius from the drag distance.
```js
document.getElementById('drawCircle').addEventListener('click', () => {
svgCanvas.style.cursor = 'crosshair';
svgCanvas.onmousedown = (e) => {
drawing = true;
startX = e.offsetX;
startY = e.offsetY;
currentShape = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
currentShape.setAttribute('cx', startX);
currentShape.setAttribute('cy', startY);
currentShape.setAttribute('r', 0);
currentShape.setAttribute('fill', 'rgba(255, 165, 0, 0.5)');
currentShape.setAttribute('stroke', '#ffa500');
svgCanvas.appendChild(currentShape);
};
svgCanvas.onmousemove = (e) => {
if (!drawing) return;
const dx = e.offsetX - startX;
const dy = e.offsetY - startY;
const radius = Math.sqrt(dx dx + dy dy);
currentShape.setAttribute('r', radius);
};
svgCanvas.onmouseup = () => {
drawing = false;
svgCanvas.onmousedown = null;
svgCanvas.onmousemove = null;
};
});
```
Selecting and Editing Shapes
A useful vector editor allows users to select shapes and modify them.
Selecting Shapes
Add event listeners to shapes so that clicking on them highlights the selection.
```js
svgCanvas.addEventListener('click', (e) => {
if (e.target === svgCanvas) return; // Ignore clicks on empty canvas
clearSelection();
e.target.setAttribute('stroke-width', 3);
e.target.setAttribute('stroke', '#ff0000');
selectedShape = e.target;
});
function clearSelection() {
const shapes = svgCanvas.querySelectorAll('rect, circle');
shapes.forEach(shape => {
shape.setAttribute('stroke-width', 1);
shape.setAttribute('stroke', shape.tagName === 'rect' ? '#0078d7' : '#ffa500');
});
selectedShape = null;
}
```
Moving Shapes
To move a selected shape, listen for drag events and update its position attributes.
```js
let selectedShape = null;
let offsetX, offsetY;
svgCanvas.addEventListener('mousedown', (e) => {
if (e.target === svgCanvas) return;
selectedShape = e.target;
offsetX = e.offsetX;
offsetY = e.offsetY;
svgCanvas.onmousemove = dragShape;
svgCanvas.onmouseup = () => {
svgCanvas.onmousemove = null;
svgCanvas.onmouseup = null;
};
});
function dragShape(e) {
if (!selectedShape) return;
const dx = e.offsetX - offsetX;
const dy = e.offsetY - offsetY;
offsetX = e.offsetX;
offsetY = e.offsetY;
if (selectedShape.tagName === 'rect') {
const x = parseFloat(selectedShape.getAttribute('x')) + dx;
const y = parseFloat(selectedShape.getAttribute('y')) + dy;
selectedShape.setAttribute('x', x);
selectedShape.setAttribute('y', y);
} else if (selectedShape.tagName === 'circle') {
const cx = parseFloat(selectedShape.getAttribute('cx')) + dx;
const cy = parseFloat(selectedShape.getAttribute('cy')) + dy;
selectedShape.setAttribute('cx', cx);
selectedShape.setAttribute('cy', cy);
}
}
```
Deleting Shapes
Add a delete button that removes the currently selected shape.
```js
document.getElementById('delete').addEventListener('click', () => {
if (selectedShape) {
svgCanvas.removeChild(selectedShape);
selectedShape = null;
}
});
```
Saving and Exporting SVG
Users will want to save their work. Exporting the SVG content as a file is straightforward.
```js
function downloadSVG() {
const svgData = svgCanvas.outerHTML;
const blob = new Blob([svgData], { type: 'image/svg+xml' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'drawing.svg';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
const saveButton = document.createElement('button');
saveButton.textContent = 'Save SVG';
saveButton.onclick = downloadSVG;
document.querySelector('.toolbar').appendChild(saveButton);
```
This code creates a button that triggers the download of the current SVG canvas as an SVG file.
Extending Your Micro-Vector Editor
Once you have the basics, consider adding these features:
Undo/Redo: Track changes and allow users to revert actions.
More Shapes: Add lines, polygons, or paths.
Color Picker: Let users change fill and stroke colors.
Resize Handles: Enable resizing shapes with drag handles.
Layer Management: Organize shapes in layers for complex drawings.
Text Support: Add text elements with font controls.
Each feature builds on the core concepts of SVG manipulation and event handling.
Building a micro-vector editor is a practical way to learn about SVG and interactive graphics programming. Starting with simple shapes and basic editing tools, you can create a functional vector graphics tool that fits your needs. Experiment with adding new features and refining the user interface to make your editor more powerful and user-friendly.
Problem Statement and Sample Paper
Objective
In this assignment, we will build a small vector graphics editor, inspired by tools like Inkscape (https://inkscape.org/). The goal is to write structured, readable, and correct code that manipulates vector graphics through a defined set of UI (user interface) actions.
This is your first serious programming assignment, and the emphasis is on clean design, correctness, and robustness. Note that there are two kinds of graphics editors – vector graphics (stores a line as a pair of points) and raster graphics (stores all the points on a line). Here, we are only interested in vector graphics, where the parameters of a shape are stored.
Problem Statement
You must implement a vector graphics editor with a graphical user interface. The entire code needs to be written in C++. Here are the broad high-level features that are needed.
Reads an input SVG file (restricted subset).
Show the diagram in the SVG on the canvas of the editor. Allows the user to modify it or create a diagram from scratch.
Writes the modified diagram to an SVG output file.
SVG stands for scalable vector graphics. It is a format for representing vector graphics diagrams. You can read more about it at https://www.w3.org/TR/SVG2/. An SVG file conforms to the XML standard (https://www.w3schools.com/xml/). Hence, reading and writing an SVG file requires one to read/write XML files. An XML file has a very simple format. Hence, you must implement your own XML/SVG parser (do not use third-party XML/SVG parsing libraries). Your parser should be able to read the SVG subset, apply edits to that model, and serialize the updated model back into a valid SVG file.
The GUI must correctly render the current (edited) diagram on the canvas. Any modification performed through the editor (e.g., creating, moving, resizing, changing stroke/fill) must be immediately reflected in the on-screen rendering and must be preserved when saving the SVG.
Background: What is a parser?
It reads an XML+SVG code snippet of the form.
<svg width="100" height="100">
<circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
</svg>
It creates a node of type circle, sets the width and height of its bounding box (100,100), sets the coordinates of its center (50,50), sets its radius (40), the stroke color to green, the width of the line to 4 and the internal color to yellow. Do not use a third-party library. It is easy to write a small parser of your own. In this case, there can be a high-level Circle object, which is derived from GraphicsObject. Every GraphicsObject will define the size of its bounding box (width and height using two fields). It can additionally define the width of the boundary (stroke-width), the color of the boundary and the color of the interior. These attributes are independent of the shape. They are equally relevant for a rectangle also. The Circle object, which is a derived class needs to additionally contain the coordinates of the center and the radius.
With every object, you can either override the “>>” operator or define a custom function to print its corresponding SVG representation. This can be used while writing to an SVG file.
A diagram is just a collection of such objects. It can be represented as a vector of objects, which is initially populated by reading an SVG file. Modifications can be made, and a new SVG file can also be created.
To understand the standard, the best methods are to read the standard and then open the SVG files in your favorite text editor, and try to understand their syntax. You can make changes in Inkscape and correlate with the changes in the SVG file.
Background: GUI Frameworks in C++
This is where there is a need to use a third-party library (use it only for rendering). Use the Qt community version. It runs on Windows, Mac and Linux. There is a need to create a window that looks like this. Link: https://www.qt.io/development/download-open-source

Details:
Here are the specific SVG features that need to be supported.
Rectangle
Rounded rectangle (see Inkscape’s implementation)
Circle
Line
Hexagon
Freehand sketch
Text
Colors for the boundary and the interior
Here are the specific features that need to be supported in the menu bar.
New, Open SVG file (restricted subset)
Save, and “Save As”
Close
Cut, copy, paste
Undo and Redo (understand the undo and redo stacks, use Google or ChatGPT)
Code Quality:
Use sophisticated C++ object-oriented features
Use smart pointers
Create multiple files (do not have more than 100 lines per file)
Note that header files only contain class and function signatures. They never contain code.
Define a CMake based build system. The only command that one needs to build the code should be cmake (with different arguments).
Learn the user of debuggers. Use them extensively. Specifically, learn Step-In, Step-
out, Step-over, breakpoints and watchpoints.
Comment your code extensively.
Follow the Google C++ style guide
(https://google.github.io/styleguide/cppguide.html)



Comments