You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在chartjs-plugin-datalabels v2.1.0中用图片替换幸运转盘标签文本

问题描述

使用chartjs-plugin-datalabels v2.1.0制作幸运转盘,需要将标签列中的文本(如'2'、'3')替换为图片,现有代码中标签行的值为文本,希望替换为图片。

解决方案

chartjs-plugin-datalabels默认不支持直接渲染HTML元素(如<img>),因为Chart.js基于Canvas绘制,需通过Canvas的drawImage方法实现图片绘制。以下是修改后的完整代码:

修改后的JavaScript代码

const spinWheel = document.getElementById("spinWheel");
const spinBtn = document.getElementById("spin_btn");
const text = document.getElementById("text");
const spinValues = [
    { minDegree: 31, maxDegree: 60, value: "Ноутбук игровой MSI Katana GF76 12UD-263RU" },
    { minDegree: 0, maxDegree: 30, value: "Lush3 + Ridge x 1 + Микрофон HyperX Quadcast S" },
    { minDegree: 61, maxDegree: 90, value: "Беззеркальная камера Canon EOS R50 Body" },
    { minDegree: 331, maxDegree: 360, value: "Lovense Webcam + Domi 2" },
    { minDegree: 301, maxDegree: 330, value: '"Капуста"' },
    { minDegree: 271, maxDegree: 300, value: '"Картошка"' },
    { minDegree: 211, maxDegree: 240, value: "Apple iPhone 15" },
    { minDegree: 241, maxDegree: 270, value: '"Морковь"' },
    { minDegree: 181, maxDegree: 210, value: "Cougar Throne – кресло для геймеров" },
    {
        minDegree: 151,
        maxDegree: 180,
        value: "Сертификат ВБ",
    },
];

const size = [10, 10, 10, 10, 10, 10, 10, 10, 10, 10];
var spinColors = ["#303032", "#303032", "#303032", "#303032", "#303032", "#303032", "#303032", "#303032", "#303032", "#303032"];

// 预加载所有图片,避免绘制时图片未加载完成
const preloadImages = (imagePaths) => {
    return Promise.all(imagePaths.map(path => {
        return new Promise((resolve, reject) => {
            const img = new Image();
            img.src = path;
            img.onload = () => resolve(img);
            img.onerror = reject;
        });
    }));
};

// 定义每个扇形对应的图片路径
const labelImages = [
    "/img/11.png",
    "/img/2.png",
    "/img/3.png",
    "/img/4.png",
    "/img/5.png",
    "/img/6.png",
    "/img/7.png",
    "/img/8.png",
    "/img/9.png",
    "/img/10.png"
];

// 预加载图片后初始化图表
preloadImages(labelImages).then(images => {
    let spinChart = new Chart(spinWheel, {
        plugins: [ChartDataLabels],
        type: "pie",
        data: {
            labels: labelImages, // 用图片路径作为标签标识
            datasets: [
                {
                    backgroundColor: spinColors,
                    data: size,
                },
            ],
        },
        options: {
            responsive: true,
            animation: { duration: 0 },
            plugins: {
                tooltip: false,
                legend: {
                    display: false,
                },
                datalabels: {
                    rotation: 90,
                    display: true,
                    formatter: () => '', // 禁用默认文本输出
                    draw: function(context) {
                        const { ctx, dataIndex } = context;
                        const image = images[dataIndex];
                        if (!image) return;

                        // 获取扇形中心位置
                        const { x, y } = context.rect;
                        // 计算图片尺寸(取扇形最小边的60%,避免超出边界)
                        const imgSize = Math.min(context.rect.width, context.rect.height) * 0.6;

                        // 旋转画布匹配标签旋转角度
                        ctx.save();
                        ctx.translate(x, y);
                        ctx.rotate((90 * Math.PI) / 180);
                        // 居中绘制图片
                        ctx.drawImage(image, -imgSize/2, -imgSize/2, imgSize, imgSize);
                        ctx.restore();
                    }
                },
            },
        },
    });

    const generateValue = (angleValue) => {
        for (let i of spinValues) {
            if (angleValue >= i.minDegree && angleValue <= i.maxDegree) {
                text.innerHTML = `<p>Поздравляем, вы выиграли: <br> ${i.value} ! </p>`;
                spinBtn.disabled = false;
                break;
            }
        }
    };

    let count = 0;
    let resultValue = 101;
    spinBtn.addEventListener("click", () => {
        spinBtn.disabled = true;
        text.innerHTML = `<p>Желаю Удачи!</p>`;
        let randomDegree = Math.floor(Math.random() * (355 - 0 + 1) + 0);
        let rotationInterval = window.setInterval(() => {
            spinChart.options.rotation = spinChart.options.rotation + resultValue;
            spinChart.update();
            if (spinChart.options.rotation >= 360) {
                count += 1;
                resultValue -= 5;
                spinChart.options.rotation = 0;
            } else if (count > 15 && spinChart.options.rotation >= randomDegree) {
                generateValue(randomDegree);
                clearInterval(rotationInterval);
                count = 0;
                resultValue = 101;
            }
        }, 10);
    });
}).catch(err => {
    console.error("图片加载失败:", err);
});

修改后的HTML代码

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-datalabels/2.1.0/chartjs-plugin-datalabels.min.js"></script>

<div>
    <canvas id="spinWheel"></canvas>
</div>
<div id="spin_btn">spin_btn</div>
<div id="text">text</div>

关键改动说明

  • 预加载图片:通过preloadImages函数提前加载所有转盘图片,确保绘制时图片已加载完成,避免空白。
  • 替换labels数组:将原文本标签替换为图片路径,用于关联对应的图片资源。
  • 自定义datalabels绘制逻辑:使用draw回调函数,利用Canvas的drawImage方法在扇形中心绘制图片,同时匹配原有的旋转角度,保证图片方向正确。
  • 动态调整图片尺寸:根据扇形大小计算图片显示尺寸,确保图片在扇形内适配显示。

内容的提问来源于stack exchange,提问作者HaoSed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 03:05:57