d3.js用户查看器图表 [英] d3.js User viewer chart

查看:96
本文介绍了d3.js用户查看器图表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

开发一个图表,为用户提供查看他们的视觉效果。内圈显示匹配(用户关注/正在关注),下一个响铃 - 用户关注其他人,最后一个响铃 - 用户的关注者。





我嘲笑了cy,cx位置,但是如何定位他们像这样 - 将橙色圆圈绑定到各个圆形象限中?



http://jsfiddle.net/NYEaX/281/

  sampleSVG.selectAll(circle)
.data(dataset)
.enter()。append(circle)
.style(stroke,gray)
.style(fill,orange)
.attr(r,6)
.attr(cx,function(d,i){return 2 + i * 80)})
.attr(cy,function(d,i){return(i * 80)});


解决方案

最新代码 - http://jsfiddle.net/NYEaX/336/ (注意:仅仅是概念性的,高度 b> -optimized!)



我不知道d3是否可以自动做到这一点,但你总是可以找出 i> y 的位置。



一种方法是随机放置每个点,直到它正确放置。这绝对不是最快的方法,但如果你没有太多的点放置,它可能仍然足够好。



假设你的最小的圆半径 和中心点( x y / i>和( x m m i>)和您最大的圈子 r l 和( x l y l ),然后您可以通过比较其距离来检查点所在或不落入哪个圆圆的中心点到圆的半径:



例如,如果要在中间圆圈中放置一个点:




  • 选择随机位置( x y i>),以便它可以落在该圆中的任何位置:

    • x m   -   r m x x m   +  r m

    • y m   -   m y y m   +  r m
    • b> x   -   x m 2 +( y   -   y 2   r m 2
    • 如果不是这样,请开始并选择不同的( x y

    • <
    • 确保在较小的圆圈内:

      • 检查( x   -   x 2 + >   -   > 重新开始并选择不同的( x y




    现在你有一个随机点在中间圈内,但不是小圈子。将一个放入大圆中的方式相同(只需替换 x m y sub> r m > r l 以及 x y x m / b> m r b> )。要将点放在最小的圆圈中,您只需检查第一个条件(使用 x m y m r m s y



    现在,您可以停止这里(但是根据您的点密度,这可能会不是最漂亮的图片),或者,你可以尝试使点相对于彼此更好一点。一种方法是:




    • 循环所有点( x 1 ) / sub> , y n


    • 在这两个中,找出哪个更接近它的邻居
    • / li>
    • 移除此点,然后使用上述方法随机重新放置

    • 重复此操作次数或直到获得任何两个点是可以接受的(我只想尝试什么效果最好)



    通过调整上面的两个校验方程,通过替换 r m 2 ,在圆圈的边框周围添加一些空白, >与   -   d 2 r s 2   +  d 2



    有很多方法可以优化这个简单的方法:例如,你可以选择你的初始( x y α 然后从中计算 x y ,以确保不会选择不在圆内的点你要。只要确保从正确加权的分布中选择 r ,即可 x y 结果是均匀分布。此外,您可以在放置点时立即检查从新放置的点到其所有邻居的距离,而不是在结尾处的第二步。例如,为每个点找到10个地点,然后总是选择离它最近的邻居距离最大的那些地点。



    UPDATE



    这是它看起来像不用担心点间距: http://jsfiddle.net/NYEaX/328/



    实现点放置的相关部分位于此处(变量名称已更改为与上述匹配) :

      function getXCoordinateInCircleSection(i,xm,ym,rm,xs,ys,rs){
    done = false ;
    while(!done){
    x = getRandomCoordinate(xm-rm,xm + rm);
    y = getRandomCoordinate(ym-rm,ym + rm);
    done = true;
    if((x-xm)*(x-xm)+(y-ym)*(y-ym)>(rm-10)*(rm-10)
    if((x-xs)*(x-xs)+(y-ys)*(y-ys)< =(rs + 10)*(rs + 10)
    }
    window.ys [i] = y;
    return x;
    }

    function getYCoordinateInCircleSection(i){
    return window.ys [i];
    }

    改进的点间距: http://jsfiddle.net/NYEaX/329/



    (这两个都是基于由@TheOldCounty创建的 http://jsfiddle.net/NYEaX/326/


    Developing a chart which will provide a user a visual for who has viewed them. The inner circle shows matches (user following/being followed), the next ring - user following others, the last ring - the followers of the user.

    I've mocked the cy, cx positions, but what would it take to position them like this - to bound the orange circles into the various circle quadrants?

    http://jsfiddle.net/NYEaX/281/

    sampleSVG.selectAll("circle")
        .data(dataset)
            .enter().append("circle")
            .style("stroke", "gray")
            .style("fill", "orange")
            .attr("r", 6)
            .attr("cx", function(d, i){return 2 + (i*80)})
            .attr("cy", function(d, i){return (i*80)});
    

    解决方案

    "LATEST CODE" - http://jsfiddle.net/NYEaX/336/ (Note: Merely conceptual, highly non-optimized!)

    I'm not sure if d3 can do this automatically somehow, but you can always just figure out the x and y positions of your dots yourself with some math:

    One way to do it is to just place each dot randomly until it sits correctly. This is definitely not the fastest approach, but if you don't have too many dots to place, it might still be way good enough.

    Let's say your smallest circle has radius rs and center point (xs, ys) and your middle circle rm and (xm, ym) and your largest circle rl and (xl, yl), then you can check which circle a dot does or does not fall into by comparing its distance from the center-point of the circle to the radius of that circle:

    For example, if you want to place a dot into the middle circle:

    • Pick a random position (x, y) so that it can fall anywhere in that circle:
      • xm - rmxxm + rm
      • ym - rmyym + rm
    • Make sure it actually is inside the circle:
      • Check (x - xm)2 + (y - ym)2rm2
      • If this is not the case, start over and pick a different (x, y)
    • Make sure it is not inside the smaller circle:
      • Check (x - xs)2 + (y - ys)2 > rs2
      • If this is not the case, start over and pick a different (x, y)

    Now you have some random point that is inside the middle circle, but not the small one. Placing one into the larger circle works the same way (just replace xm, ym, and rm with xl, yl, and rl as well as xs, ys, and rs with xm, ym, and rm). To place a dot into the smallest circle, you only need to check the first condition (with xm, ym, and rm replaced by xs, ys, and rs).

    Now, you can either stop here (but depending on your dot-density, this might not be the prettiest picture) or, you can try to space the dots a little nicer relative to each other. One way to do this is the following:

    • Loop over all dots (x1, y1) ... (xn, yn)
    • Calculate the distance from each dot to each other dot
    • Find the two that are closest together
    • Of those two, figure out which one is closer to its neighbors
    • Remove this dot and place it again randomly using the method described above
    • Either repeat this some number of times or until you get a minimum distance between any two dots that is acceptable (I would just try out what works best)

    By adjusting the two check-equations above, you can also add a little bit of clearance around the borders of your circles that the dots will avoid, by replacing rm2 with (rm - d)2 and rs2 with (rs + d)2.

    There are definitely a bunch of ways to optimize this simple approach: For example you can pick your initial (x, y) position in polar coordinates by choosing r and α instead and then calculating x and y from them to make sure that you never pick a dot that is not inside the circle you want. Just make sure you pick r from a correctly weighted distribution so that x and y turn out to be uniformly distributed. Also, you can check the distance from a newly placed dot to all its neighbors immediately when placing the dot rather than in a second step at the end. For example, find 10 places for each dot and then always pick the one out of those with the largest distance to its closest neighbor.

    UPDATE

    And this is what it looks like without worrying about dot spacing: http://jsfiddle.net/NYEaX/328/

    The relevant section implementing the dot placement is here (variable names changed to match above):

    function getXCoordinateInCircleSection(i, xm, ym, rm, xs, ys, rs) {
        done = false;
        while (!done) {
            x = getRandomCoordinate(xm-rm, xm+rm);
            y = getRandomCoordinate(ym-rm, ym+rm);
            done = true;
            if ((x-xm)*(x-xm)+(y-ym)*(y-ym) >  (rm-10)*(rm-10)) done = false;
            if ((x-xs)*(x-xs)+(y-ys)*(y-ys) <= (rs+10)*(rs+10)) done = false;
        }
        window.ys[i] = y;
        return x;
    }
    
    function getYCoordinateInCircleSection(i) {
        return window.ys[i];
    }
    

    And with improved dot spacing: http://jsfiddle.net/NYEaX/329/

    (Both of these are based on http://jsfiddle.net/NYEaX/326/ created by @TheOldCounty)

    这篇关于d3.js用户查看器图表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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