Skip to content

Instantly share code, notes, and snippets.

Last active October 10, 2023 11:44
Show Gist options
  • Save vijithassar/8278587 to your computer and use it in GitHub Desktop.
Save vijithassar/8278587 to your computer and use it in GitHub Desktop.
d3textwrap plugin demo
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("d3-selection")):"function"==typeof define&&define.amd?define(["exports","d3-selection"],e):e(t.d3=t.d3||{},t.d3)}(this,function(t,e){"use strict";var n,o,r,i,d,u,p,a;n="undefined"==typeof SVGForeignObjectElement?"tspans":"foreignobject",o=function(t){var n,o;return o="function"==typeof t,"object"!=typeof t||t.nodeType?!!(t instanceof e.selection||t.nodeType||o||n)||(console.error("invalid bounds specified for text wrapping"),!1):!(!t.height||!t.width)||(console.error("text wrapping bounds must specify height and width"),!1)},r=function(t){var e,n,o,r;for(e=["height","width"],"function"==typeof t?n=t():t.nodeType?n=t.getBoundingClientRect():"object"==typeof t&&(n=t),o=Object.create(null),r=0;r<e.length;r++)o[e[r]]=n[e[r]];return o},i=function(t){var e;return"function"==typeof t?e=t():"number"==typeof t?e=t:"undefined"==typeof t&&(e=0),"number"==typeof e?e:void console.error("padding could not be converted into a number")},d=function(t,e){var n;return n={height:t.height-2*e,width:t.width-2*e}},u=function(t,e){var n;return n=d(r(t),i(e))},p={},p.foreignobject=function(t,n,o){var r,i,d,u;return r=t.text(),,t.remove(),d=i.append("foreignObject"),d.attr("requiredFeatures","").attr("width",n.width).attr("height",n.height),"number"==typeof o&&d.attr("x",o).attr("y",o),u=d.append("xhtml:div"),"height",n.height).style("width",n.width).html(r),u},p.tspans=function(t,e,n){var o,r,i,d,u,p;for(o=t.text().split(" ").reverse(),t.text(""),u=t.append("tspan"),u.attr("dx",0).attr("dy",0),d=0;o.length>0;)r=o.pop(),u.text(u.text()+" "+r),i=u.node().getComputedTextLength()||0,i>e.width&&(p=u.text().split(" ").slice(0,-1).join(" "),u.text(p),d=u.node().getComputedTextLength()*-1,u=t.append("tspan"),u.attr("dx",d).attr("dy","1em").text(r));"number"==typeof n&&t.attr("y",t.attr("y")+n).attr("x",t.attr("x")+n)},a=function(){var t,r,d;return t=function(t){t.each(function(){[n],u(r,d),i(d))})},t.bounds=function(e){return e?o(e)?(r=e,t):(console.error("invalid text wrapping bounds"),!1):r},t.padding=function(e){return e?"number"==typeof e||"function"==typeof e?(d=e,t):(console.error("text wrap padding value must be either a number or a function"),!1):d},t.method=function(e){return e?(n=e,t):n},t};var c=a;t.selection=e.selection,,t.textwrap=c,Object.defineProperty(t,"__esModule",{value:!0})});
<title>d3-textwrap example</title>
<link href="textwrapdemo.css" rel="stylesheet" type="text/css">
<div id="page-wrapper">
<div id="overview">
<a href="">d3-textwrap</a> is a <a href="">D3.js</a> plugin written by <a href="">Vijith Assar</a></a> which allows quick cross-browser text wrapping in SVG images.
<div id="demo">
<div id="text-content">
<textarea>All work and no play makes Vijith a dull boy. All work and no play makes Vijith a dull boy. All work and no play makes Vijith a dull boy. All work and no play makes Vijith a dull boy. All work and no play makes Vijith a dull boy. All work and no play makes Vijith a dull boy. All work and no play makes Vijith a dull boy. All work and no play makes Vijith a dull boy. All work and no play makes Vijith a dull boy.</textarea>
<div id="set-padding">
<h3>Padding (optional)</h3>
<input name="padding" id="padding" type="text" value="30">
<div id="wrap-targets">
<h3>Click to wrap</h3>
<script src="" type="text/javascript"></script>
<script src="./d3-textwrap.min.js" type="text/javascript"></script>
<script src="textwrapdemo.js" type="text/javascript"></script>
body {
font-family: 'Georgia', 'Crimson-Text', 'serif';
width: 100%;
float: left;
h3 {
font-size: small;
font-family: 'Arial Black', 'Arial', 'sans-serif';
text-transform: uppercase;
font-weight: bold;
color: #666666;
div#page-wrapper {
display: block;
margin: auto;
padding: 1em;
width: 960px;
div#overview {
text-align: left;
width: 30%;
float: left;
font-size: large;
font-style: italic;
padding: 2.7em 1em 0em 1em;
div#text-content {
width: 30%;
float: left;
padding: 0 1em 0 1em;
div#set-padding {
width: 20%;
float: left;
padding: 0 1em 0 1em;
div#wrap-targets {
clear: both;
div#demo {
width: 900px;
div#overview {
color: #111111;
div#overview a {
color: #111111;
div#demo textarea {
width: 100%;
height: 120px;
border: 1px solid #666666;
color: #666666;
font-size: x-small;
font-family: 'Arial', 'sans-serif'
div#demo input#padding {
font-family: 'Georgia', 'Crimson Text', 'serif';
font-style: italic;
width: 240px;
height: 120px;
font-size: 70px;
color: #666666;
border: 1px solid #666666;
text-align: center;
div#demo svg {
height: 240px;
width: 100%;
background-color: #FFFFFF;
border: 1px solid #666666;
svg g.targets {
font-size: 120%;
color: #666666;
svg .first {
fill: #FFCCCC;
svg .second {
fill: #CCFFFF;
svg .third {
fill: #FFFFCC;
(function() {
// general setup, declare variables
var demo,
demo ='div#demo')
svg ='svg')
width ='width').replace('px', '')
height ='height').replace('px', '')
// create three rectangles
first = svg.append('g').classed('target', true)
.attr('transform', 'translate(0,0)')
.attr('width', width * 0.4)
.attr('height', height)
.classed('first', true)
second = svg.append('g').classed('target', true)
.attr('transform', 'translate(' + (width * 0.4) + ',0)')
.attr('width', width * 0.35)
.attr('height', height)
.classed('second', true)
third = svg.append('g').classed('target', true)
.attr('transform', 'translate(' + (width * 0.75) + ',0)')
.attr('width', width * 0.25)
.attr('height', height)
.classed('third', true)
wrap = d3.textwrap()
targets = svg.selectAll('')
// wrap text into rectangle on click
targets.on('click', function() {
var padding,
// remove any text which is already present
// add a text node and transfer the textarea content to it
text_node ='text')
text_content ='div#demo textarea')
// use the selected rect element as the bounds
bounds ='rect').node()
// get current padding value, or default to 0
padding = parseInt('input#padding').property('value'), 10) || 0
// wrap text to the rectangle in the same group
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment