我是Angular的新手,所以如果我的方法不是惯用的,我会提前道歉。我正在尝试在控制器中找到的<circle>
函数中附加placeShot()
元素,该函数从ng-click='placeShot($event)
调用。
我目前还在#basketball-container
内对ng-init
的宽度进行硬编码。由于我的页面是响应式的,我想抓住这个元素的宽度(在各种设备上会有所不同),然后根据这个值创建<svg>
#basketball-court。
HTML
<div ng-app="myApp">
<div id="basketball-container" ng-controller="BasketballCtrl" ng-init="width=400; height=width*0.75">
<h3>Width: {{width}}, Height: {{height}} - Hardcoded</h3>
<svg id="basketball-court" ng-attr-height="{{height}}" ng-attr-width="{{width}}" ng-click="placeShot($event)">
<!-- Boundary -->
<line x1="0" y1="0" x2="0" y2="{{height}}" class="boundary" />
<line x1="0" y1="0" x2="{{width}}" y2="0" class="boundary" />
<line x1="0" y1="{{height}}" x2="{{width}}" y2="{{height}}" class="boundary" />
<line x1="{{width}}" y1="0" x2="{{width}}" y2="{{height}}" class="boundary" />
<!-- 3 Pt Arc -->
<path d="M {{0.11*width}} 0 V {{0.1*height}}" />
<path d="M {{0.89*width}} 0 V {{0.1*height}}" />
<path d="M {{0.11*width}} {{0.1*height}} C {{0.11*width}} {{height}}, {{0.89*width}} {{height}}, {{0.89*width}} {{0.1*height}}" fill="transparent"/>
<!-- Key Outline -->
<path d="M {{0.35*width}} 0 v {{0.57*height}} h {{0.3*width}} v -{{0.57*height}}" fill="transparent"/>
<!-- Top of Key -->
<circle cx="{{width/2}}" cy="{{0.57*height}}" r="{{0.15*width}}" fill="transparent" />
<!-- Backboard -->
<path d="M {{0.41*width}} {{0.033*height}} h {{0.18*width}}" />
<!-- Basket -->
<circle cx="{{width/2}}" cy="{{0.08*height}}" r="{{0.03*width}}" fill="transparent" />
</svg>
</div>
</div>
角
var myApp = angular.module('myApp',[]);
myApp.controller('BasketballCtrl', ['$scope', '$element', function($scope, $element) {
$scope.placeShot = function(event) {
var x = event.offsetX;
var y = event.offsetY
console.log($element);
console.log(x);
console.log(y);
var html = '<circle cx="'+ x.toString() +'" cy="'+ y.toString() +'" r="10" class="shot" />';
console.log(html);
// Append shot to <svg>
$("#basketball-court").append(html);
};
}]);
这是JSFiddle的链接:http://jsfiddle.net/Abundnce10/426LX/6/
我原来的问题是:如何在<circle>
函数中附加placeShot()
元素?但我很高兴听到我应该如何重构我的代码,使其更符合Angular最佳实践。
基本上,我有一个响应的页面,所以我想抓住<svg>
的父元素的宽度,然后允许该值来驱动它的大小。我还想让用户点击球场,新的<circle>
元素将标记该项运动。这似乎是一项简单的任务,但我在使用Angular时遇到了麻烦。我欢迎所有建议/反馈。谢谢!
答案 0 :(得分:1)
为了记录,要在js中创建圆圈,通常会这样做:
var circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
circle.setAttribute("cx",x);
circle.setAttribute("cy",y);
circle.setAttribute("r",10);
circle.setAttribute("class","shot");
document.getElementById('basketball-court').appendChild(circle);
使用angular,我们可以为html执行此操作:
<circle class="shot" ng-repeat="circle in circles"
ng-attr-cx="{{circle.x}}"
ng-attr-cy="{{circle.y}}"
ng-attr-r= "{{circle.r}}">
</circle>
然后为你的控制器:
$scope.circles = [];
$scope.placeShot = function(event) {
$scope.circles.push({'x': event.offsetX, 'y': event.offsetY, 'r':10});
};
实际上,在任何一个svg元素中都有一个带有角度变量的属性(比如cx={{whatever}}
),你需要在属性(ng-attr-
)之前添加ng-attr-cx
或者你会在控制台中出现大量错误,它在某些浏览器上无效。
要设置高度和宽度,您可以在控制器中执行以下操作:
$scope.width = $('#basketball-container').width();
$scope.height = $('#basketball-container').height();
如果您需要在窗口更改时调整其大小,可以执行
$(window).on('resize', function() {
$scope.$apply(function() {
$scope.width = $('#basketball-container').width();
$scope.height = $('#basketball-container').height();
});
});
我不知道它是多么棱角分明,但它会起作用。
答案 1 :(得分:0)
Angular中的一般规则是永远不要从控制器执行DOM操作。所有DOM操作都应该在指令中进行。因此,您希望避免在控制器方法中添加元素。
您应该操作控制器中的$ scope,并让指令相应地更新DOM。如果正确设置,当角度运行摘要周期时,DOM操作将自动发生。这是棱角分明的美。使用指令,您不必编写实际操作DOM的代码。您更改模型,视图只是更新。这是一个简单的例子......
myApp.controller('BasketballCtrl', function ($scope) {
$scope.ballIsVisible = false;
$scope.placeShot = function (event) {
$scope.ballIsVisible = true;
}
}
<circle ng-if="ballIsVisible" />
Angular将持续$观察ballIsVisible的值,它会在页面上添加圆圈时将其添加到页面,并在其为false时将其删除。您可以使用内置指令执行任何操作,也可以编写自己的指令。 ng-if添加/删除元素,ng-show隐藏并显示它,ng-class添加和删除类等。