Chart js在一页上显示多个饼图

Chart js multiple pie chart on one page

我正在构建我的投资组合网站,并且我构建了一个简单的股票追踪器。我从 Chart.js 添加了一些图表,但不知何故,当我执行代码时只渲染了一个。

我设法通过使变量动态化来动态分配所有 div 和数据。我通过在 for 循环中添加投资组合 ID 来做到这一点。我不明白为什么它不起作用。感谢任何帮助。

{% extends 'base.html' %}
{% block page_content %}
{% if user.is_authenticated %}
<body>
<div class="container">
    <div class="row">
        <div class="col-12">
            <h2>
                Welcome to the stocktracker
            </h2>
            <p>I build this stocktracker app to learn database operations. To get current stock data, I linked this to
                the free API from Polygon.io. It's only possible to do 5 API calls per minute. You will see an error
                message whenever the api calls are exceeded.
                <br><br>Current features are:
            <ol>
                <li>Basic CRUD database operation</li>
                <li>Adding portfolio's linked to user</li>
                <li>Only show portfolio's linked to user</li>
                <li>Show general KPI's in portfolio overview</li>
                <li>KPI's calculated based on positions in portfolio</li>
                <li>Adding position to portfolio</li>
                <li>API connection with Polygon.io to get live stock data</li>
                <li>Chart.js integration for visual representation of portfolio metrics</li>
            </ol>
            </p>
        </div>
    </div>
    <div class="row">
        <div class="col-8">
            <h2>Select your portfolio</h2>
        </div>
        <div class="col-4 text-end">
            <!-- Button trigger modal -->
            <button type="button" class="btn btn-secondary" data-bs-toggle="modal" data-bs-target="#addPortfolioModal">
                Add new portfolio
            </button>

            <!-- Modal -->

            <div class="modal fade" id="addPortfolioModal" tabindex="-1" role="dialog"
                 aria-labelledby="addPortfolioModalLabel"
                 aria-hidden="true">
                <div class="modal-dialog" role="document">
                    <div class="modal-content">
                        <div class="modal-header">
                            <h5 class="modal-title" id="addPortfolioLabel">Modal title</h5>
                            <button type="button" class="close" data-bs-dismiss="modal" aria-label="Close">
                                <span aria-hidden="true">&times;</span>
                            </button>
                        </div>
                        <div class="modal-body">
                            <form name="portfolio_form" method="post">
                                {% csrf_token %}
                                <p>
                                    {{ portfolio_form }}
                                </p>
                                <div class="modal-footer">
                                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close
                                    </button>
                                    <input type="submit" value="Submit"/>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div>
            {% for portfolio in portfolios %}
            <div class="row pt-4">
                <div class="col-6">
                    <a class="btn btn-primary" href="{% url 'portfolio_detail' portfolio.pk%}">Go to {{ portfolio }}</a>
                </div>
            </div>
            {% if portfolio.total_positions > 0 %}
            <div>
                {% load static %}
                <div class="col-4 text-start" style="width: 50%;">
                    <canvas id="pie-chart{{ portfolio.pk }}"></canvas>

                    <script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.3/dist/Chart.min.js"></script>
                    <script>
                    var randomNum_{{ portfolio.pk }} = () => Math.floor(Math.random() * (235 - 52 + 1) + 52);
                    function rgbToHex(r, g, b) {
                        return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
                    }
                    countPositions = {{ portfolio.total_positions|safe }};

                    var barColors_{{ portfolio.pk }} = [];
                    for (let i = 0; i < countPositions; i++) {
                        randomGeneratedColor = rgbToHex(randomNum_{{ portfolio.pk }}(), randomNum_{{ portfolio.pk }}(), randomNum_{{ portfolio.pk }}());
                        while (barColors_{{ portfolio.pk }}.includes(randomGeneratedColor)) {
                            randomGeneratedColor = rgbToHex(randomNum(), randomNum(), randomNum());
                        }
                        barColors_{{ portfolio.pk }}.push(randomGeneratedColor);
                    }
                    var config_{{ portfolio.pk }} = {
                        type: 'pie',
                        data: {
                            datasets: [{
                                data: {{ portfolio.data_for_chart_array|safe }},
                                backgroundColor: barColors_{{ portfolio.pk }},
                                label: 'Stock ticker'
                            }],
                            labels: {{ portfolio.labels_array|safe }}
                        },
                        options: {
                            responsive: true
                        }
                    };

                    window.onload = function() {
                        var ctx = document.getElementById('pie-chart{{ portfolio.pk }}').getContext('2d');
                        window.myPie = new Chart(ctx_{{ portfolio.pk }}, config_{{ portfolio.pk }});
                    };

                    </script>
                </div>
            </div>
            {% endif %}
            <div class="row">
                <div class="col-4 pt-2">
                    <b>Total amount invested:</b> {{ portfolio.total_amount_invested }}
                    <br><b>Positions:</b> {{ portfolio.total_positions }}
                    <br><b>Profit:</b> {{ portfolio.total_profit }}
                    <br><b>Profit in %:</b> {{ portfolio.total_profit_percentage }} %
                </div>
            </div>
        </div>
        {% endfor %}
    </div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"
            integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p"
            crossorigin="anonymous"></script>
</div>
</body>
{% endif %}
{% endblock %}

不知怎么的,只有最后一个图表被渲染,而不是所有三个图表。

那里有一个循环,在循环的每次迭代中,您都在使用 window.onload = function() {…};

基本上,您是在循环的每次迭代中覆盖 onload 函数,因此只有最后一次覆盖保留下来。

您想要的是在 window 上添加 load 个事件侦听器,而不是不断地覆盖一个侦听器。

为此,我建议替换为:

window.onload = function () {…}

有了这个:

window.addEventListener('load', function() {…})`

addEventListener

另一种看出 window.onload = function () {…} 有问题的方法是以下代码段:

window.onload = function () { alert('one') };
window.onload = function () { alert('two') };

问:您希望此处的页面加载发生什么?

A: 与您的情况类似,只会调用第二个函数(提醒“two”)。