如何让 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() 在 jqLite 中不可用 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-viewBox
、ng-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标志,所以如果内插字符串中的任何表达式导致未定义,则属性被删除并且未添加到元素
我正在尝试获取 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() 在 jqLite 中不可用 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-viewBox
、ng-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标志,所以如果内插字符串中的任何表达式导致未定义,则属性被删除并且未添加到元素