如何让 AngularJS 在 svg 模板中填充初始标签值?

How to get AngularJS to fill initial tag value in svg template?

我正在尝试获取 AngularJS 指令来设置 svg 标签中的各种属性。

angular.module("complexNumbers")
.directive("cartesianPlane", function() {
  return {
    restrict: "E",
    scope: { },
    templateUrl: "shared/cartesianPlane/cartesianPlaneView.html",
    controller: function($scope) {
      $scope.viewBox = {
        x : -20,
        y : -20,
        width : 40,
        height : 40,

        value : function() {
            return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height;
        }
      };
    },
    link: function($scope, $elem) {
      // Then adjust for aspect ratio
      var aspectRatio = $elem.height() / elem.width();
      $scope.viewBox.height = $scope.viewBox.width * aspectRatio;  
    }
  };
});
<!-- cartesianPlaneView.html -->

<svg width='100%' height='100%' viewBox='{{viewBox.value()}}' style='position:relative; top:0px; left:0px; float:left;'>
<line class='axis' x1='{{viewBox.x}}' y1='0'  x2='{{viewBox.x + viewBox.width}}' y2='0'></line>
<line class='axis' x1='0' y1='{{viewBox.y}}' x2='0' y2='{{viewBox.y + viewBox.height}}'></line>

这个方法有两个问题:

1) AngularJS 似乎从 templateUrl 呈现标签,但最初没有插入值。因此浏览器抱怨:

Error: Invalid value for <svg> attribute viewBox="{{viewBox.value()}}"
Error: Invalid value for <line> attribute y1="{{viewBox.y}}"
Error: Invalid value for <line> attribute y2="{{viewBox.y + viewBox.height}}"
Error: Invalid value for <line> attribute x1="{{viewBox.x}}"
Error: Invalid value for <line> attribute x2="{{viewBox.x + viewBox.width}}"

我还以为渲染模板时,$scope 的初始值会立即插入?相反,模板 {{}} 标签按原样进入。

2) link 函数的 $elem 参数没有 width() 和 height() 属性。这些何时可用?我如何计算和设置 aspectRatio?

Error: TypeError: $elem.height() is not a function

第 2 点的答案你没有加载 jQuery,height() 在 jqLit​​e 中不可用 https://docs.angularjs.org/api/ng/function/angular.element#angular-s-jqlite

1.) 创建自定义 svg 指令,例如 example-svg,这样浏览器就不会将其解释为 SVG

2.) 在 link 方法中手动构建 svg 元素并在 dom 中替换它,这样当浏览器检测到 SVG 元素时,它将具有正确的属性值。

 app.directive('exampleSvg' , function() {
 return {
   scope : {
    viewBox : '='
   },
   restrict : 'E',
   link : function(scope,element) {
    element.replaceWith('<svg viewBox="' + scope.viewBox + '"></svg>');
    $compile(element)(scope);
 }
});

模板

<example-svg viewBox="viewBox.value()"></example-svg>

初始加载范围未被替换,它在下一个摘要中被替换,因此对于 angular 浏览器的 1 $digest 将看不到内插范围,您在 chrome 检查器中看到它,因为您在摘要后看到 DOM,因此插值完成。

我相信对于问题 #1,您会想要使用 ng-attr。因此,在您的指令中,您将使用 ng-attr-viewBoxng-attr-x 等...

至于你的第二个问题,.height()应该在那里可用,并且应该由 JQLite

提供

关于问题

Error: Invalid value for <line> attribute x1="{{viewBox.x1}}"
Error: Invalid value for <line> attribute y1="{{viewBox.y1}}"

您可以将 x1 和 y1 替换为 ng-attr-x1 & ng-attr-y1

有关详细信息,请阅读 here

当使用ngAttr时,使用$interpolate的allOrNothing标志,所以如果内插字符串中的任何表达式导致未定义,则属性被删除并且未添加到元素