D3.js如何在路径上旋转文本 [英] D3.js How to rotate Text on a path

查看:92
本文介绍了D3.js如何在路径上旋转文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的第一个D3项目(我不是程序员,所以要一次学习所有东西).

This is my first D3 project (I'm not a programmer, so learning everything at once).

我正在尝试制作已经手工绘制数年的圆形日历,这是一个巨大的痛苦.

I'm trying to make a circular calendar that I've been drawing by hand for several years, which is a huge pain.

大多数位现在都可以使用,但是我不知道如何在此弧线上将文本旋转90度.

Most of the bits are now working, but I can't figure out how to get the text turned 90 degrees on this arc.

一旦我打开了文字,那么我就需要弄清楚如何使它在圆上等距分布.

Once I get the text turned, then I'll need to figure out how to get it spaced equally around the circle.

我的目标是使它看起来像下面的手绘示例:

My goal is to get it to look like this hand drawn example:

这是当前的样子:

通过将文本放在路径上,我可能陷入了死胡同,所以欢迎任何建议.

I may have gone down a dead end by placing the text on a path, so any and all suggestions welcome.

我在这里 jsfiddle.net/LMF9h/1/创建了一个jsFiddle

这是我到目前为止的代码:

Here is the code I have so far:

<!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>

推荐答案

要使文本正确,您只需要以计算径向线末端的相同方式来计算其位置和旋转度即可.代码就像

To get the text right, you simply need to calculate its position and rotation in the same way that you're calculating the end of the radial lines. The code would be something like

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 此处.

Note that on the side of the circle that is visible in your jsfiddle, the text would be upside down. You can fix this by adding 180 to the rotate value. Modified jsfiddle here.

这篇关于D3.js如何在路径上旋转文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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