Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
D3.js D3三角形定位到精确点_D3.js_Svg_Position - Fatal编程技术网

D3.js D3三角形定位到精确点

D3.js D3三角形定位到精确点,d3.js,svg,position,D3.js,Svg,Position,我正在尝试创建一个D3图形,它看起来像Illustrator创建的设计(好的图像1),但就定位而言,我能得到的最接近的是第二个(坏的图像2) 我对D3和创建SVG都是新手,所以我可能在这方面做的都是错的。下面的代码是我在网上找到的。看起来我不能直接使用css定位来调整元素本身的定位?我试着通过html和JQuery使用$(.myClass.css…)添加类,但我所做的一切都没有效果。唯一有效的方法是变换,但它很难看,如第二张图所示 var margin = { left:10, right:10

我正在尝试创建一个D3图形,它看起来像Illustrator创建的设计(好的图像1),但就定位而言,我能得到的最接近的是第二个(坏的图像2)

我对D3和创建SVG都是新手,所以我可能在这方面做的都是错的。下面的代码是我在网上找到的。看起来我不能直接使用css定位来调整元素本身的定位?我试着通过html和JQuery使用$(.myClass.css…)添加类,但我所做的一切都没有效果。唯一有效的方法是变换,但它很难看,如第二张图所示

var margin = { left:10, right:10, top:10, bottom:10 };

var width = 400 - margin.left - margin.right,
    height = 450 - margin.top - margin.bottom;

var g = d3.select("#pyramid-chart-area")
    .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 + ")");

d3.json("../data/pyramid_hp.json").then(function(data){
    data.forEach(function(d){
        d.hp = +d.hp;
    });

    var x = d3.scaleBand()
        .domain(data.map(function(d){ return d.hp; }))
        .range([0, width])
        .paddingInner(0.3)
        .paddingOuter(0.3);

    var y = d3.scaleLinear()
        .domain([0, d3.max(data, function(d){
            return d.hp;
        })])
        .range([height, 0]);

    var xAxisCall = d3.axisBottom(x);
    g.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0, " + height + ")")
        .call(xAxisCall)
        .selectAll("text")
            .attr("y", "10")
            .attr("x", "-5")
            .attr("text-anchor", "end")
            .attr("transform", "rotate(-40)");

    var yAxisCall = d3.axisLeft(y)
        .ticks(3)
        .tickFormat(function(d){
            return d;
        });


    g.append("g")
        .attr("class", "y-axis")
        .call(yAxisCall);


    var arc = d3.symbol().type(d3.symbolTriangle)
                .size(function(d){ return scale(d.hp); });

    var scale = d3.scaleLinear()
        .domain([0, 5])
        .range([0, width]);

    var colors = d3.scaleLinear()
    .domain(d3.extent(data, function(d) {return d.hp}))
    .range([
        '#ffffff',        
        '#303030'        
    ]);

    var group = g.append('g')
                .attr('transform','translate('+ 192 +','+ 320 +')')
                .attr('class', 'triangle-container');


    var line = group.selectAll('path')
            .data(data)
            .enter()
            .append('path')
            .attr('d', arc)
            // .attr('fill',function(d){ return colorscale(d.hp); })
            .attr('fill', d => colors(d.hp))
            .attr('stroke','#000')
            .attr('stroke-width', 1)
            .attr('class', 'triangle')
            .attr('transform',function(d,i){ return "translate("+ (i * 20) +","+(i * 10)+")"; });

您可以定位符号,但其复杂的符号大小表示面积,因为rioV8注释符号是通过其中心定位的。但是如果你能算出三角形的性质,我们就可以相对容易地放置它

对于等边三角形,您需要知道给定边的长度以及质心的高度(即三角形高度/3)。因此,这些功能可能很有用:

// get length of a side/width of upright equilateral triangle from area:
function getWidth(a) {
    return Math.sqrt(4 * a / Math.sqrt(3));
}
// get height of the triangle from length of a side
function getHeight(l) {
    return Math.sqrt(3)*l/2;
}
利用质心的高度,我们可以将圆定位在我们想要的位置,例如:

y = SVGheight - SymbolHeight/3 - marginBottom;
这里不需要缩放

每个符号的x值确实需要一些缩放,以便根据您的喜好进行排列。下面我使用一个范围为
[width/10,0]
的线性刻度,分母将改变水平倾斜。在这种情况下,可能有更好的方法来微调

通过此操作,您可以达到预期的效果:

为了简单起见,下面我使用的数据(因为您没有显示任何数据)表示像素区域-如果缩放区域,则必须将缩放比例考虑到高度和宽度计算中。我也在每个三角形的顶部加上了圆圈,以备标签使用,因为我们知道三角形的尺寸,现在这很简单

var-margin={left:10,right:10,top:10,bottom:10};
变量宽度=400-margin.left-margin.right,
高度=300-margin.top-margin.bottom;
变量g=d3。选择(“主体”)
.append(“svg”)
.attr(“宽度”,宽度+边距。左侧+边距。右侧)
.attr(“高度”,高度+边距。顶部+边距。底部)
.附加(“g”)
.attr(“转换”、“平移”(“+margin.left+”,“+margin.top+”)
风险值数据=[
{a:40000},
{a:30000},
{a:20000},
{a:10000}
];
函数getWidth(a){
返回Math.sqrt(4*a/Math.sqrt(3));
}
函数getHeight(l){
返回数学sqrt(3)*l/2;
}
data.forEach(函数(d){
d、 w=getWidth(d.a);
d、 h=高度(d.w);
})
var x=d3.scaleLinear()
.domain(d3.extent(数据,函数(d){返回d.w;}))
.范围([宽度/10,0]);
var arc=d3.symbol().type(d3.symbolTriangle)
.size(函数(d){返回d.a;});
var colors=d3.scaleLinear()
.domain(d3.extent(数据,函数(d){return d.a}))
.范围(['#ffffff','#303030']);
var group=g.append('g')
.attr('transform','translate('+width/2+',0'))
.attr('class','triangle container');
var line=group.selectAll('path')
.数据(数据)
.输入()
.append('路径')
.attr('d',弧)
.attr('fill',d=>颜色(d.a))
.attr('class','triangle')
.attr('transform',函数(d,i){返回“translate”(+x(d.w)+)”,“+(height-d.h/3-margin.bottom)+”);};
变量圆=组。选择全部(“圆”)
.数据(数据)
.输入()
.附加(“圆圈”)
.attr(“cx”,函数(d){返回x(d.w);})
.attr(“cy”,函数(d){返回高度-d.h-margin.bottom;})
.attr(“r”,3)

您必须基于
x()
y()
创建自己的三角形形状路径生成器。d3生成的形状很难定位和获得正确的大小(它们是相对于“质心”建模的)。如果json文件中的值不是按降序排序的呢?你的小金字塔被大金字塔遮住了。@rioV8啊,我明白了。在一次尝试中,我使用点创建了一条路径,但在使用数据正确缩放三角形时遇到了问题。不过我会朝那个方向走。关于顺序,我将对数据进行排序,但我只是想先弄清楚布局和基本设置。谢谢你的信息!您的颜色域应该是
.domain([0100])
同一
hp
的颜色不同将是非常奇怪的,因为
hp
值中的分布较少。这个答案优雅而令人敬畏。我相信你帮我省了好几天在沮丧中放弃或想出乱七八糟的事情之前撞我的头。我只是根据我的项目和数据调整了它,它工作得非常好。非常感谢你。