放大时,D3轴标签变得过细 [英] D3 axis labels become too fine grained when zoomed in

查看:84
本文介绍了放大时,D3轴标签变得过细的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图创建一个轴函数,即刻度/标签是动态的,这意味着它们会自动隐藏/显示。但在上面,我想在一些缩放级别停止呈现更多的刻度/标签。这里有一个例子:首先,轴显示年份,然后当放大时,刻度变为月份,当进一步放大时,它显示天数(I.E.,12月28日)。除了我想限制d3,这样当缩放比月份更远,它不会再呈现任何更多的刻度,因为月份是我想要的最小单位。



我有一个几个例子,如果组合将是我想要的,但我不知道如何做。



另外:我添加了.tickFormat,因为我想



示例1:
http ://jsfiddle.net/GGYKL/

  var xAxis = d3.svg.axis()。scale x)
.tickFormat(d3.time.format('%b'))
.orient(bottom);

此示例显示在放大时刻度/标签如何正确显示和消失,但当您继续缩放时in,it split the months and starts repeated the month ticks / labels,and I do not want to restrict the user from zoom in in。



示例2:
http://jsfiddle.net/4kz7t/

  var xAxis = d3.svg.axis()。scale(x)
.ticks(d3.time.months)
.tickFormat(d3.time.format('%b' ))
.orient(bottom),

继续放大,就像我们在示例1中看到的,但是它不会在缩放时动态隐藏/显示刻度/标签。

解决方案

p>我遇到的最接近的答案是@Lars Kotthoff建议的多尺度时间格式。我将自定义时间格式化程序编辑为:



http: //jsfiddle.net/BdGv5/1/

  var customTimeFormat = timeFormat([
[d3 .time.format(%Y),function(){return true;}],
[d3.time.format(%b),function(d){return d.getMonth() }],
[function(){return;},function(d){return d.getDate()!= 1;}]
]

因此,缩放本身仍会在放大时生成,但标签将为空字符串。 / p>

更新:



我最终创建了自己的函数,我在.ticks蜱传递给您的函数,比例范围为t0和t1。我将图表宽度除以标签大小(和填充),以找出不重叠的标签的最大数量,并使用下划线删除每个其他的重叠,如果重叠会发生。



http://jsfiddle.net/BdGv5/3/

  function customTickFunction(t0,t1,dt)
{

var labelSize = 30; //最大标签是23像素(May)
var maxTotalLabels = Math.floor(width / labelSize);

函数步(日期,偏移量)
{
date.setMonth(date.getMonth()+ offset);
}

var time = d3.time.month.ceil(t0),times = [];

while(time< t1)times.push(new Date(+ time)),step(time,1);

if(times.length> maxTotalLabels)
times = _.filter(times,function(d){
return(d.getMonth()+ 1)%2 ;
});

return times;
}

var domain = xScale.domain();
var xAxisMonthsFunction = d3.svg.axis()。scale(xScale)
.ticks(customTickFunction)
.tickFormat(d3.time.format(%b))$ b $ 底部;

更新2:



http://jsfiddle.net/BdGv5/5/



使刻度调整超过1级,现在它有4级(2,3,4,6)。

  function customTickFunction(t0,t1,dt)
{

var labelSize = 30; //最大标签是23像素(May)
var maxTotalLabels = Math.floor(width / labelSize);

函数步(日期,偏移量)
{
date.setMonth(date.getMonth()+ offset);
}

var time = d3.time.month.ceil(t0),times = [],monthFactors = [2,3,4,6];

while(time< t1)times.push(new Date(+ time)),step(time,1);

var i;
for(i = 1; times.length> maxTotalLabels; i ++)
times = _.filter(times,function(d){
return(d.getMonth())%monthFactors [i] == 0;
});

return times;
}


I'm trying to create an axis function that the ticks/labels are dynamic meaning they hide/show automatically. BUT on top of that, I want at some zoom level to stop rendering more ticks/labels. Here's an example: At first the axis shows the years, then when you zoom in the ticks become Months, and when you zoom further in it shows the days (I.E., Dec 28). Except I want to restrict d3 such that when zooming further than the months, it doesn't render any more ticks because months are the smallest unit I want.

I have a couple examples that if combined would be exactly what I want, but I can't figure out how to do that.

Also: I added the .tickFormat because I want to display every tick to have an abbreviated month format.

Example 1: http://jsfiddle.net/GGYKL/

var xAxis = d3.svg.axis().scale(x)
    .tickFormat(d3.time.format('%b'))
    .orient("bottom");

This example shows how the ticks/labels appear and disappear correctly when zooming in, BUT when you continue zooming in, it splits the months and starts repeating the month ticks/labels, and I do not want to restrict the user from zooming in.

Example 2: http://jsfiddle.net/4kz7t/

var xAxis = d3.svg.axis().scale(x)
    .ticks(d3.time.months)
    .tickFormat(d3.time.format('%b'))
    .orient("bottom"),

This example fixes the problem when you continue zooming in like what we saw with Example 1, BUT it doesn't dynamically hide/show the ticks/labels when zooming.

解决方案

The closest answer I've come across was the multi-scale time Format that @Lars Kotthoff suggested. I edited the custom time formatter to be:

http://jsfiddle.net/BdGv5/1/

var customTimeFormat = timeFormat([
    [d3.time.format("%Y"), function() { return true; }],
    [d3.time.format("%b"), function(d) { return d.getMonth(); }],
    [function(){return "";}, function(d) { return d.getDate() != 1; }]
]);

So the ticks themselves would still be generated when zooming in, but the labels would be empty string.

UPDATE:

I ended up creating my own function that I used in .ticks(). Ticks passes to your function the scale extent as t0 and t1. I divided the chart width by the label size (and padding) to find the maximum amount of labels without overlapping, and used underscore to remove every other tick if overlapping will occur.

http://jsfiddle.net/BdGv5/3/

function customTickFunction(t0, t1, dt)
    {

        var labelSize = 30; // largest label is 23 pixels ("May")
        var maxTotalLabels = Math.floor(width / labelSize);

        function step(date, offset)
        {
            date.setMonth(date.getMonth() + offset);
        }

        var time = d3.time.month.ceil(t0), times = [];

        while (time < t1) times.push(new Date(+time)), step(time, 1);

        if(times.length > maxTotalLabels)
            times = _.filter(times, function(d){
                return (d.getMonth() + 1) % 2;
            });

        return times;
    }

    var domain = xScale.domain();
    var xAxisMonthsFunction = d3.svg.axis().scale(xScale)
        .ticks(customTickFunction)
        .tickFormat(d3.time.format("%b"))
        .orient("bottom");

Update 2:

http://jsfiddle.net/BdGv5/5/

Made the ticks adjust further than just 1 level, now it has 4 levels (2,3,4,6).

function customTickFunction(t0, t1, dt)
{

    var labelSize = 30; // largest label is 23 pixels ("May")
    var maxTotalLabels = Math.floor(width / labelSize);

    function step(date, offset)
    {
        date.setMonth(date.getMonth() + offset);
    }

    var time = d3.time.month.ceil(t0), times = [], monthFactors = [2,3,4,6];

    while (time < t1) times.push(new Date(+time)), step(time, 1);

    var i;
    for(i=1 ; times.length > maxTotalLabels ; i++)
        times = _.filter(times, function(d){
            return (d.getMonth()) % monthFactors[i] == 0;
        });

    return times;
}

这篇关于放大时,D3轴标签变得过细的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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