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> |