utilize the functionality of chartjs to overlay images on top of pie chart segments

Currently working with chartjs version 3.6.0 and vue version 2.6.11. My goal is to create charts using chartjs in combination with vue, which has been going smoothly overall. However, I have encountered a challenge that I am struggling to solve. Specifically, I am attempting to place images on the slices of a pie chart, similar to the example shown in this image: https://i.sstatic.net/211uM.png

This image serves as a reference for the idea that I am aiming to achieve. If you have any insights or solutions regarding this issue, I would greatly appreciate your help. Thank you!

Answer №1

If you want to create images directly on the canvas, you can utilize the capabilities of the Plugin Core API. This API provides various hooks that allow for custom code implementation. For your scenario, you may consider using the afterDatasetsDraw hook in conjunction with CanvasRenderingContext2D.

Below is an example of how you can implement this functionality using runnable sample code:

const imageURLs = [
  'https://i.sstatic.net/2RAv2.png',
  'https://i.sstatic.net/Tq5DA.png',
  'https://i.sstatic.net/3KRtW.png',
  'https://i.sstatic.net/iLyVi.png'
];
const images = imageURLs.map(v => {
  var image = new Image();
  .src = v;
  return image;
});

new Chart('myChart', {
  type: 'pie',
  plugins: [{
    afterDatasetsDraw: chart => {
      var ctx = chart.ctx;
      ctx.save();
      var xCenter = chart.canvas.width / 2;
      var yCenter = chart.canvas.height / 2;
      var data = chart.config.data.datasets[0].data;
      var vTotal = data.reduce((a, b) => a + b, 0);
      data.forEach((v, i) => {
        var vAngle = data.slice(0, i).reduce((a, b) => a + b, 0) + v / 2;
        var angle = 360 / vTotal * vAngle - 90;        
        var radians = angle * (Math.PI / 180);
        var r = yCenter;
        var x = xCenter + Math.cos(radians) * r / 2;
        var y = yCenter + Math.sin(radians) * r / 2;
        ctx.translate(x, y);
        var image = images[i];
        ctx.drawImage(image, -image.width / 2, -image.height / 2);
        ctx.translate(-x, -y);
      });
      ctx.restore();
    }
  }],
  data: {
    labels: ['red vans', 'blue vans', 'green vans', 'gray vans'],
    datasets: [{
      label: 'My Dataset',
      data: [48, 56, 33, 44],
      backgroundColor: ['rgba(255, 0, 0, 0.4)', 'rgba(0, 0, 255, 0.4)', 'rgba(0, 255, 0, 0.4)', 'rgba(124, 124, 124, 0.4)']
    }]
  },
  options: {
    responsive: false,
    plugins: {
      legend: {
        display: false
      }
    },
    scales: {
      ticks: {
        display: false
      }
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.6.1/chart.min.js"></script>
<canvas id="myChart" width="250"></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

submit django form when a checkbox is checked

tml: <div id="report-liveonly"> <form action="." id="status" method="POST">{% csrf_token %} <p>{{SearchKeywordForm.status}}Only display LIVE reports</p> </form> </div> I am facing an issue while trying to submit ...

Export data table from HTML to Excel successfully implemented with C#

I am currently working on an Umbraco website and developing a custom plugin for the backend that allows users to export an Excel worksheet from an HTML table. In order to achieve this functionality, I am utilizing AngularJS along with a C# controller. Belo ...

Utilizing the Filter function to extract both the content contained within a class and the class itself

The filter function is working properly, returning multiple divs with a class of post. However, it is only capturing the content inside the div: <h1></h1> and not the entire structure like this: <div class="post"><h1></h1>& ...

embed a hyperlink onto a live video at a designated moment within an HTML document

Can anyone help me figure out how to overlay a link over a video playing at a specific time on an HTML page? I know it's easy to do on Youtube, but I need to accomplish this task without using Youtube. :) Thank you in advance for any assistance! ...

Invoke a method on a child component once an event has been emitted

Currently, I am working on creating a custom button component that includes a spinner. The functionality works well - the button gets disabled and displays a spinner upon click. However, I am facing issues when it comes to resetting the button's state ...

Is there a way to transform text into a distinct element (such as a divider) when clicked?

I'm currently exploring a method to transform text on my webpage into a divider or new element when clicked. It's a bit difficult to explain, but think of it like an image with a caption underneath - when you click the caption, the image above ch ...

Interacting with Django backend via AJAX to trigger Python functions using jQuery/AJAX

Currently, I am developing a small website using Django. Within this project, there are DateTime fields that need to be handled. My intention is to utilize ajax by implementing another button to establish the UTC date while taking into consideration sola ...

I would love to hear your suggestions for a custom select element plugin in jQuery

After browsing multiple options online, I decided to turn to the expertise of the Stack Overflow community to ask for recommendations based on personal experience. I am specifically in search of a plugin that can substitute a select element with a custo ...

Experience the classic game of rock-paper-scissors brought to life through JavaScript and HTML,

I've been working on a rock, paper, scissors game in JavaScript and I'm struggling to get the wins and losses to register correctly. The game keeps resulting in a draw even though I've checked my code multiple times. It's frustrating be ...

A method for displaying both the next and previous steps without relying on a switch case statement

I have an array list as follows: const data = [ { title: 'Title1', }, { title: 'Title2', }, { title: 'Title3', }, { title: 'Title4', ...

I can't understand why my server is displaying an error on the browser stating "This site can't be reached ERR_UNSAFE_PORT" while it is functioning flawlessly on the terminal

I have created an index.html file, along with index.js and server.js. In the server.js file, I have included the following code: const express = require("express"); const path = require("path" ); const app = express(); app.use(" ...

Leveraging JavaScript promises to execute a function only once

var dataFetch= $q.defer(); function fetchData(){ return dataFetch.promise; } (function getData(){ setTimeOut( function(){ myPromise.resolve("data"); } ,1000); })(); fetchData().then(function(){alert("use ...

Guide on embedding a compiled JavaScript file into NuxtJS

Currently, I am working on a NuxtJS application and I am looking to add a file named app.js which is located in assets/js/app.js. This file contains the following code: // imports from node_modules import 'focus-visible'; import 'other-pack ...

A guide to obtaining radar chart coordinates by utilizing the getValueForDistanceFromCenter method in Chart.js

I've been experimenting with creating radar charts using Chart.js. I have a good grasp on the basics, as shown in the simple chart below, but I'm looking to utilize the x y coordinates of the graph to position text directly on the canvas. After ...

Retrieve the value of a CSS class property regardless of whether it is actively being utilized

I am facing a dilemma where I need to determine the value of the 'width' property for a css class named 'foo' (example: ".foo { width:200px}" ). However, there may not be an element with this class in the dom yet. My goal is to retrie ...

Issue with ng-hide logic malfunctioning

I am currently developing an Ionic application and encountering some issues with the ng-hide directive. My goal is to display or hide a button based on whether the user has completed registration. The button in question: <button class="button button-c ...

Which folder should I utilize - assets or public - for Laravel 5.3?

Exploring the World of Laravel 5.3 After diving into Laravel 5.3, I discovered that the view files are located within a folder named resources, while an additional assets folder contains a subfolder called js. Meanwhile, the trusty public folder remains i ...

Issue with aligning dropdown menu to the right in Bootstrap 5.1 not being resolved

I'm facing an issue with aligning my dropdown menu responsively on the right side of the page while keeping the "Create Event" button on the left. I followed the documentation which suggests adding .dropdown-menu-end to the ul class, but it didn' ...

"Nested transitions in Vue 3 aren't functioning as expected, and no errors are

I'm currently working on a Vue3 Root component that displays a list of groups, where each group can contain multiple entries. <script setup lang="ts"> import EntryItem from '../components/EntryItem.vue'; let groups = [ { n ...

Setting up anchor tags with dynamically changing href values does not trigger a get request

I seem to be facing an issue that I can't quite pinpoint. Essentially, I am retrieving data from my database to populate an HTML page and dynamically assigning href values to some anchor tags. However, upon clicking on the links, the page simply reloa ...