【问题标题】:Angular.js - Appending Element From ControllerAngular.js - 从控制器附加元素
【发布时间】:2014-04-04 01:00:29
【问题描述】:

我是 Angular 的新手,所以如果我的方法不是惯用的,我提前道歉。我试图在控制器中找到的placeShot() 函数中附加一个<circle> 元素,该函数是从ng-click='placeShot($event) 调用的。

我目前还在ng-init 内硬编码#basketball-container 的宽度。由于我的页面是响应式的,我想获取这个元素的宽度(在不同的设备上会有所不同),然后根据这个值创建<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/

我最初的问题是:如何在 placeShot() 函数中附加 &lt;circle&gt; 元素?但我很高兴听到我应该如何重组我的代码以更符合 Angular 最佳实践。

基本上,我有一个响应式页面,所以我想获取&lt;svg&gt; 的父元素的宽度,然后允许该值驱动它的大小。我还想让用户点击球场,在球场上一个新的&lt;circle&gt; 元素将标记这项运动。这似乎是一项简单的任务,但我在使用 Angular 时遇到了麻烦。我欢迎所有建议/反馈。谢谢!

【问题讨论】:

    标签: angularjs svg angularjs-directive angularjs-scope


    【解决方案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();
        });
     });
    

    我不知道那是多么有棱角,但它会起作用。

    【讨论】:

    • 这种方法更有意义。您如何建议我使用其父元素的宽度创建 (和相应的形状)?
    【解决方案2】:

    Angular 的一般规则是永远不要从控制器进行 DOM 操作。所有的 DOM 操作都应该发生在一个指令中。因此,您要避免在控制器方法中添加元素。

    您应该改为在控制器中操作 $scope 并让指令相应地更新 DOM。如果设置正确,DOM 操作将在 Angular 运行摘要循环时自动发生。这就是棱角分明的美。使用指令,您不必编写实际操作 DOM 的代码。您更改模型,视图就会更新。这是一个简单的例子......

    myApp.controller('BasketballCtrl', function ($scope) {
        $scope.ballIsVisible = false;
    
        $scope.placeShot = function (event) {
            $scope.ballIsVisible = true;
        }
    }
    
    <circle ng-if="ballIsVisible" />
    

    Angular 会持续 $watch 的 ballIsVisible 值,当它为 true 时它会将圆圈添加到页面中,当它为 false 时将其删除。您可以使用内置指令执行任何操作,或者编写您自己的指令。 ng-if 添加/删除元素,ng-show 隐藏和显示它,ng-class 添加和删除类等。

    【讨论】:

      猜你喜欢
      • 2013-02-23
      • 1970-01-01
      • 2014-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-12
      • 2015-12-06
      相关资源
      最近更新 更多