Angular.js - 从Controller添加元素

时间:2014-04-03 04:56:20

标签: angularjs svg angularjs-directive angularjs-scope

我是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时遇到了麻烦。我欢迎所有建议/反馈。谢谢!

2 个答案:

答案 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添加和删除类等。