html canvas中的内容应该是响应式的

时间:2015-01-25 14:11:25

标签: html css angularjs

我有html画布。每个内部都是一个计数盒,每个候选人的投票数量产生了计数盒的数量。当投票低于50时,计数框完全显示在画布内,但当投票超过100时,其他计数框就丢失了。它们都是水平显示的。我现在想要的是显示画布内的所有标签框。我添加了一个最大宽度的css:“100%”,我认为这样可以解决问题,但不能。我应该怎么做呢?任何建议将不胜感激。提前致谢

这是我的代码如下。特别感谢Shomz。

var tb = angular.module("tb", []);
tb.controller("tallyboxController", function($scope) {
  'use strict';

  $scope.label = {
    table: {
      cName: "Candidate's Name",
      cVote: 'Vote',
      cTB: 'Tally Boxes',
      cNV: 'No of votes',
      period: '.'
    },
  };

  $scope.presidents = [{
    no: '1',
    name: 'Jeoanna Lingh',
    votes: 1223,
  },{
    no: '2',
    name: 'Jewel Miller',
    votes: 1234,
  },{
    no: '3',
    name: 'Shin Lee',
    votes: 1001,
  }];

  $scope.candidates = [
    $scope.presidents,
    $scope.vicepresidents
  ];

});


var tb = angular.module('tb');

tb.directive('drawing', function() {
  return {
    restrict: 'A',
    scope: {
      candidate: '='
    },
    link: function(scope, element, attrs) {

        var colors = ['Red', 'Green', 'Blue', 'Yellow','black'];

        scope.$watch("candidate.votes", function(newValue, oldValue) {
          console.log('rendering', newValue);
          render();
        });

        function render() {
          var votes = scope.candidate.votes;
          var ctx = element[0].getContext('2d');
          var remainder = 0;
          var oneBox = 0;
          
          // clear canvas (needed for subtracting votes)
          // and is a good practice anyway
          element[0].width = element[0].width;

          if (votes > 4) {
            if (remainder = votes % 5) {
              oneBox = (votes - remainder) / 5;
            }
            else {
              oneBox = votes / 5;
            }
          } else {
            remainder = votes;
          }
          
          drawOneBox();          

          function drawOneBox() {
            ;
            for (var i = 0; i < oneBox; i++) {
              
              var color = colors[Math.floor(i/5)];

              ctx.beginPath();
              ctx.moveTo(5 + i * 25, 5);
              ctx.lineTo(25 + i * 25, 5);

              ctx.moveTo(5 + i * 25, 5);
              ctx.lineTo(5 + i * 25, 25);

              ctx.moveTo(25 + i * 25, 5);
              ctx.lineTo(25 + i * 25, 25);

              ctx.moveTo(5 + i * 25, 5);
              ctx.lineTo(25 + i * 25, 25);

              ctx.moveTo(25 + i * 25, 25);
              ctx.lineTo(5 + i * 25, 25);
              ctx.strokeStyle = color;
              ctx.stroke();
            }
            
            // recheck the color
            color = colors[Math.floor(oneBox/5)];

            if (remainder == 1) {
              ctx.beginPath();
              ctx.moveTo(5 + i * 25, 5);
              ctx.lineTo(5 + i * 25, 25);
              ctx.strokeStyle = color;
              ctx.stroke();
            }

            if (remainder == 2) {
              ctx.beginPath();
              ctx.moveTo(5 + i * 25, 5);
              ctx.lineTo(25 + i * 25, 5);

              ctx.moveTo(5 + i * 25, 5);
              ctx.lineTo(5 + i * 25, 25);
              ctx.strokeStyle = color;
              ctx.stroke();
            }

            if (remainder == 3) {
              ctx.beginPath();
              ctx.moveTo(5 + i * 25, 5);
              ctx.lineTo(25 + i * 25, 5);

              ctx.moveTo(5 + i * 25, 5);
              ctx.lineTo(5 + i * 25, 25);

              ctx.moveTo(25 + i * 25, 5);
              ctx.lineTo(25 + i * 25, 25);

              ctx.strokeStyle = color;
              ctx.stroke();
            }

            if (remainder == 4) {
              ctx.beginPath();
              ctx.moveTo(5 + i * 25, 5);
              ctx.lineTo(25 + i * 25, 5);

              ctx.moveTo(5 + i * 25, 5);
              ctx.lineTo(5 + i * 25, 25);

              ctx.moveTo(25 + i * 25, 5);
              ctx.lineTo(25 + i * 25, 25);

              ctx.moveTo(25 + i * 25, 25);
              ctx.lineTo(5 + i * 25, 25);

              ctx.strokeStyle = color;
              ctx.stroke();
            }
          };
        }
        render();
      } // end 
  };
});
canvas {
    max-width: 100%;
    height: auto;
    border: 2px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html data-ng-app="tb">

<head lang="en">
  <meta charset="utf-8">
  <title>Tally Boxes</title>
</head>

<body data-ng-controller="tallyboxController" data-ng-init="init()">
  <div id="container">
  </div>
  <div class="container-table">
    <table border="1" width="100%">
      <thead>
        <tr>
          <td>{{label.table.cName}}</td>
          <td>{{label.table.cTB}}</td>
          <td>{{label.table.cNV}}</td>
        </tr>
      </thead>
      <tbody>
        <tr ng-repeat="(key,value) in candidates[0]">
          <td>{{value.no}} {{label.table.period}} {{value.name}}</td>
          <td>
            <canvas width="1000" height="30" id="{{value.no}}" candidate="value" drawing></canvas>
          </td>
          <td>{{value.votes}}</td>
        </tr>
      </tbody
    </table>
  </div>

</body>

</html>

1 个答案:

答案 0 :(得分:1)

在响应性方面,Canvas可能会遇到很多问题。当然,您可以使用CSS来缩放它(请记住,CSS尺寸与画布尺寸不同,如果不同,画布会拉伸)。

因此,您需要自己实施智能响应技术 - 考虑获取可用的画布大小,并相应地重新绘制框。这可以进入窗口调整大小回调,因此它也适用于窗口大小调整。

如果你不想搞砸所有这些,你仍然可以切换回使用常规图像(每种颜色5个),并使用标准的HTML / CSS响应实践。如果没有,则必须在每次调整大小时重新计算画布大小(加上首次加载时)并相应地定位标记框。

谢谢你的提及,顺便说一句。 :)


更新

我看到你同时设法实现了CSS缩放,但请记住,当票数增加时,盒子可能会变得非常小;你可能想要使用多行。


更新2

这就是我的意思 - 看看画布上的这个响应版本是否适合您。它仍然需要一些调整,但你明白了:

var tb = angular.module("tb", []);
tb.controller("tallyboxController", function($scope) {
  'use strict';

  $scope.label = {
    table: {
      cName: "Candidate's Name",
      cVote: 'Vote',
      cTB: 'Tally Boxes',
      cNV: 'No of votes',
      period: '.'
    },
  };

  $scope.presidents = [{
    no: '1',
    name: 'Jeoanna Lingh',
    votes: 1223,
  }, {
    no: '2',
    name: 'Jewel Miller',
    votes: 1234,
  }, {
    no: '3',
    name: 'Shin Lee',
    votes: 1001,
  }];

  $scope.candidates = [
    $scope.presidents,
    $scope.vicepresidents
  ];

});


var tb = angular.module('tb');

tb.directive('drawing', function() {
  return {
    restrict: 'A',
    scope: {
      candidate: '='
    },
    link: function(scope, element, attrs) {

        var colors = ['Red', 'Green', 'Blue', 'Yellow', 'black'];

        scope.$watch("candidate.votes", function(newValue, oldValue) {
          console.log('rendering', newValue);
          render();
        });

        function render() {
          var votes = scope.candidate.votes;
          var ctx = element[0].getContext('2d');
          var remainder = 0;
          var oneBox = 0;

          // clear canvas (needed for subtracting votes)
          // and is a good practice anyway
          element[0].width = element[0].width;

          if (votes > 4) {
            if (remainder = votes % 5) {
              oneBox = (votes - remainder) / 5;
            } else {
              oneBox = votes / 5;
            }
          } else {
            remainder = votes;
          }

          window.addEventListener('resize', handleResize);
          setTimeout(handleResize, 100);

          function handleResize() {
            var c = element[0];
            var width = c.parentNode.offsetWidth;
            var perRow = Math.floor((width - 10) / 25);
            c.width = width;
            c.height = Math.ceil(oneBox / perRow) * 25 + 5;
            console.log(perRow, width, oneBox);
            drawOneBox(perRow);

          }

          function drawOneBox(perRow) {
            for (var r = 0; r < oneBox / perRow; r++) {
              var remainingInRow = (oneBox - r * perRow);
              if (remainingInRow > perRow) remainingInRow = perRow;
              for (var i = 0; i < remainingInRow; i++) {

                var rowOffset = r * 25;

                var color = colors[Math.floor(i / 5)];

                ctx.beginPath();
                ctx.moveTo(5 + i * 25, 5 + rowOffset);
                ctx.lineTo(25 + i * 25, 5 + rowOffset);

                ctx.moveTo(5 + i * 25, 5 + rowOffset);
                ctx.lineTo(5 + i * 25, 25 + rowOffset);

                ctx.moveTo(25 + i * 25, 5 + rowOffset);
                ctx.lineTo(25 + i * 25, 25 + rowOffset);

                ctx.moveTo(5 + i * 25, 5 + rowOffset);
                ctx.lineTo(25 + i * 25, 25 + rowOffset);

                ctx.moveTo(25 + i * 25, 25 + rowOffset);
                ctx.lineTo(5 + i * 25, 25 + rowOffset);
                ctx.strokeStyle = color;
                ctx.stroke();
              }
            }

            // recheck the color
            color = colors[Math.floor(oneBox / 5)];

            if (remainder == 1) {
              ctx.beginPath();
              ctx.moveTo(5 + i * 25, 5 + rowOffset);
              ctx.lineTo(5 + i * 25, 25 + rowOffset);
              ctx.strokeStyle = color;
              ctx.stroke();
            }

            if (remainder == 2) {
              ctx.beginPath();
              ctx.moveTo(5 + i * 25, 5 + rowOffset);
              ctx.lineTo(25 + i * 25, 5 + rowOffset);

              ctx.moveTo(5 + i * 25, 5 + rowOffset);
              ctx.lineTo(5 + i * 25, 25 + rowOffset);
              ctx.strokeStyle = color;
              ctx.stroke();
            }

            if (remainder == 3) {
              ctx.beginPath();
              ctx.moveTo(5 + i * 25, 5 + rowOffset);
              ctx.lineTo(25 + i * 25, 5 + rowOffset);

              ctx.moveTo(5 + i * 25, 5 + rowOffset);
              ctx.lineTo(5 + i * 25, 25 + rowOffset);

              ctx.moveTo(25 + i * 25, 5 + rowOffset);
              ctx.lineTo(25 + i * 25, 25 + rowOffset);

              ctx.strokeStyle = color;
              ctx.stroke();
            }

            if (remainder == 4) {
              ctx.beginPath();
              ctx.moveTo(5 + i * 25, 5 + rowOffset);
              ctx.lineTo(25 + i * 25, 5 + rowOffset);

              ctx.moveTo(5 + i * 25, 5 + rowOffset);
              ctx.lineTo(5 + i * 25, 25 + rowOffset);

              ctx.moveTo(25 + i * 25, 5 + rowOffset);
              ctx.lineTo(25 + i * 25, 25 + rowOffset);

              ctx.moveTo(25 + i * 25, 25 + rowOffset);
              ctx.lineTo(5 + i * 25, 25 + rowOffset);

              ctx.strokeStyle = color;
              ctx.stroke();
            }

          };
        }
        render();
      } // end 
  };
});
canvas {
  max-width: 100%;
  height: auto;
  border: 2px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html data-ng-app="tb">

<head lang="en">
  <meta charset="utf-8">
  <title>Tally Boxes</title>
</head>

<body data-ng-controller="tallyboxController" data-ng-init="init()">
  <div id="container">
  </div>
  <div class="container-table">
    <table border="1" width="100%">
      <thead>
        <tr>
          <td>{{label.table.cName}}</td>
          <td>{{label.table.cTB}}</td>
          <td>{{label.table.cNV}}</td>
        </tr>
      </thead>
      <tbody>
        <tr ng-repeat="(key,value) in candidates[0]">
          <td>{{value.no}} {{label.table.period}} {{value.name}}</td>
          <td>
            <canvas width="1000" height="30" id="{{value.no}}" candidate="value" drawing></canvas>
          </td>
          <td>{{value.votes}}</td>
        </tr>
      </tbody>
    </table>
  </div>

</body>

</html>