Example of using AngularJS to render text into SVG shapes
Makes use of directive controllers to customize behavior per shape.
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>AngularJS to render text into SVG Shapes</title> | |
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> | |
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0-rc.2/angular.min.js"></script> | |
<script type="text/javascript"> | |
angular.module('myMod', []) | |
.directive('myText', function () { | |
return { | |
controller: function myTextController() { | |
this.$render = angular.noop; | |
}, | |
link: function (scope, iElement, iAttrs, ctrl) { | |
var d3Element = d3.select(iElement[0].parentNode); | |
var bbox = iElement[0].getBBox(); | |
var text = d3Element.append('text') | |
.attr('font-size', 16) | |
.attr('font-family', 'Arial') | |
.attr('x', bbox.x) | |
.attr('y', bbox.y); | |
iAttrs.$observe('myText', function (val) { | |
text.text(val); | |
var bbox = text.node().getBBox(); | |
ctrl.$render(text, bbox); | |
}); | |
} | |
}; | |
}) | |
.directive('rect', function () { | |
return { | |
restrict: 'E', | |
require: '?myText', | |
link: function (scope, iElement, iAttrs, textCtrl) { | |
if (textCtrl) { | |
var x = +iAttrs['x'], y = +iAttrs['y']; | |
textCtrl.$render = function (d3text, bbox) { | |
d3text | |
.attr('x', x) | |
.attr('y', y + bbox.height); | |
iElement | |
.attr('width', bbox.width) | |
.attr('height', bbox.height + 5); | |
} | |
} | |
} | |
}; | |
}) | |
.directive('circle', function () { | |
return { | |
restrict: 'E', | |
require: '?myText', | |
link: function (scope, iElement, iAttrs, textCtrl) { | |
if (textCtrl) { | |
var x = +iAttrs.cx, y = +iAttrs.cy; | |
textCtrl.$render = function (d3text, bbox) { | |
d3text | |
.attr('x', x - bbox.width / 2) | |
.attr('y', y + 5); | |
iElement | |
.attr('r', bbox.width / 2 + 5); | |
} | |
} | |
} | |
}; | |
}) | |
.directive('myTriangle', function () { | |
var line = d3.svg.line() | |
.x(function(d) { return d.x; }) | |
.y(function(d) { return d.y; }); | |
function points(x, y, width) { | |
return [ | |
{x: x, y: y}, | |
{x: x + width*2, y: y}, | |
{x: x + width*1, y: y + width*2}, | |
] | |
} | |
return { | |
priority: 1000, | |
restrict: 'E', | |
require: '?myText', | |
compile: function (tElement, tAttrs, transclude) { | |
var parent = d3.select(tElement[0].parentNode); | |
var path = parent.append('path') | |
.attr('d', line(points(+tAttrs.x, +tAttrs.y, 10))) | |
.attr('transform', 'rotate(45,' + tAttrs.x + ',' + tAttrs.y + ')'); | |
tElement.replaceWith(path[0]); | |
angular.forEach(tAttrs.$attr, function (attr, normAttr) { | |
path.attr(attr, tAttrs[normAttr]); | |
}); | |
return function (scope, iElement, iAttrs, textCtrl) { | |
if (textCtrl) { | |
var x = +iAttrs.x, y = +iAttrs.y; | |
textCtrl.$render = function (d3text, bbox) { | |
d3text | |
.attr('x', x) | |
.attr('y', y+bbox.height) | |
.attr('transform', 'rotate(45,' + x + ',' + y + ')'); | |
iElement | |
.attr('d', line(points(+tAttrs.x - 10, +tAttrs.y, bbox.width / 2 + 10))); | |
} | |
} | |
}; | |
} | |
}; | |
}) | |
; | |
function myCtrl($scope) { | |
$scope.obj = { | |
someText: "Type in here!" | |
}; | |
} | |
</script> | |
</head> | |
<body> | |
<div ng-app="myMod" ng-controller="myCtrl"> | |
<div> | |
<input type="text" ng-model="obj.someText" /> | |
</div> | |
<svg width="500" height="200"> | |
<circle cx="50" cy="50" r="10" fill="green" my-text="{{obj.someText}}"/> | |
<rect x="100" y="20" height="50" rx="5" ry="5" width="50" fill="aqua" my-text="{{obj.someText}}"/> | |
<my-triangle x="50" y="70" my-text="{{obj.someText}}" fill="orange" /> | |
</svg> | |
</div> | |
</body> | |
</html> |