2013-06-21 3 views
2

Это мой первый проект D3 (я не программист, поэтому сразу все изучаю).D3.js Как повернуть текст по пути

Я пытаюсь сделать круговой календарь, который я рисовал вручную несколько лет, что является огромной болью.

Большинство бит теперь работает, но я не могу понять, как получить текст, повернутый на 90 градусов на этой дуге.

Как только я получу текст, то мне нужно будет выяснить, как его равномерно распределить по кругу.

Моя цель состоит в том, чтобы заставить его выглядеть следующим образом рисованной пример:

Goal for the text

Вот как это выглядит в настоящее время:

Current text

я, возможно, пошел вниз мертвым заканчивая тем, что размещаем текст по пути, поэтому приветствуем любые предложения.

Edit: Я создал jsFiddle здесь jsfiddle.net/LMF9h/1/

Вот код, который я до сих пор:

<!DOCTYPE html> 
<meta charset="utf-8"> 
<style> 
body { font: 12px Arial;} 
path { 
    stroke: red; 
    stroke-width: 1; 
    fill: none; 
} 
.axis path, 
.axis line { 
    fill: none; 
    stroke: grey; 
    stroke-width: 1; 
    shape-rendering: crispEdges; 
} 
</style> 

<body> 
    <script type="text/javascript" src="d3/d3.v3.js"></script> 

    <script type="text/javascript"> 

var margin = {top: 25, right: 25, bottom: 25, left: 25}, 
width = 950 - margin.left - margin.right, 
height = 950 - margin.top - margin.bottom; 

// Build Day Numbers 
function pad(n) { 
    return (n < 10) ? ("0" + n) : n; 
} 

function getDaysArray(year) { 
    var numDaysInMonth, daysInWeek, daysIndex, index, i, l, daysArray; 

    numDaysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; 
    daysInWeek = ['S', 'M', 'T', 'W', 'T', 'F', 'S']; 
    daysIndex = { 'Sun': 0, 'Mon': 1, 'Tue': 2, 'Wed': 3, 'Thu': 4, 'Fri': 5, 'Sat': 6 }; 

    daysArray = []; 

for (m=0; m < 12; m++) { 
     index = daysIndex[(new Date(year, m, 1)).toString().split(' ')[0]]; 
    for (i = 0, l = numDaysInMonth[m]; i < l; i++) { 
     daysArray.push(pad((i + 1)) + ' ' + daysInWeek[index++]); 
     if (index == 7) index = 0; 
    } 
} 
    return daysArray; 
} 


var year = 2014 

var days = getDaysArray(year) 

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


var arc = d3.svg.arc() 
    .innerRadius(850) 
    .outerRadius(851) 
    .startAngle(0) 
    .endAngle(-pi*1.99999) 

var path = svg.append("path") 
    .attr("d", arc) 
    .attr("id", "path1") 
    .attr("transform", "translate(900,900)") 
    .attr("fill","#f00") 


// Draw lines 
function daysInYear(year) { 
    if(year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)) { 
     // Leap year 
     return 366; 
    } else { 
     // Not a leap year 
     return 365; 
    } 
} 

var dt = new Date(year+"/01/01"); 
var day = dt.getDay(); 
var startrads = (2*pi/daysInYear(year)) * day; 
    //---center point(width,height)--- 
     var cx=width 
     var cy=height 
     var r=850 //--radius-- 
     var radialLines=52 //---create 52 lines--- 
     var angle=2*Math.PI/radialLines //---angle between each line--- 
     var radialPoints=[] 
     for(var k=startrads;k<radialLines;k++) 
     { 
       var x2=r*Math.cos(angle*k)+cx 
       var y2=r*Math.sin(angle*k)+cy 
       radialPoints.push([x2,y2]) 
     } 
    //---your d3 SVG parent element--- 
     svg.selectAll("line")//---an empty selection--- 
     .data(radialPoints) 
     .enter().append("svg:line") 
     .attr("x1",cx) 
     .attr("y1",cy) 
     .attr("x2",function(p){return p[0]}) 
     .attr("y2",function(p){return p[1]}) 
     .attr("stroke","red"); 



// Add day labels. 
var text1 = svg.append("text"); 


text1 
    .selectAll("body") 
    .data(days) 
    .enter() 
    .append("textPath") 
    .attr("xlink:href","#path1") 
    .text(function(d) { return d; }); 



    </script> 

</body> 

ответ

1

Чтобы получить текст справа, вам нужно просто вычислить его положение и поворот в так же, как вы вычисляете конец радиальных линий. Код будет что-то вроде

svg.selectAll("text").data(days).enter() 
.append("text") 
.attr("transform", function(d, i) { 
    return "translate(" + (850*Math.cos(i*2*Math.PI/365)+width) + 
      "," + (850*Math.sin(i*2*Math.PI/365)+height) + ")" + 
      "rotate(" + (i*360/365) + ")"; 
}) 
.text(function(d) { return d; }); 

Обратите внимание, что на стороне круга, который виден в вашем jsfiddle, текст будет перевернутым. Вы можете исправить это, добавив 180 к значению rotate. Изменено jsfiddle here.