Tips for aligning chart data alongside a chart that is compatible with various screen sizes

Positioning elements in CSS is presenting a new challenge for me, especially when it comes to creating a custom chart details section alongside my chart. Unfortunately, I am encountering issues with the display on different devices. While minor misalignments of text do not bother me, ensuring that the scale legend aligns vertically with the chart is crucial. The chart itself scales with a width of 80%.

https://i.sstatic.net/SFZB0.png <-- Image comparison: iPhone 5https://i.sstatic.net/yNDIn.png <-- Image comparison: iPhone 6

In attempting to address this issue, I have experimented with positioning elements 'absolute' and utilizing percentages for width and placement. One example is the scale image:

img#scale {
    width: 121%;
    left: -38%;
    bottom: 53%;
}

At this point, I am seeking advice on alternative CSS styling techniques or whether enhancing the chart functionality within Chart.js could offer a more suitable solution. However, uncertain if the desired outcome can be achieved in the manner I envision.

Answer №1

If you are considering using a static image, it is recommended to incorporate the image directly into the chart itself rather than adding it separately and dealing with positioning complexities.

To integrate the image seamlessly into the chart, you can leverage the following plugin:

Chart.plugins.register({
   chartUpdated: false,
   preload: false,
   imageLoaded: false,
   image: new Image(),
   loadImage: function(chart) {
      var _this = this;
      this.image.onload = function() {
         _this.imageLoaded = true;
         _this.drawScale(chart, this);
      }
      this.image.src = 'https://i.imgur.com/YDRy5jA.png'; // URL of the image
   },
   drawScale: function(chart, img) {
      var ctx = chart.ctx,
         y_axis = chart.scales['y-axis-0'],
         topY = y_axis.top,
         bottomY = y_axis.bottom,
         scaleHeight = bottomY - topY,
         scaleOffset = scaleHeight * (img.width / img.height * 100) / 100;
      chart.options.layout = {
         padding: {
            left: scaleOffset
         }
      }
      ctx.drawImage(img, 0, topY, scaleOffset, scaleHeight);
      if (!this.chartUpdated) {
         chart.update();
         this.chartUpdated = true;
      }
   },
   afterDraw: function(chart, ease) {
      if (!this.preload) {
         this.loadImage(chart);
         this.preload = true;
      } else if (this.imageLoaded) this.drawScale(chart, this.image);
   }
});

DEMO ⧩

Chart.plugins.register({
   chartUpdated: false,
   preload: false,
   imageLoaded: false,
   image: new Image(),
   loadImage: function(chart) {
      var _this = this;
      this.image.onload = function() {
         _this.imageLoaded = true;
         _this.drawScale(chart, this);
      }
      this.image.src = 'https://i.imgur.com/YDRy5jA.png'; // image URL
   },
   drawScale: function(chart, img) {
      var ctx = chart.ctx,
         y_axis = chart.scales['y-axis-0'],
         topY = y_axis.top,
         bottomY = y_axis.bottom,
         scaleHeight = bottomY - topY,
         scaleOffset = scaleHeight * (img.width / img.height * 100) / 100;
      chart.options.layout = {
         padding: {
            left: scaleOffset
         }
      }
      ctx.drawImage(img, 0, topY, scaleOffset, scaleHeight);
      if (!this.chartUpdated) {
         chart.update();
         this.chartUpdated = true;
      }
   },
   afterDraw: function(chart, ease) {
      if (!this.preload) {
         this.loadImage(chart);
         this.preload = true;
      } else if (this.imageLoaded) this.drawScale(chart, this.image);
   }
});

Chart.plugins.register({
   beforeDraw: function(chart) {
      var ctx = chart.chart.ctx,
         x_axis = chart.scales['x-axis-0'],
         topY = chart.scales['y-axis-0'].top,
         bottomY = chart.scales['y-axis-0'].bottom;
      x_axis.options.gridLines.display = false;
      for (i = 0; i <= x_axis.ticks.length; i++) {
         var x = i === x_axis.ticks.length ?
            x_axis.right :
            x_axis.getPixelForValue(x_axis.ticks[i]);
         ctx.save();
         ctx.beginPath();
         ctx.lineWidth = 1;
         ctx.strokeStyle = x_axis.options.gridLines.color;
         ctx.moveTo(x, topY);
         ctx.lineTo(x, bottomY);
         ctx.stroke();
         ctx.restore();
      }
   }
});

var options = {
   type: 'bar',
   data: {
      labels: ["1", "2", "3", "4", "5"],
      datasets: [{
         borderWidth: 2,
         borderColor: "#5d5d5d",
         pointBorderColor: "#5d5d5d",
         pointBackgroundColor: "#5d5d5d",
         pointBorderWidth: 5,
         type: 'line',
         data: [26, 26, 33, 28, 30],
         fill: false,
         lineTension: 0
      }, {
... (repeated content removed for brevity)
      }]
   },
   options: {
       ... (options configuration continued here for brevity)
   }
}

var ctx = document.getElementById('canvas').getContext('2d');
var myChart = new Chart(ctx, options);
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<canvas id="canvas" width="400"></canvas>

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

Tips for removing files from an <input type='file' /> element with jQuery or JavaScript

I have multiple <input type='file' /> fields in my file without any HTML form. I need to clear the attached files from a specific <input type='file' />, not all of them. Using $('input').val(""); clears all the < ...

Backbone.js experiencing synchronization issues exclusively in Internet Explorer

Can anyone confirm if they have encountered this issue before? I'm unsure how to elaborate further as it seems to be the only symptom. Additionally, it does not sync correctly in Internet Explorer. ...

Combine strings in PHP with an alert box in JavaScript

Is there a way to concatenate a string in a JavaScript alert box? I want the first part of the alert box to be a simple text, while the second part is a string retrieved from a MySQL table. $myname = $row["name"]; echo ' <scri ...

Why does the border-radius property not work on my image elements?

Greetings! I have defined an ID named #img in my stylesheet with the property border-radius: 15px; In my HTML, I assigned this ID to a div. However, the images within that div are not getting rounded corners as expected. When using the img selector, it aff ...

What is the connection between importing and using destructuring in ES6 syntax?

Bring in: import React, { Component } from 'react'; Unpacking: let z, { b } = {a: 1, b: 2, c: 3} Both of these examples seem to have similar syntax. However, in the second example, z will be undefined instead of {a: 1, b: 2, c: 3}. Does this ...

Is it possible to incorporate varied icon images for every item in an unordered list?

While I'm not an CSS expert, I do have a decent understanding of it. My current project involves creating an unordered list with unique icons for each item, along with changing the background color upon hover. I wonder if there's a way to achiev ...

How can an array be concatenated using tabs?

I am currently in the process of integrating with an old system that requires a value to be sent via a GET request as a tab delimited string. I have my data stored in an array, but I am facing difficulty when attempting to properly format it using the join ...

Having trouble retrieving the location property from an object obtained through an API request

Upon retrieving a task using its id after scanning a barcode, I successfully obtain the id and the data associated with the task. However, I am encountering an issue where I am unable to properly utilize the setLocation function with the resultData. When I ...

Is it possible to target li a instead of li in jQuery and CSS?

Currently in the process of integrating bootstraps scrollspy on my website, while also working with a menu similar to this example: At the moment, I am able to target the li in the navigation, but what I really want is to target the li a. selector = ...

Steps to Delete Branding WHMCS Ver 8.1 "Powered by WHMcomplete solutions"

As a newcomer to this community, I am reaching out for the first time seeking assistance. A friend of mine recently updated his WHMCS to the latest version and encountered a branding line above the footer area. Previously, he could remove it by editing th ...

Controls that shift a DIV in either direction

I've been working on making a div scroll left or right with either a mouseover effect or click, but I can't seem to figure out what's going wrong. My initial attempt was straightforward: <body> <div id="innerscroll"></div> ...

Unlocking Angular 10: Harnessing the Power of JWT for Seamless

I am encountering an issue with JWT login in angular. Although I have successfully logged in and saved the token, my frontend isn't reflecting the changes Auth.service.ts import { Injectable } from '@angular/core'; import { HttpClient, Http ...

What causes the exception in JavaScript to be an empty object?

try { let temporary = null; temporary.split(','); } catch (error) { Logger().info('caught error: ', error, error.constructor); } output: caught error: {} undefined I attempted to use JSON.stringify and encountered the sa ...

What is the best way to save functions that can be utilized in both Vue front-end and Node back-end environments at the same time?

As I dive into the world of Node/Express back-end and Vue.js front-end development, along with server-side rendering, I am faced with the need to create utility functions that can format textual strings. These functions need to be accessible and reusable b ...

Padding needed for floated <li> items in horizontal menu

I'm attempting to design a horizontal top header featuring a main navigation stacked above a sub-navigation. Both navigations are constructed using <ul> elements with floated <li> items. The sub-navigation mysteriously has excess horizonta ...

"Unlocking the Secrets of Extracting Data from Highlighted Cells in Excel with Node.js

I created a script in node.js to extract information from an excel file. Each row contains a highlighted cell (only one). Right now, I am utilizing the xlsx package to access the data. Here is my code snippet for retrieving data from the sheet: var XLSX = ...

Guide on how to bypass IDM when downloading a PDF file through a GET request

When I try to fetch a PDF by sending a GET request to the server and open it in a new tab, IDM interrupts my request and downloads the file instead. It changes the server response status to 204 and removes the headers. How can I prevent IDM from doing th ...

Here is a unique rewrite of the text: "Learn the process of toggling the tabindex for

Is there a way to dynamically change the tabindex of an element based on its visibility in the viewport? I am looking to either reset the current tabindex when entering a new section and assign new values to elements within that section, or disable and re- ...

I encountered an issue while attempting to utilize a JavaScript script - I received an error message stating "Uncaught ReferenceError: jQuery is not defined."

Currently, I am utilizing a template with multiple pages and I need to use one of them. I followed all the necessary steps correctly, but I encountered an error in the console that says Uncaught ReferenceError: jQuery is not defined. Below is my HTML scrip ...

Opting for a name selector over an id for more specific styling

Is there a way to modify the code below in order to make it function based on a name selector instead of an id? <div id="light" class="change_group_popup"> <a class="close" href="javascript:void(0)">Close</a> JavaScript $('.ch ...