Vector graphics editor with raster-to-SVG auto-tracing, element manipulation, zoom control, and export to SVG or high-resolution PNG.
<iframe id="se-demo" src="/online/webapp/svg-editor" width="100%" height="500" frameborder="0" style="border:1px solid #ccc; border-radius:4px;"></iframe>
<script>window._wsConnect('se-demo', 'seSocket');</script>
<iframe src="https://sgapps.io/online/webapp/svg-editor"
width="100%" height="600" frameborder="0"></iframe><iframe src="https://sgapps.io/online/webapp/svg-editor/url/aHR0cHM6Ly9leGFtcGxlLmNvbS9pY29uLnN2Zw=="
width="100%" height="600" frameborder="0"></iframe>loadSvgImage -- Load SVG SourceLoads an SVG document from a string into the editor. Use this to programmatically set the SVG content.
| Arg | Type | Description |
|---|---|---|
svgString | string | Raw SVG markup |
callback | function | (err) |
socket.fire("webapp::instance::request", "loadSvgImage",
'<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">' +
'<circle cx="100" cy="100" r="80" fill="coral" />' +
'<text x="100" y="110" text-anchor="middle" fill="white" font-size="24">Hello</text>' +
'</svg>',
function (err) { console.log("SVG loaded"); }
);<button onclick="window._ws('seSocket')&&window.seSocket.fire('webapp::instance::request','loadSvgImage','<svg xmlns='http://www.w3.org/2000/svg' width='300' height='200'><rect width='300' height='200' fill='#4a6cf7' rx='10'/><circle cx='150' cy='100' r='60' fill='#fff3'/><text x='150' y='108' text-anchor='middle' fill='white' font-size='20'>SGApps</text></svg>')">Try: Load Sample SVG</button>
loadRasterImage -- Import Raster ImageImports a raster image (PNG, JPEG, etc.) and auto-traces it to SVG vectors using the ImageTracer algorithm. The result replaces the current editor content.
| Arg | Type | Description |
|---|---|---|
imageBase64 | string | Base64 image data |
callback | function | (err) |
options | object (optional) | { numberofcolors, mincolorratio, linefilter } |
socket.fire("webapp::instance::request", "loadRasterImage",
"data:image/png;base64,iVBORw0KGgo...",
function (err) { console.log("Traced"); },
{ numberofcolors: 16, mincolorratio: 3, linefilter: true }
);getSVGSource -- Get SVG SourceReturns the current SVG source as a string. This is the most common way to extract the edited content.
socket.fire("webapp::instance::request", "getSVGSource", function (err, svgString) {
console.log("SVG source:", svgString.length, "bytes");
});<button onclick="window._ws('seSocket')&&window.seSocket.fire('webapp::instance::request','getSVGSource',function(e,s){if(s)alert('SVG length: '+s.length+' bytes\n\n'+s.substring(0,300)+'...')})">Try: Get SVG Source</button>
getSVGDynamicSource, getSVGAbsoluteSource -- Alternative ExportgetSVGDynamicSource -- returns SVG with dynamic (relative) coordinatesgetSVGAbsoluteSource -- returns SVG with all coordinates converted to absolutesocket.fire("webapp::instance::request", "getSVGAbsoluteSource", function (err, svg) {
// SVG with absolute path coordinates
});generateRasterImage -- Export as PNGRenders the current SVG to a high-resolution PNG (scaled to 3500px) and returns it as a base64 data URL.
socket.fire("webapp::instance::request", "generateRasterImage", function (err, pngDataUrl) {
var img = document.createElement('img');
img.src = pngDataUrl;
document.body.appendChild(img);
});<button onclick="window._ws('seSocket')&&window.seSocket.fire('webapp::instance::request','generateRasterImage',function(e,d){if(d){var i=document.createElement('img');i.src=d;i.style.maxHeight='120px';document.getElementById('se-png-result').innerHTML='';document.getElementById('se-png-result').appendChild(i);}})">Try: Export PNG</button><div id="se-png-result" style="margin:8px 0; min-height:20px;"></div>
editor:currentElement:getAttribute -- Get Element AttributesReads attributes from the currently selected SVG element.
| Arg | Type | Description |
|---|---|---|
attrs | Array | Attribute names to read (e.g., ["fill", "stroke", "stroke-width"]) |
callback | function | (err, values: object) |
socket.fire("webapp::instance::request", "editor:currentElement:getAttribute",
["fill", "stroke", "opacity"],
function (err, attrs) { console.log(attrs); }
);editor:currentElement:setAttribute -- Set Element AttributesSets attributes on the selected element. Pass null as a value to remove an attribute.
| Arg | Type | Description |
|---|---|---|
attrs | object | { attributeName: value } |
callback | function | (err) |
socket.fire("webapp::instance::request", "editor:currentElement:setAttribute",
{ fill: "#ff6600", "stroke-width": "3", stroke: "#333" }
);editor:currentElement:set-zoom, editor:currentElement:get-zoom -- Zoom// Set zoom to 150%
socket.fire("webapp::instance::request", "editor:currentElement:set-zoom", 1.5);
// Get current zoom
socket.fire("webapp::instance::request", "editor:currentElement:get-zoom",
function (err, zoom) { console.log("Zoom:", zoom); }
);<!DOCTYPE html>
<html>
<head><title>SVG Editor Widget</title></head>
<body>
<div style="display:flex;gap:8px;padding:10px;flex-wrap:wrap;">
<button id="load-svg">Load Circle</button>
<button id="get-svg">Get SVG</button>
<button id="export-png">Export PNG</button>
</div>
<iframe id="editor" src="https://sgapps.io/online/webapp/svg-editor"
width="100%" height="500" frameborder="0"></iframe>
<pre id="svg-output" style="background:#f6f8fa;padding:8px;max-height:200px;overflow:auto;"></pre>
<script src="https://sgapps.io/components/window-socket/index.js"></script>
<script>
var socket = new WindowSocket(document.getElementById('editor').contentWindow);
socket.start();
socket.on("webapp::connection::ping", function () {
socket.fire("webapp::instance::embed-mode", true);
});
document.getElementById('load-svg').onclick = function () {
socket.fire("webapp::instance::request", "loadSvgImage",
'<svg xmlns="http://www.w3.org/2000/svg" width="300" height="300">' +
'<circle cx="150" cy="150" r="120" fill="#4a6cf7" />' +
'<circle cx="150" cy="150" r="80" fill="#fff" opacity="0.3" />' +
'</svg>');
};
document.getElementById('get-svg').onclick = function () {
socket.fire("webapp::instance::request", "getSVGSource",
function (err, svg) {
document.getElementById('svg-output').textContent = svg;
});
};
document.getElementById('export-png').onclick = function () {
socket.fire("webapp::instance::request", "generateRasterImage",
function (err, data) {
var a = document.createElement('a');
a.href = data;
a.download = 'export.png';
a.click();
});
};
</script>
</body>
</html>