d3图表重绘无法在窗口调整大小上使用 [英] d3 chart redraw not working on window resize

查看:96
本文介绍了d3图表重绘无法在窗口调整大小上使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用d3显示几个等效的折线图,而我正在使用单个chart()函数构建该折线图,该函数接受所有图表数据.

I'm displaying several equivalent line charts using d3, that I'm building using a single chart() function, which accepts all the chart data.

draw()函数根据需要调用此chart()函数,该函数循环浏览页面上的所有占位符图表元素.

This chart() function is called as required by a draw() function, which loops through all the placeholder chart elements on the page.

我想在调整视口大小时重新绘制所有图表.因此,为此,我要使用d3.select("svg").remove();删除现有图表,然后再次调用我的draw()函数.

I want to redraw all charts when the viewport is resized. So, to do this I'm removing the existing charts using d3.select("svg").remove();, then calling my draw() function again.

不幸的是,当重绘图表时,并非所有元素都是正确的-我的路径没有出现(尽管它存在于标记中),并且其他一些圆形对象也没有显示).我不知道为什么会这样.

Unfortunately, when the charts are redrawn, not all elements are correct - my path does not appear (although it is present in the mark up), and some other circle objects also do not show). I don't know why this is.

请参阅我创建的 codepen .另外,这是相关代码:

Please see the codepen I've created. Also, here is the relevant code:

function debounce(func, wait, immediate) {
    var timeout;
    return function() {
        var context = this, args = arguments;
        var later = function() {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };
        var callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    };
}

var data = [], promos = [], stocks = [], start = [], end = [];

data['chart-7114'] = [{"date":"2017-08-14","value":"5.0000"},{"date":"2017-08-16","value":"5.0000"},{"date":"2017-08-17","value":"5.0000"},{"date":"2017-08-24","value":"5.0000"},{"date":"2017-08-31","value":"5.0000"},{"date":"2017-09-13","value":"5.0000"},{"date":"2017-09-14","value":"5.0000"},{"date":"2017-09-25","value":"6.4500"},{"date":"2017-09-26","value":"6.4500"},{"date":"2017-09-27","value":"6.4500"},{"date":"2017-09-28","value":"6.4500"}];
                promos['chart-7114'] = [{"start_date":"2017-08-14","end_date":"2017-08-16"},{"start_date":"2017-08-24","end_date":"2017-08-24"},{"start_date":"2017-09-13","end_date":"2017-09-14"}];
                stocks['chart-7114'] = [{"start_date":"2017-08-16","end_date":"2017-08-16"},{"start_date":"2017-09-14","end_date":"2017-09-14"},{"start_date":"2017-09-26","end_date":"2017-09-26"}];
                start['chart-7114'] = "2017-08-14";
                end['chart-7114'] = "2017-09-28";


$(document).ready(function() {

function chart(selector, data, promos, stocks, start, end) {

    var margin = {top: 20, right: 20, bottom: 30, left: 60},
        width = $(selector).width() - margin.left - margin.right,
        height = $(selector).height() - margin.top - margin.bottom;

    var svg = d3.select(selector).append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom);

    g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var parseDate = d3.timeParse("%Y-%m-%d"),
        formatDate = d3.timeFormat("%Y"),
        formatDate2 = d3.timeFormat("%d/%m/%Y");

    var x = d3.scaleTime()
        .domain([parseDate(start), parseDate(end)])
        .range([0, width]);

    var y = d3.scaleLinear()
        .range([height, 0]);

    var xAxis = d3.axisBottom(x);
    var yAxis = d3.axisLeft(y);

    var area = d3.line()
        .curve(d3.curveLinear)
        .y(function(d) { return y(d.value); });

    var areaPath = g.append("path")
        .attr('class', 'line')
        .attr("clip-path", "url(#clip)");

    var yGroup = g.append("g");

    var xGroup = g.append("g")
        .attr("transform", "translate(0," + height + ")");

    var tip = d3.tip()
        .attr('class', 'd3-tip')
        .offset([-10, 0])
        .html(function(d) {
            return "Date: " + formatDate2(d.date) + "<br>Price: &pound;" + d.value;
        });

    g.call(tip);

    var promoHighlights = g.selectAll('.promo')
        .data(promos)
        .enter().append("rect")
            .attr('class', 'promo' )
            .style("pointer-events","all")
            .attr("height", height);


    var stockHighlights = g.selectAll('.nostock')
        .data(stocks)
        .enter().append("rect")
            .attr('class', 'nostock' )
            .style("pointer-events","all")
            .attr("height", height);

    var zoom = d3.zoom()
        .scaleExtent([1 / 4, 8])
        .translateExtent([[-width, -Infinity], [2 * width, Infinity]])
        .on("zoom", zoomed);

    var zoomRect = g.append("rect")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .attr("fill", "none")
        .attr("pointer-events", "all")
        .call(zoom);

    var toolTips = g.selectAll("circle")
        .data(data).enter()
        .append("circle")
            .attr("r", 4)
            .style("pointer-events","all")
            .on('mouseover', function(d, e) {
                tip.show(d);
                d3.select(this).attr('r', 8);
            })
            .on('mouseout', function(d, e) {
                tip.hide(d);
                d3.select(this).attr('r', 4);
            });

    g.append("clipPath")
        .attr("id", "clip")
        .append("rect")
            .attr("width", width)
            .attr("height", height);

    data.forEach(function(d) {
        d.date = parseDate(d.date);
        d.value = +d.value;
    });

    var xExtent = d3.extent(data, function(d) { return d.date; });
    zoom.translateExtent([[x(xExtent[0]), -Infinity], [x(xExtent[1]), Infinity]]);
    y.domain([0, d3.max(data, function(d) { return d.value; })+1]);
    yGroup.call(yAxis).select(".domain").remove();
    areaPath.datum(data);
    zoomRect.call(zoom.transform, d3.zoomIdentity);
    toolTips.attr("cy", function(d) { return y(d.value); });

    function zoomed() {
        var xz = d3.event.transform.rescaleX(x);
        xGroup.call(xAxis.scale(xz));
        areaPath.attr("d", area.x(function(d) { return xz(d.date); }));
        toolTips.attr("cx", function(d) { return xz(d.date); });
        promoHighlights.attr("x", function(d) { return xz(parseDate(d.start_date)); })
            .attr("width", function(d) {
                if(d.end_date != d.start_date) {
                    //console.log(parseDate(d.end_date));
                    return xz(parseDate(d.end_date))-xz(parseDate(d.start_date));
                }
                else {
                    return xz(d3.timeDay.offset(parseDate(d.end_date)))-xz(parseDate(d.start_date));
                }
            });
        stockHighlights.attr("x", function(d) {
                return xz(parseDate(d.start_date));
            })
            .attr("width", function(d) {
                if(d.end_date != d.start_date) {
                    //console.log(parseDate(d.end_date));
                    return xz(parseDate(d.end_date))-xz(parseDate(d.start_date));
                }
                else {
                    return xz(d3.timeDay.offset(parseDate(d.end_date)))-xz(parseDate(d.start_date));
                }
            });
    }

}

function draw() {
    $('.chart').each(function() {
        chart_id = $(this).attr('id');
        chart('#'+$(this).attr('id'), data[chart_id], promos[chart_id], stocks[chart_id], start[chart_id], end[chart_id]);
    });
}

if($('.chart').length > 0) {
    draw();

    $(window).resize(debounce(function(){
        d3.select("svg").remove();
        draw();
    },100));
}

});

推荐答案

我最终确定了问题-就是这个循环:

I eventually identified the issue - it was this loop:

data.forEach(function(d) {
    d.date = parseDate(d.date);
    d.value = +d.value;
});

本质上,这是在更新数组中的日期值.由于它是chart()函数的一部分,因此它试图对日期进行两次处理,然后有效地将其值更改为null-并破坏了数据.

Essentially, this was updating the date values in my array. As it was part of the chart() function, it was trying to process the dates twice, which was then effectively changing their value to null - and breaking the data.

这篇关于d3图表重绘无法在窗口调整大小上使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆