Как преобразовать холст в угловую директиву

0

Можете ли вы помочь мне интегрировать этот код в угловую директиву?.
Я пробовал, но получаю много ошибок, например: element[0].getContext is not a function.

Я много пробовал...
попробуйте вызвать getcontext в элементе шаблона, подобном этому
var circle = angular.element (элемент [0].querySelector('. xxxClass'));
var ctx = circle.getContext('2d');

Вот код.

var app = angular.module('xxx', []);
app.controller('xxxCtrl', function () {});
app.directive('xxxItem', function () {
        var linked = function(scope, element) {
            var circle = angular.element(element[0].querySelector('.xxxClass'));


            var options = {
                size: 125,
                percent: circle.percent || 50,
                timer: circle.timer || 100,
                max: circle.timer || 100,
                lineColor: circle.lineColor || "red",
                timerColor: circle.timerColor || "green",
                lineWidth: 3,
                rotate: 0
            };

            var canvas = angular.element('<canvas></canvas>');
            var span = angular.element('<span></span>');

            if (typeof(G_vmlCanvasManager) !== 'undefined') {
                G_vmlCanvasManager.initElement(canvas);
            }

            circle.appendTo(span);
            circle.appendTo(canvas);

            var ctx = element[0].getContext('2d');
            canvas.width = canvas.height = options.size;


            var circleMargin = 10;
            var radius = (options.size - options.lineWidth - circleMargin) / 2;
            var to_rad = Math.PI / 180;
            var drawCircle = function(color, lineWidth, percent) {
                ctx.save();
                ctx.translate(options.size / 2, options.size / 2);
                ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI);
                percent = Math.min(Math.max(0, percent || 1), 1);
                ctx.beginPath();
                ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, false);
                ctx.strokeStyle = color;
                ctx.lineCap = 'round';
                ctx.lineWidth = lineWidth;
                ctx.stroke();
                ctx.restore();
            };

            function drawArrow(color, percent) {
                percent = Math.min(Math.max(0, percent || 1), 1);
                if (percent == 1) return;
                ctx.save();
                ctx.fillStyle = color;
                ctx.translate(options.size / 2, options.size / 2);
                ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI);
                ctx.beginPath();
                ctx.rotate(Math.PI * 2 * percent);

                var arrowWidth = 10;
                var arrowHeight = 8;

                ctx.moveTo(radius - (arrowWidth / 2), 0);
                ctx.lineTo(radius + (arrowWidth / 2), 0);
                ctx.lineTo(radius, arrowHeight);
                ctx.lineTo(radius - (arrowWidth / 2), 0);
                ctx.fill();
                ctx.restore();
            }

            function drawTicks(color, seconds) {
                var to_rad = Math.PI / 180;
                ctx.save();
                ctx.translate(options.size / 2, options.size / 2);
                ctx.rotate(-90 * to_rad);
                ctx.lineWidth = 1;
                ctx.strokeStyle = color;

                var angle = 360 / 60;
                var tickSize = 14;
                var tickMargin = 8;

                var stepTime = angle*seconds/options.max*10;
                for (var i = 0; i <= stepTime; i++) {
                    ctx.save();
                    ctx.rotate((360-(i * angle)) * to_rad);
                    ctx.beginPath();
                    ctx.moveTo(radius - tickSize - tickMargin, 0);
                    ctx.lineTo(radius - tickMargin, 0);
                    ctx.stroke();
                    ctx.restore();
                }
                ctx.restore();
            }

            function render() {
                ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
                --options.timer;
                if(options.timer < 0 ){options.timer = options.max}
                var seconds = options.timer;
                var size = -(options.timer - ((options.max / options.timer) * seconds)) ;

                drawCircle(options.lineColor, options.lineWidth, options.percent / 100);
                drawArrow(options.lineColor, options.percent / 100);
                drawTicks(options.timerColor, size);
                span.innerHTML = "<b>" + seconds + "</b>" + "<br/>" + "seconds";
                setTimeout(render, 1000);
            }
            render();
        };

        return {
            restrict: "E",
            scope: {
                percent: "@",
                timer: "=timer",
                lineColor: "@",
                timerColor: "@"
            },
            link: linked,
            template:
            '<div class="xxxClass" percent="percent" timer="timer" lineColor="lineColor" timerColor="timerColor"></div>'
        };
    });
div {
  position: relative;
  margin: 80px;
  width: 220px;
  height: 220px;
}
canvas {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
}
span {
    color: #555;
    display: block;
    line-height: 16px;
    padding-top: 90px;
    text-align: center;
    width: 220px;
    font-family: sans-serif;
    font-size: 25px;
    font-weight: 100;
    margin-left: 5px;
}
input {
  width: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0-beta.1/angular.min.js"></script>
<div ng-app="xxx">
    <div ng-controller="xxxCtrl">
        <xxx-item percent="80" timer="100" lineColor="red" data-timerColor="green"></xxx-item>
        <xxx-item percent="50" timer="50" lineColor="blue" data-timerColor="red"></xxx-item>
    </div>
</div>
  • 0
    Какие конкретные проблемы вы пытаетесь решить, не могли бы вы дать более подробную информацию?
  • 0
    Вы даже пытались реализовать директиву? Я не могу найти ничего в Codepen, кроме вашего ванильного кода JS.
Показать ещё 5 комментариев
Теги:
canvas

1 ответ

0

Вы просто немного смущены, где должен быть элемент, и где должен быть холст.

Итак, во-первых, circle в вашем коде относится к элементу класса xxxClass css, а в вашем коде:

<div class="xxxClass" percent="percent" timer="timer" lineColor="lineColor" timerColor="timerColor"></div>

таким образом, вы у вас есть jqLite элемент circle, но jqLite, не имеет appendTo метод, так что кажется, вы имеете в виду append

Затем element - этот элемент jqLite, где применяется директива, поэтому вы в своем случае

<xxx-item percent="80" timer="100" lineColor="red" data-timerColor="green"></xxx-item>

а также

<xxx-item percent="50" timer="50" lineColor="blue" data-timerColor="red"></xxx-item>

поэтому, это не canvas а также не имеет .getContext.

поэтому вам просто нужно немного изменить свой код, и вы можете получить что-то вроде этого:

var app = angular.module('xxx', []);
app.controller('xxxCtrl', function() {});
app.directive('xxxItem', function() {
  var linked = function(scope, element) {
    var circle = angular.element(element[0].querySelector('.xxxClass'));

    console.log(circle, element[0]);

    var options = {
      size: 125,
      percent: scope.percent || 50,
      timer: scope.timer || 100,
      max: scope.timer || 100,
      lineColor: scope.lineColor || "red",
      timerColor: scope.timerColor || "green",
      lineWidth: 3,
      rotate: 0
    };

    var canvas = angular.element('<canvas></canvas>');
    var span = angular.element('<span></span>');

    if (typeof(G_vmlCanvasManager) !== 'undefined') {
      G_vmlCanvasManager.initElement(canvas);
    }

    circle.append(span);
    circle.append(canvas);

    var ctx = canvas[0].getContext('2d');
    canvas[0].width = canvas[0].height = options.size;


    var circleMargin = 10;
    var radius = (options.size - options.lineWidth - circleMargin) / 2;
    var to_rad = Math.PI / 180;
    var drawCircle = function(color, lineWidth, percent) {
      ctx.save();
      ctx.translate(options.size / 2, options.size / 2);
      ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI);
      percent = Math.min(Math.max(0, percent || 1), 1);
      ctx.beginPath();
      ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, false);
      ctx.strokeStyle = color;
      ctx.lineCap = 'round';
      ctx.lineWidth = lineWidth;
      ctx.stroke();
      ctx.restore();
    };

    function drawArrow(color, percent) {
      percent = Math.min(Math.max(0, percent || 1), 1);
      if (percent == 1) return;
      ctx.save();
      ctx.fillStyle = color;
      ctx.translate(options.size / 2, options.size / 2);
      ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI);
      ctx.beginPath();
      ctx.rotate(Math.PI * 2 * percent);

      var arrowWidth = 10;
      var arrowHeight = 8;

      ctx.moveTo(radius - (arrowWidth / 2), 0);
      ctx.lineTo(radius + (arrowWidth / 2), 0);
      ctx.lineTo(radius, arrowHeight);
      ctx.lineTo(radius - (arrowWidth / 2), 0);
      ctx.fill();
      ctx.restore();
    }

    function drawTicks(color, seconds) {
      var to_rad = Math.PI / 180;
      ctx.save();
      ctx.translate(options.size / 2, options.size / 2);
      ctx.rotate(-90 * to_rad);
      ctx.lineWidth = 1;
      ctx.strokeStyle = color;

      var angle = 360 / 60;
      var tickSize = 14;
      var tickMargin = 8;

      var stepTime = angle * seconds / options.max * 10;
      for (var i = 0; i <= stepTime; i++) {
        ctx.save();
        ctx.rotate((360 - (i * angle)) * to_rad);
        ctx.beginPath();
        ctx.moveTo(radius - tickSize - tickMargin, 0);
        ctx.lineTo(radius - tickMargin, 0);
        ctx.stroke();
        ctx.restore();
      }
      ctx.restore();
    }

    function render() {
      ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
      --options.timer;
      if (options.timer < 0) {
        options.timer = options.max
      }
      var seconds = options.timer;
      var size = -(options.timer - ((options.max / options.timer) * seconds));

      drawCircle(options.lineColor, options.lineWidth, options.percent / 100);
      drawArrow(options.lineColor, options.percent / 100);
      drawTicks(options.timerColor, size);
      span.html("<b>" + seconds + "</b>" + "<br/>" + "seconds");
      setTimeout(render, 1000);
    }
    render();
  };

  return {
    restrict: "E",
    scope: {
      percent: "@",
      timer: "=timer",
      lineColor: "@",
      timerColor: "@"
    },
    link: linked,
    template: '<div class="xxxClass" percent="percent" timer="timer" lineColor="lineColor" timerColor="timerColor"></div>'
  };
});
/* Styles go here */

canvas {
  display: block;
  position: relative;
  top: 0;
  left: 0;
}
span {
  color: #555;
  display: block;
  line-height: 12px;
  padding-top: 42px;
  text-align: center;
  width: 108px;
  font-family: sans-serif;
  font-size: 10px;
  text-transform: uppercase;
}
span b {
  font-size: 17px;
}
<script data-require="[email protected]" data-semver="1.4.7" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
<div ng-app="xxx">
  <div ng-controller="xxxCtrl">
    <xxx-item percent="80" timer="100" linecolor="red" data-timercolor="green"></xxx-item>
    <xxx-item percent="50" timer="50" linecolor="blue" data-timercolor="red"></xxx-item>
  </div>
</div>

Ещё вопросы

Сообщество Overcoder
Наверх
Меню