Chartjs:设置拖动时缩放的最小值和适当的用户反馈

stszievb  于 2023-01-20  发布在  Chart.js
关注(0)|答案(1)|浏览(141)

我正在使用Chartjs 4.0.1和chartjs-plugin-zoom 2.0.0,我的图表看起来像这样:

我已经将拖动选项设置为启用,以便用户可以绘制一个矩形来进行放大。我还将缩放模式设置为“x”。因此,用户只能在x轴上进行放大,而不能在y轴上进行放大。现在,我想限制用户可以放大的范围。到一个月的时间跨度。我已经设法做到这一点时,使用鼠标滚轮放大。但我不知道如何实现同样的使用拖动选项。我将其配置为:

drag:{
  enabled: true,
  backgroundColor:'rgba(180,180,180,0.4)',
  threshold: 25,
}

阈值似乎是我最好的选择。然而,它是以像素为单位的,它只说明了绘制的矩形必须有多宽才能发生缩放。我已经使用onZoomStart回调函数来检查图表放大了多远,并基于此决定用户是否可以放大更多。但显然,该回调函数只在通过鼠标滚轮缩放时执行,而在拖动时不执行。所以我想我需要能够动态地设置拖动对象的阈值,有人知道怎么做吗?
我还想知道,是否有可能改变边界颜色的矩形时,拖动显示用户,如果它是足够大的滚动发生?

sy5wg1nm

sy5wg1nm1#

标准的解决方案似乎是设置一个limits:{x:{minRange:...}}选项。我花了一段时间才意识到应该在哪里插入这个选项。
下面是一个代码片段,其中包含一些类似于您的数据,并且minRange设置为90天(因此我可以跳过调整tick间隔)。
此外,如果间隔小于90天,还有一个将拖动矩形的颜色更改为红色的黑客。它可以很容易地适应小于所需间隔时完全拒绝缩放,而不是当前的标准行为,即调整(扩展)间隔,直到它等于minRange
this fiddle中相同。

const nPoints = 400,
        t0 = Date.parse("2018-06-02T00:00:00Z"),
        dt = 2.5*365/nPoints*24*3600*1000;
    const data = Array.from(
        {length: nPoints},
        (_, i)=>({
            "timestamp":(t0+dt*i),
            value: 80*Math.sin(i*Math.PI/nPoints)+2*Math.random()
        })
    );
    let mouseMoveHandler = null;
    chart = new Chart(document.getElementById("myChart"), {
        type: 'line',
        data: {
            datasets: [{
                label: "Count",
                //pointStyle: false,
                pointRadius: 2,
                showLine: true,
                fill: true,
                tension: 0,
                borderColor: '#aa6577',
                //pointRadius: 4,
                //pointBorderWidth: 1,
                //pointBackgroundColor: '#7265ce',
                data: data
            }]
        },
        options: {
            parsing: {
                xAxisKey: 'timestamp',
                yAxisKey: 'value'
            },
            spanGaps: false,
            responsive: false,
            scales: {
                x: {
                    bounds: 'ticks',
                    type: 'time',
                    time: {
                        unit: 'month',
                    },
                    title: {
                        display: false,
                        text: 'time'
                    },
                    ticks: {
                        display: true,
                        color: '#cecece'
                    }
                },
                y: {
                    type: 'linear',
                    display: true,
                    min: -10,
                    max: 140,
                    ticks: {
                        autoSkip: true,
                        color: '#cecece'
                    },
                    grid:{
                        color: ctx => ctx.tick.value === 0 ? '#000' : '#ddd',
                        lineWidth: ctx => ctx.tick.value === 0 ? 3 : 1,
                    },
                    title: {
                        display: false,
                        text: 'Count',
                        align: 'end'
                    },
                }
            },
            plugins:{
                legend:{
                    display: false
                },
                zoom: {
                    zoom: {
                        drag: {
                            enabled: true,
                            backgroundColor:'rgba(180,180,180,0.4)',
                        },
                        mode: 'x',
                        onZoomStart({chart, event}){
                            const x0 = chart.scales.x.getValueForPixel(event.clientX);
                            if(event.type==="mousedown"){
                                mouseMoveHandler = function(e){
                                    if(
                                        Math.abs(chart.scales.x.getValueForPixel(e.clientX) - x0) <
                                            chart.options.plugins.zoom.limits.x.minRange
                                    ){
                                        chart.options.plugins.zoom.zoom.drag.backgroundColor = 'rgba(255,180,180,0.4)';
                                    }
                                    else{
                                        chart.options.plugins.zoom.zoom.drag.backgroundColor = 'rgba(180,180,180,0.4)';
                                    }
                                };
                                chart.canvas.addEventListener("mousemove", mouseMoveHandler);
                                chart.canvas.addEventListener("mouseup", function(){
                                    if(mouseMoveHandler){
                                        chart.canvas.removeEventListener("mousemove", mouseMoveHandler);
                                        mouseMoveHandler = null;
                                    }
                                }, {once: true});
                            }
                        },
                        onZoomComplete({chart}){
                            if(mouseMoveHandler){
                                chart.canvas.removeEventListener("mousemove", mouseMoveHandler);
                                mouseMoveHandler = null;
                            }
                            document.querySelector('#zoom').innerText = chart.getZoomLevel().toFixed(1)+'x';
                            document.querySelector('#xSpan').innerText =
                                Math.round((chart.scales.x.max-chart.scales.x.min)/24/3600/1000)+'days';
                        }
                    },
                    limits:{
                        x: {
                            minRange: 90 * 24* 3600 * 1000
                        }
                    }
                }
            }
        }
    });
    document.querySelector('#resetZoom').addEventListener('click', function(){chart.resetZoom();});
    document.querySelector('#xSpan').innerText = Math.round((chart.scales.x.max-chart.scales.x.min)/24/3600/1000)+'days';
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.0.1/chart.umd.min.js"
        integrity="sha512-HyprZz2W40JOnIBIXDYHCFlkSscDdYaNe2FYl34g1DOmE9J+zEPoT4HHHZ2b3+milFBtiKVWb4sorDVVp+iuqA=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-zoom/2.0.0/chartjs-plugin-zoom.min.js"
        integrity="sha512-B6F98QATBNaDHSE7uANGo5h0mU6fhKCUD+SPAY7KZDxE8QgZw9rewDtNiu3mbbutYDWOKT3SPYD8qDBpG2QnEg=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns/dist/chartjs-adapter-date-fns.bundle.min.js">
</script>

<canvas id="myChart" style="height:500px; width: 90vw"></canvas>
<button id="resetZoom">Reset zoom</button> <br>
zoom: <span id="zoom">1x</span><br>
X axis span: <span id="xSpan"></span>

相关问题