Skip to content

Instantly share code, notes, and snippets.

@chrisirhc
Last active June 2, 2016 14:33
Show Gist options
  • Save chrisirhc/6587467 to your computer and use it in GitHub Desktop.
Save chrisirhc/6587467 to your computer and use it in GitHub Desktop.
Example of using AngularJS to render text into SVG shapes

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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment