javascript 262 lines · 1 tab

SVG manipulation with JavaScript

Alex Chang Feb 2026
1 tab
// 1. Create SVG elements
const svgNS = 'http://www.w3.org/2000/svg';

function createSVGElement(type, attributes = {}) {
  const element = document.createElementNS(svgNS, type);
  Object.entries(attributes).forEach(([key, value]) => {
    element.setAttribute(key, value);
  });
  return element;
}

// Create SVG container
const svg = createSVGElement('svg', {
  width: '600',
  height: '400',
  viewBox: '0 0 600 400'
});
document.body.appendChild(svg);

// 2. Create shapes
// Circle
const circle = createSVGElement('circle', {
  cx: '100',
  cy: '100',
  r: '50',
  fill: '#4285f4',
  stroke: '#1a73e8',
  'stroke-width': '2'
});
svg.appendChild(circle);

// Rectangle
const rect = createSVGElement('rect', {
  x: '200',
  y: '50',
  width: '100',
  height: '80',
  fill: '#34a853',
  rx: '10' // rounded corners
});
svg.appendChild(rect);

// Line
const line = createSVGElement('line', {
  x1: '50',
  y1: '200',
  x2: '200',
  y2: '200',
  stroke: '#ea4335',
  'stroke-width': '3'
});
svg.appendChild(line);

// Polyline
const polyline = createSVGElement('polyline', {
  points: '250,200 300,220 350,180 400,210',
  fill: 'none',
  stroke: '#fbbc04',
  'stroke-width': '2'
});
svg.appendChild(polyline);

// Polygon
const polygon = createSVGElement('polygon', {
  points: '450,200 500,250 400,250',
  fill: '#ea4335'
});
svg.appendChild(polygon);

// 3. Path element (complex shapes)
const path = createSVGElement('path', {
  d: 'M 50 300 Q 150 250 250 300 T 450 300',
  fill: 'none',
  stroke: '#4285f4',
  'stroke-width': '2'
});
svg.appendChild(path);

// Path commands:
// M = moveto
// L = lineto
// H = horizontal lineto
// V = vertical lineto
// C = curveto (cubic Bezier)
// S = smooth curveto
// Q = quadratic Bezier curve
// T = smooth quadratic Bezier
// A = elliptical arc
// Z = closepath

// 4. Text
const text = createSVGElement('text', {
  x: '300',
  y: '350',
  'text-anchor': 'middle',
  'font-size': '24',
  fill: '#000'
});
text.textContent = 'SVG Text';
svg.appendChild(text);

// 5. Groups
const group = createSVGElement('g', {
  transform: 'translate(500, 300)'
});

const groupCircle = createSVGElement('circle', {
  cx: '0',
  cy: '0',
  r: '20',
  fill: '#4285f4'
});

const groupRect = createSVGElement('rect', {
  x: '-10',
  y: '-40',
  width: '20',
  height: '30',
  fill: '#34a853'
});

group.appendChild(groupCircle);
group.appendChild(groupRect);
svg.appendChild(group);

// 6. Animations with JavaScript
let angle = 0;

function rotateSVG() {
  angle += 1;
  group.setAttribute('transform', `translate(500, 300) rotate(${angle})`);
  requestAnimationFrame(rotateSVG);
}

rotateSVG();

// 7. Interactive SVG
circle.addEventListener('click', function() {
  const currentFill = this.getAttribute('fill');
  const newFill = currentFill === '#4285f4' ? '#ea4335' : '#4285f4';
  this.setAttribute('fill', newFill);
});

circle.addEventListener('mouseenter', function() {
  this.setAttribute('r', '60');
});

circle.addEventListener('mouseleave', function() {
  this.setAttribute('r', '50');
});

// 8. Drag and drop SVG elements
let selectedElement = null;
let offset = null;

svg.addEventListener('mousedown', (e) => {
  if (e.target.tagName === 'circle' || e.target.tagName === 'rect') {
    selectedElement = e.target;
    const transform = selectedElement.transform.baseVal;

    if (transform.length === 0) {
      const translate = svg.createSVGTransform();
      selectedElement.transform.baseVal.appendItem(translate);
    }

    const pt = svg.createSVGPoint();
    pt.x = e.clientX;
    pt.y = e.clientY;

    offset = pt.matrixTransform(svg.getScreenCTM().inverse());
  }
});

svg.addEventListener('mousemove', (e) => {
  if (selectedElement) {
    e.preventDefault();

    const pt = svg.createSVGPoint();
    pt.x = e.clientX;
    pt.y = e.clientY;

    const cursorPt = pt.matrixTransform(svg.getScreenCTM().inverse());
    const dx = cursorPt.x - offset.x;
    const dy = cursorPt.y - offset.y;

    const transform = selectedElement.transform.baseVal.getItem(0);
    transform.setTranslate(dx, dy);
  }
});

svg.addEventListener('mouseup', () => {
  selectedElement = null;
});

// 9. Charts with SVG
function createBarChart(data, width, height) {
  const chartSvg = createSVGElement('svg', {
    width: width,
    height: height,
    viewBox: `0 0 ${width} ${height}`
  });

  const maxValue = Math.max(...data.map(d => d.value));
  const barWidth = width / data.length;

  data.forEach((item, index) => {
    const barHeight = (item.value / maxValue) * (height - 40);
    const x = index * barWidth;
    const y = height - barHeight - 20;

    const bar = createSVGElement('rect', {
      x: x + 5,
      y: y,
      width: barWidth - 10,
      height: barHeight,
      fill: '#4285f4'
    });

    const label = createSVGElement('text', {
      x: x + barWidth / 2,
      y: height - 5,
      'text-anchor': 'middle',
      'font-size': '12'
    });
    label.textContent = item.label;

    chartSvg.appendChild(bar);
    chartSvg.appendChild(label);
  });

  return chartSvg;
}

const chartData = [
  { label: 'A', value: 30 },
  { label: 'B', value: 50 },
  { label: 'C', value: 40 },
  { label: 'D', value: 70 },
  { label: 'E', value: 20 }
];

const chart = createBarChart(chartData, 400, 200);
document.body.appendChild(chart);

// 10. SVG filters
const defs = createSVGElement('defs');
svg.appendChild(defs);

const filter = createSVGElement('filter', {
  id: 'blur'
});

const blur = createSVGElement('feGaussianBlur', {
  in: 'SourceGraphic',
  stdDeviation: '5'
});

filter.appendChild(blur);
defs.appendChild(filter);

// Apply filter
circle.setAttribute('filter', 'url(#blur)');
1 file · javascript Explain with highlit

SVG (Scalable Vector Graphics) creates resolution-independent graphics. I manipulate SVG elements with DOM methods like createElementNS(). Attributes control SVG properties: setAttribute(), getAttribute(). Animations use CSS or SMIL for declarative effects. The getBBox() method gets element dimensions. Path data with d attribute defines complex shapes. The viewBox attribute controls coordinate system and scaling. SVG filters create visual effects. Inline SVG allows CSS styling and JavaScript interaction. SVG excels at icons, logos, charts, and responsive graphics.


Related snips

javascript
// Creating a Promise
const myPromise = new Promise((resolve, reject) => {
  const success = true;

  setTimeout(() => {
    if (success) {

Promises and async/await patterns for asynchronous JavaScript

javascript promises async-await
by Alex Chang 1 tab
javascript
import { Controller } from "@hotwired/stimulus"
import Mousetrap from "mousetrap"

export default class extends Controller {
  connect() {
    // Global shortcuts

Keyboard shortcuts with Stimulus and Mousetrap

stimulus javascript ux
by Jordan Lee 2 tabs
javascript
// Get canvas and context
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');

// 1. Basic shapes
// Rectangle (filled)

Canvas API for graphics and animations

canvas javascript graphics
by Alex Chang 1 tab
javascript
// Basic event listener
const button = document.getElementById('myButton');

button.addEventListener('click', function(event) {
  console.log('Button clicked!');
  console.log('Event type:', event.type);

Event handling and event delegation patterns in JavaScript

javascript events event-delegation
by Alex Chang 1 tab
javascript
// Basic GET request
fetch('https://api.example.com/users')
  .then(response => {
    console.log('Status:', response.status);
    console.log('OK:', response.ok);
    return response.json();

Fetch API for HTTP requests and AJAX communication

javascript fetch api
by Alex Chang 1 tab
erb
<turbo-stream action="set_title">
  <template><%= "Inbox (#{@unread_count})" %></template>
</turbo-stream>

Turbo Streams: update document title with a custom action

rails hotwire turbo
by Henry Kim 2 tabs

Share this code

Here's the card — post it anywhere.

SVG manipulation with JavaScript — share card
Link copied