简体   繁体   中英

Build dynamic rectangle with Angular directive

Recently I have written a project with D3, so I need a dynamic rectangle. I used Angular to create a dynamic visualization.I have two input type rang , the first one will change the 'width' of rectangle and the second will change the 'height'.However I don't know how to use angular to draw a dynamic rectangle. This is my code:

<div ng-app="myApp"> 
   <rect-designer/>
   <div>
     <input type="range"  ng-model="rectWidth" min="0" max="400" value="0"/>
     <input type="range" ng-model="rectHeight" min="0" max="700" value="0"/>
   </div>
</div>

Here is my JavaScript code:

var App = angular.module('myApp', []);
App.directive('rectDesigner', function() {
    function link(scope, el, attr) {

 var svgwidth=1000, svgheight=600;
 var svgContainer = d3.select(el[0]).append('svg').attr('id','svgcontainer')
      .attr({ width: svgwidth, height: svgheight });

 scope.$watchGroup(['rectWidth','rectHeight'], function () {

      svgContainer.append("rect").attr("id", "Rect")
       .attr({ width: rectWidth, height: rectHeigh })
       .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')')


   },true);
  }return {

   link: link,
   scope: {
       rectHeigh: '=',
       rectWidth: '=',

   },
   restrict: 'E'
 };
}); 

I don't know if there is any way to make svgWidth and svgheight dynamic, I used this code but the result was undefined .

   scope.$watch(function(){
           svgWidth = el.clientWidth;
           svgHeight = el.clientHeight;
    });

You are missing some basics here:

  1. You don't have a controller.
  2. The variables you are watching are not part of your directive but they should be part of that missing controller.
  3. Since these variables aren't part of the directive, there's no need to return them into it's scope (again, they will be in the controller).
  4. $scope.watchGroup has a callback with a function of newValues . This is where the changed variables will be.
  5. You want to append the rect to the svg and then manipulate it's width/height. You don't want to re-append it each time the width/height changes.

So putting all this together:

var App = angular.module('myApp', []);

var Ctrl = App.controller('myCtrl', ['$scope', function($scope) {

  // I always like to give them defaults in code
  $scope.rectWidth = 50;
  $scope.rectHeight = 50;

}]);

Ctrl.directive('rectDesigner', function() {

  function link(scope, el, attr) {

    var svgwidth = 500,
      svgheight = 600;

    var svgContainer = d3.select(el[0])
      .append('svg')
      .attr('id', 'svgcontainer')
      .attr({
        width: svgwidth,
        height: svgheight
      });
    // only append one rect
    var rect = svgContainer
      .append("rect")
      .attr("id", "Rect")
      .attr('transform', 'translate(' + svgwidth / 2 + ',' + svgheight / 2 + ')');

    scope.$watchGroup(['rectWidth', 'rectHeight'], function(newValues) {

      var width = newValues[0];
      var height = newValues[1];

      // now change it's width and height
      rect.attr({
        width: width,
        height: height
      });

    }, true);
  }
  return {
    link: link,
  };
});

Example here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM