Skip to content

D3.js - SVG Transformation

Scalable Vector Graphics (SVG) provides powerful options to transform individual SVG elements or groups of elements. These transformations include translating (moving), scaling (resizing), rotating, and skewing. D3.js makes it easy to apply these transformations dynamically based on data.

SVG elements use the transform attribute to specify transformations. The value of this attribute is a string containing one or more transform definitions. Common transform functions are:

  • Translate: translate(tx [ty]) - Moves an element by tx along the x-axis and ty along the y-axis. If ty is not provided, it defaults to 0. Example: translate(30 30) or translate(50) (moves 50 along x, 0 along y).
  • Rotate: rotate(angle [cx cy]) - Rotates an element by angle degrees around a center point (cx, cy). If cx and cy are not specified, the rotation is around the origin (0,0) of the element’s current coordinate system. Example: rotate(60) or rotate(45 10 10).
  • Scale: scale(sx [sy]) - Scales an element by a factor sx along the x-axis and sy along the y-axis. If sy is not provided, it defaults to the value of sx (uniform scaling). Example: scale(2) (doubles size) or scale(1.5 0.5).
  • SkewX: skewX(angle) - Skews an element along the x-axis by angle degrees.
  • SkewY: skewY(angle) - Skews an element along the y-axis by angle degrees.

Example of an SVG rectangle with a translate transformation applied directly in SVG markup:

<svg width="200" height="150">
<rect x="10" y="10" width="50" height="50" fill="green" transform="translate(30 30)">
</rect>
<!-- The rectangle's top-left corner, originally at (10,10), will effectively be at (40,40) -->
</svg>

Multiple transformations can be applied by listing them in the transform attribute, separated by spaces. They are applied sequentially from left to right.

<svg width="200" height="200">
<rect x="20" y="20" width="60" height="60" fill="blue"
transform="translate(50 50) rotate(45)">
<!-- First translated, then rotated around its new (0,0) which is the translated point -->
</rect>
</svg>

Transformations can also be applied to SVG group elements (<g>). This is very useful as all child elements within the group inherit the transformation.

<svg width="300" height="300">
<g transform="translate(100,100) rotate(30)">
<rect x="0" y="0" width="80" height="40" fill="green"></rect>
<circle cx="40" cy="60" r="20" fill="red"></circle>
<!-- Both the rectangle and circle are translated and then rotated together -->
</g>
</svg>

Let’s build a small SVG graphic with transformations directly in HTML.

Step 1: Create an SVG container.

<svg width="300" height="300" style="border: 1px solid #ccc;">

Step 2: Create an SVG group (<g>) element.

<g>

Step 3: Add a rectangle to the group.

<rect x="20" y="20" width="60" height="30" fill="green"></rect>

Step 4: Add a circle to the group, relative to the group’s origin.

<circle cx="0" cy="0" r="30" fill="rgba(255,0,0,0.5)"></circle>
<!-- Note: circle is centered at the group's origin for this example -->

Step 5: Apply translate and rotate transformations to the group element.

<g transform="translate(100, 80) rotate(30)">
<rect x="20" y="20" width="60" height="30" fill="green"></rect>
<circle cx="0" cy="0" r="30" fill="rgba(255,0,0,0.5)"></circle>
</g>
</svg>

The full HTML code would be:

<!DOCTYPE html>
<html>
<head>
<title>SVG Transformation Example</title>
<style> body { font-family: Arial; } </style>
</head>
<body>
<h2>SVG Group Transformation</h2>
<svg width="300" height="300" style="border: 1px solid #ccc;">
<g transform="translate(100, 80) rotate(30)">
<rect x="20" y="20" width="60" height="30" fill="green"></rect>
<circle cx="0" cy="0" r="30" fill="rgba(255,0,0,0.5)">
</circle>
</g>
</svg>
</body>
</html>

When viewed in a browser, this will show a green rectangle and a semi-transparent red circle, both moved to (100,80) relative to the SVG’s top-left, and then rotated 30 degrees around that point.

D3.js allows you to create and manipulate these SVG elements and their transform attributes programmatically.

Step 1: Create a container div in your HTML to hold the SVG.

<div id="svgcontainer"></div>

Step 2: Use D3 to create an SVG image within the container.

const width = 300;
const height = 300;
const svg = d3.select("#svgcontainer")
.append("svg")
.attr("width", width)
.attr("height", height)
.style("border", "1px solid #ccc");

Step 3: Create an SVG group element and set its transform attribute using D3. Use template literals for cleaner transform strings.

const group = svg.append("g")
.attr("transform", `translate(100, 80) rotate(30)`);

Step 4: Create an SVG rectangle and append it to the group.

const rect = group.append("rect")
.attr("x", 20)
.attr("y", 20)
.attr("width", 60)
.attr("height", 30)
.attr("fill", "green");

Step 5: Create an SVG circle and append it to the group.

const circle = group.append("circle")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", 30)
.attr("fill", "rgba(255,0,0,0.5)");

The complete D3.js code integrated into an HTML page:

<!DOCTYPE html>
<html lang="en">
<head>
<title>D3.js SVG Transformation</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
<style> body { font-family: Arial; } </style>
</head>
<body>
<h2>SVG Transformation with D3.js</h2>
<div id="svgcontainer"></div>
<script>
const svgWidth = 300;
const svgHeight = 300;
const svg = d3.select("#svgcontainer")
.append("svg")
.attr("width", svgWidth)
.attr("height", svgHeight)
.style("border", "1px solid #ccc");
const group = svg.append("g")
.attr("transform", `translate(100, 80) rotate(30)`);
const rect = group.append("rect")
.attr("x", 20)
.attr("y", 20)
.attr("width", 60)
.attr("height", 30)
.attr("fill", "green");
const circle = group.append("circle")
.attr("cx", 0) // Relative to the group's (0,0)
.attr("cy", 0) // Relative to the group's (0,0)
.attr("r", 30)
.attr("fill", "rgba(255,0,0,0.5)");
</script>
</body>
</html>

This D3 code achieves the same visual result as the manual SVG markup example. The key D3 method used here is .attr("transform", "...") to set the transformation string. Understanding SVG’s transform system is crucial for positioning and orienting elements in D3 visualizations.