2015-12-16 19 views
5

Buduję wizualizację osi czasu za pomocą d3, gdzie domena może się różnić od kilku dni do kilku dekad. Używam skalę czasową d3 i oś tak:d3.js: pobierz format znacznika ze skali czasu

var timeScale = d3.time.scale() 
    .domain([firstEvent, lastEvent]) 
    .range([leftPadding, w - rightPadding]); 
var timeAxis = d3.svg.axis() 
    .scale(timeScale) 
    .orient("bottom"); 
timeAxis.ticks(5); 

Ponieważ domena jest tak zmienny, że jest wygodny w użyciu ticks(x) który automatycznie wybrać format kleszcza. Mój problem polega na tym, że w niektórych przypadkach rok nie jest pokazany, co jest kluczowe. Moim pomysłem było sprawdzenie formatu zaznaczenia po utworzeniu osi, a jeśli nie zawiera on roku, pokaż go ręcznie obok osi. Jednak nie udało mi się uzyskać formatu znacznika skali; użycie timeScale.tickFormat() właśnie zwraca funkcję. Jak mogę rozwiązać ten problem?

+0

Możesz wywołać '.ticks()' bez żadnych argumentów, aby uzyskać lokalizacje zaznaczenia. –

+0

@LarsKotthoff Tak, ale '.ticks()' zwraca niesformatowane lokalizacje, więc nie można stwierdzić, czy rok będzie wyświetlany w ich etykietach, o ile widzę. – speedymcs

Odpowiedz

3

Co powiesz na prosty test regex?

var hasYear = false; 
var re = /^\d{4}$/; 
// get the ticks text  
d3.selectAll('.x>.tick>text').each(function(d){ 
    // does the text look like a year? 
    var txt = this.textContent; 
    if (re.test(txt)){ 
    hasYear = true; 
    } 
}); 
console.log(hasYear); 

używany ten przykładowy kod i bawił się z różnych zakresów:

<!DOCTYPE html> 
 
<meta charset="utf-8"> 
 
<style> 
 

 
.axis text { 
 
    font: 10px sans-serif; 
 
} 
 

 
.axis line, 
 
.axis path { 
 
    fill: none; 
 
    stroke: #000; 
 
    shape-rendering: crispEdges; 
 
} 
 

 
</style> 
 
<body> 
 
<script src="//d3js.org/d3.v3.min.js"></script> 
 
<script> 
 

 
var margin = {top: 250, right: 40, bottom: 250, left: 40}, 
 
    width = 960 - margin.left - margin.right, 
 
    height = 500 - margin.top - margin.bottom; 
 

 
var x = d3.time.scale() 
 
    .domain([new Date(2013, 12, 2), new Date(2013, 12, 6)]) 
 
    .range([0, width]); 
 

 
var xAxis = d3.svg.axis() 
 
    .scale(x) 
 
    .ticks(5); 
 

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

 
svg.append("g") 
 
    .attr("class", "x axis") 
 
    .attr("transform", "translate(0," + height + ")") 
 
    .call(xAxis); 
 
    
 
xAxis.ticks().some(function(d){ 
 
    return /^\d{4}$/.exec("3434") 
 
}) 
 

 
var hasYear = false; 
 
var re = /^\d{4}$/; 
 
d3.selectAll('.x>.tick>text').each(function(d){ 
 
    var txt = this.textContent; 
 
    if (re.test(txt)){ 
 
    hasYear = true; 
 
    } 
 
}); 
 
console.log(hasYear); 
 

 

 
</script>

+0

Wydaje się działać dobrze - wielkie dzięki! Potrzebujesz dowiedzieć się więcej o selekcji ... – speedymcs

1

osi czasu D3 formatowania sprawdza, czy którykolwiek z tych dat wyświetlanych na kleszczy jest na północ, pierwszy stycznia wyświetla tylko rok. Można sprawdzić, czy cały rok będzie wyświetlany przez coraz kleszczy, a następnie sprawdzanie tego warunku:

function isYear(t) { 
    return +t == +(new Date(t.getFullYear(), 0, 1, 0, 0, 0, 0)); 
} 
var ticks = timeScale.ticks(); 
var willDisplayYear = ticks.some(isYear); 

Kompletna demo obu przypadkach here.

+0

Dzięki za odpowiedź, Lars. Czy masz źródło, w jaki sposób oś czasu decyduje o wyświetlaniu roku? Brzmi bardzo mało prawdopodobne, myślę, że to zależy od zasięgu osi. Kod daje mi błąd - 't.getFullYear' nie jest funkcją. Podobno musi zostać wywołany z obiektu Date. Stworzyłem pierwszy: var date = new Date (t); nowa data (+ t) == nowa data (date.getFullYear(), 0, 0, 0, 0, 0, 0); Kod zwraca "fałsz", mimo że w zaznaczeniach występuje rok. Zaznacziłem odpowiedź Marka jako poprawną, ponieważ wydaje się, że jest to solidniejsze rozwiązanie w obu kierunkach. – speedymcs

+0

Ach masz rację - musisz użyć skali do tego. Naprawię odpowiedź. –

+0

Nadal zwraca wartość "false", nawet jeśli w etykietach zaznaczenia znajdują się pełne lata. Może mieć związek ze strefami czasowymi. – speedymcs