这是我的第一个D3项目(我不是程序员,所以一次学习一切)。
我正在尝试制作一个我已经手工绘制了几年的圆形日历,这是一个巨大的痛苦。
大多数位现在都在工作,但我无法弄清楚如何在这个弧上使文字转为90度。
一旦我翻开文字,我就需要弄清楚如何让它在圆圈周围均匀分布。
我的目标是让它看起来像这个手绘的例子:
以下是目前的情况:
我可能已将文字放在路径上,因此欢迎任何和所有建议。
修改:我在这里创建了一个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>
答案 0 :(得分: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中可见的圆圈侧面,文字会颠倒。您可以通过向rotate
值添加180来解决此问题。修改了jsfiddle here。