A demo for the circle-text plugin, which can place text aligned along the bottom of circles.
Last active
December 15, 2015 14:59
-
-
Save musically-ut/5278601 to your computer and use it in GitHub Desktop.
The circle-text plugin.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*globals d3*/ | |
(function () { | |
d3.circleText = function () { | |
"use strict"; | |
var radius = function (d) { return d.r; }, | |
value = function (d) { return d.value; }, | |
fontSize = '100%', | |
method = "stretch", spacing = "auto", | |
position = "50%", precision = null; | |
function _draw(selection) { | |
selection.each(function (d, i) { | |
var g = d3.select(this); | |
// Reuse the old id, if present. Otherwise, generate a unique id | |
// for the path. | |
var oldPath = g.select('path.arc-path'); | |
var arcId = (oldPath.node() && oldPath.attr('id')) || | |
'id-' + guid(); | |
g.selectAll('path.arc-path') | |
.data([d]) | |
.enter() | |
.append('path') | |
.classed('arc-path', true) | |
.attr('id', arcId) | |
.attr('d', function (d) { return circle_d(radius(d)); }); | |
d3.transition(g.select('path.arc-path')) | |
.attr('d', function (d) { return circle_d(radius(d)); }); | |
var arcText = g.selectAll('text.arc-text').data([d]); | |
arcText.enter() | |
.append('text') | |
.classed('arc-text', true) | |
.attr('text-anchor', 'middle') | |
.append('textPath'); | |
// Not transitioning the `font-size` style since getComptedStyles | |
// for it may not return the actual value which was set in CSS, | |
// e.g., "font-size: 100%" may return "16px" when the font-size | |
// is requested via getComptedStyles. Hence, the font-size will | |
// be unnecessarily transitioned. | |
// Also see: http://stackoverflow.com/a/10145250/987185 | |
arcText.style('font-size', fontSize); | |
/* There is a bug in Chrome which makes it impossible to select | |
* camel case tags, like textPath. Hence, using the :first-child | |
* selector to select the embedded textPath element. | |
* | |
* https://github.com/mbostock/d3/issues/925 | |
* https://bugs.webkit.org/show_bug.cgi?id=46800 | |
* https://bugs.webkit.org/show_bug.cgi?id=83438 | |
* | |
* Keep the textPath hidden until the best position | |
* has been found. | |
*/ | |
d3.transition(arcText.select(':first-child')) | |
.attr('xlink:href', '#' + arcId) | |
.attr('method', method) | |
.attr('spacing', spacing) | |
.text(value) | |
.attr('startOffset', position); | |
}); | |
return selection.selectAll('text.arc-text'); | |
} | |
/*************************************** | |
* Private functions | |
*/ | |
/* Code for generating UUID version 4 from: | |
* http://note19.com/2007/05/27/javascript-guid-generator/ | |
*/ | |
function s4() { | |
return Math.floor((1 + Math.random()) * 0x10000) | |
.toString(16) | |
.substring(1); | |
} | |
function guid() { | |
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + | |
s4() + '-' + s4() + s4() + s4(); | |
} | |
function circle_d(r) { | |
return [ "M0,0", | |
"m", "0,", -r, | |
"a", r, ",", r, " 0 1,0 0,", 2*r, | |
"a", r, ",", r, " 0 1,0 0,", -2*r | |
].join(''); | |
} | |
/*************************************** | |
* Public properties | |
*/ | |
_draw.radius = function (_) { | |
if (arguments.length === 0) return radius; | |
radius = d3.functor(_); | |
return _draw; | |
}; | |
_draw.value = function (_) { | |
if (arguments.length === 0) return value; | |
value = d3.functor(_); | |
return _draw; | |
}; | |
_draw.precision = function (_) { | |
try { | |
console.warn('circleText.precision has been deprecated.'); | |
} catch (e) { | |
// Ignore if the warning could not be displayed. | |
} | |
if (arguments.length === 0) return precision; | |
precision = _; | |
return _draw; | |
}; | |
_draw.fontSize = function (_) { | |
if (arguments.length === 0) return fontSize; | |
fontSize = d3.functor(_); | |
return _draw; | |
}; | |
_draw.method = function (_) { | |
if (arguments.length === 0) return method; | |
method = _; | |
return _draw; | |
}; | |
_draw.spacing = function (_) { | |
if (arguments.length === 0) return spacing; | |
spacing = _; | |
return _draw; | |
}; | |
_draw.position = function (_) { | |
if (arguments.length === 0) return position; | |
position = _; | |
return _draw; | |
}; | |
return _draw; | |
}; | |
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Circle text</title> | |
<meta charset="utf-8"> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> | |
<script src="circle-text.js"></script> | |
<style> | |
#container { | |
margin: auto; | |
width: 800px; | |
} | |
svg { | |
width: 100%; | |
min-height: 600px; | |
} | |
.arc-path { | |
visibility: hidden; | |
} | |
circle { | |
stroke: none; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="container"></div> | |
<script> | |
var circles = [ | |
{ | |
cx: 200, | |
cy: 300, | |
r: 20, | |
text: 'A' | |
}, | |
{ | |
cx: 400, | |
cy: 300, | |
r: 50, | |
text: 'plugin' | |
}, | |
{ | |
cx: 600, | |
cy: 300, | |
r: 100, | |
text: 'for text inside circles!' | |
} | |
]; | |
var svg = d3.select('#container') | |
.append('svg'), | |
colors = d3.scale.category10(); | |
var circleText = d3.circleText() | |
.radius(function (d) { return d.r - 5; }) | |
.value(function (d) { return d.text; }) | |
.precision(0.1); | |
var gs = svg.selectAll('g') | |
.data(circles) | |
.enter() | |
.append('g') | |
.attr('transform', function (d) { | |
return 'translate(' + d.cx + ',' + d.cy + ')'; | |
}); | |
gs.append('circle') | |
.attr('cx', 0).attr('cy', 0) | |
.attr('r', function (d) { return d.r; }) | |
.attr('fill', function (d, i) { return colors(i); }) | |
.attr('fill-opacity', '0.3'); | |
var texts = gs.call(circleText); | |
texts | |
.attr('stroke', 'none') | |
.attr('fill', function (d, i) { return colors(i); }); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment