The elements displayed within an HTML canvas need to adapt to different screen sizes

I am facing an issue with my HTML canvas. Inside each canvas, there are tally boxes that represent the number of votes for different candidates. The problem arises when the number of votes exceeds 100, as some of the tally boxes disappear from the canvas. They are all displayed horizontally. I have tried adding CSS with max-width: "100%", but it did not solve the issue. Can anyone suggest a solution to display all the tally boxes within the canvas? Your help is much appreciated. Thank you in advance.

Below is the code snippet. Special thanks to 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.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>

Answer №1

Dealing with responsiveness in Canvas can be tricky. While CSS can help scale it, keep in mind that CSS dimensions and canvas dimensions are not the same. If they differ, the canvas will stretch accordingly.

To ensure responsive behavior, you may need to develop a smart technique by fetching the available canvas size and adjusting the elements based on that information. This could involve implementing a window resize callback function to handle resizing dynamically.

If you prefer a simpler solution, consider using regular images instead of the canvas for each color variant and apply standard HTML/CSS techniques for responsiveness. Otherwise, you will have to constantly update the canvas size during resizing (and initial load) and reposition the tally boxes accordingly.

Thanks for mentioning that, by the way. :)


UPDATE

I noticed that you've managed to implement CSS scaling in the meantime. However, be cautious as the boxes may become extremely small when the number of votes increases; in such cases, utilizing multiple rows might be necessary.


UPDATE 2

Here is an example of a responsive version on canvas. It still requires some adjustments but should give you a clear idea:

// The AngularJS code snippet goes here...

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Dynamic input fields with autocomplete functionality

I have attempted to implement the solutions provided elsewhere on this specific issue, but unfortunately they do not seem to be working for me. It is highly probable that I am making some mistake in my approach... My main objective is to achieve what is me ...

Button fails to align properly on smaller screens

I am facing an issue with the alignment of a form on different devices. The form looks correct on larger devices, like PC monitors, as shown in this image: https://i.sstatic.net/FiEyt.png However, on smaller devices, it appears like this: https://i.sstati ...

Could really use some help with troubleshooting my jQuery UI Todo List - it's just not

I've been working on a new project using jQuery UI to create a "to do list" application. So far, I've managed to get it up and running, but I'm having trouble displaying the tasks correctly in the designated div. Instead of showing up as a b ...

Utilizing attributes as scope properties within AngularJS

I am currently working on a directive and I need to pass the Attributes (Attrs) to the $scope, however, I am facing some difficulties in achieving this. Specifically, my goal is to assign attributes in my template based on the name set in my date-picker ta ...

JSON format for capturing country-specific information such as mailing address and phone number requirements

Hey everyone, I'm looking for a website that provides country-specific form fields for mailing addresses and phone numbers in JSON format. I want to be able to iterate through the JSON data, generate HTML, and ensure that my address and phone number f ...

Double Execution Issue in AngularJS Controllers

Currently, I am working on a Sharepoint 2013 visual web part. Here is a snippet of my .ascx file: <%@ Control Language="C#" Inherits="SharePoint.BLL.UserControls.VODCatalog, SharePoint.BLL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=81fc048468441 ...

Using AJAX and Perl to dynamically update HTML content

Currently, I am attempting to dynamically update a div on my website using ajax and perl. The current implementation I have sort of works but needs improvement. HTML: <h2 id="cpu">--</h2> JS/ajax call: $.ajax({ type: 'GET&apos ...

Creating responsive images in a navbar with HTML and CSS

I need help with this code snippet: <div> <nav class="navbar navbar-expand-lg navbar-light bg-light"> <div class="container"> <div class="d-flex flex-row justify-content-center align-items-center"> <a cla ...

Choosing a nested object within a JavaScript object

Is there a way to select the style contents of an object within another object? The data consists of a json encoded array. In my scenario, I am using data[i].replies and getting 2. How can I access data[i].userstyles instead? It seems to be an object. h ...

Accordion nested within another accordion

I am facing a challenge while trying to nest an accordion within another accordion. The issue is that the nested accordion only expands as much as the first accordion, requiring additional space to display its content properly. Any assistance with resolvin ...

Guide to linking two input fields using a single datepicker

To achieve the goal of filling two input fields simultaneously, take a look at the following code snippet: <mat-form-field> <input matInput [matDatepicker]="startDate" formControlName="SaleDate" /> ...

The jQuery statements are not properly executing the if and else conditions

i'm currently assessing the condition using this particular code. jQuery(document).ready(function($){ $('#uitkering_funds').hide(); $('#uitkering_funds_hoofd').hide(); $('#partner_uitkering').hide(); $('#par ...

Issue with align-items-* class in Bootstrap 4 causing alignment problems

Currently in the process of constructing a website utilizing the Bootstrap 4 framework and encountering difficulties with aligning items properly. For instance: Refer to Bootstrap 4 official documentation for row positioning Compare to my row positionin ...

Calculating the total of selected values in Checkboxes and Selectors using KnockoutJS

I have already created this using jQuery. You can view it on JSFiddle: JSFiddle HTML: <div class="container"> <header> <h3>The Crazy Things We'll Do for Money</h3> <div class="small"><em>An ele ...

Rephrasing links with JavaScript, excluding links leading to a particular directory

I am facing an issue with my webpage where I need to rewrite links using Javascript. Specifically, all the links within the div id="container" need to be changed from "post=post-number-234" to "?id=blog&post=post-number-234". Currently, I have a scrip ...

The window.addEventListener function is failing to work properly on mobile devices

Hey there! I am facing an issue in my JS code. I wrote this code because I want the menu to close when a visitor clicks on another div (not the menu) if it is open. The code seems to be working fine in developer tools on Chrome or Firefox, but it's no ...

Creating uniform line lengths with a ruler utilizing Fabric.js

I have a div that scrolls horizontally and contains a ruler div and a canvas where I draw horizontal lines of varying lengths. When drawing the lines, I want to ensure they are accurately measured against the ruler using JavaScript and CSS: var canvas = ...

"Enhancing User Experience with Multiple Conditional Checkboxes in jQuery

Having difficulty making a checkbox change some HTML content using JQuery. There is a standard html checkbox with the following attributes <input type="checkbox" name="AQN1" class="checkbox Q1" value="AQN10" id="3mcq"> <input type="checkbox" nam ...

Skipping is a common issue encountered when utilizing Bootstrap's Affix feature

I'm trying to implement Bootstraps Affix feature in a sticky subnav. <div class="container" data-spy="affix" data-offset-top="417" id="subnav"> I've adjusted the offset to ensure there's no "skip" or "jump" when the subnav sticks. Ho ...

Slide the toggle icon to activate the add-to-cart button on click!

Is it possible to achieve the functionality of sliding a plus icon to an add to cart button on click, instead of hover? I have attempted using CSS without success. Would JQuery be able to accomplish this task? codepen.io HTML <div class="socialIcons" ...