d3 + vx反应曲线在每个数据点处平坦 [英] d3 + vx react chart curve flat at each data point

查看:74
本文介绍了d3 + vx反应曲线在每个数据点处平坦的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试按照 https://dribbble.com/shots/2673159-Funnel-UI-concept/attachments/538068

我查看了d3/vx提供的所有曲线,但似乎没有一条曲线出现在每个不同的步骤之间,并且数据点处的线是平坦的.我是否缺少类似于上面的曲线类型?如果不是,并且需要自定义曲线,那么是否有地方比d3文档更深入地描述了如何实现自定义曲线?

I've looked through all the curves provided by d3/vx and none of them seem to have the curve happen between each distinct step with the line flat at the data point. Is there a curve type i'm missing that would look similar to the above? If not and it needs a custom curve, is there somewhere with a more in-depth description of how to implement custom curves than the d3 docs?

推荐答案

没有标准曲线可以做到这一点;但是,如果有需要,可以重复添加其他点以强制将标准d3曲线平坦化.例如,阶段之前和之后的相加点将更改为具有相同的y值.

There is no standard curve that does this; however, it may be possible if duplicating adding additional points to coerce a standard d3 curve to be flat where needed. For example, adding points before and after the stage change with the same y value.

但是,自定义曲线可能会起作用,并且无需进行数据处理.贝塞尔曲线应该可以解决问题.具有起点,终点和控制点的东西如下:

However, a custom curve could work and avoid the need for data manipulation. A bezier curve should do the trick. With origin, destination, and control points something like:

来自此codepen

要实现这一想法,我们可以将标准曲线(例如d3.curveLinear)中的点函数替换为绘制贝塞尔曲线的点函数.

To implement this idea we can replace the point function in a standard curve, such as d3.curveLinear with one that draws a bezier curve.

使用d3.curveLinear的点函数进行比较:

The point function of d3.curveLinear for comparison:

  function(x, y) {
    x = +x, y = +y;
    switch (this._point) {
      case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
      case 1: this._point = 2; // proceed
      default: this._context.lineTo(x, y); break;
    }

新点功能:

  function(x,y) {
    x = +x, y = +y;
    switch (this._point) {
      case 0: this._point = 1; 
        this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y);
        this.x0 = x; this.y0 = y;        
        break;
      case 1: this._point = 2;
      default:  
        var x1 = this.x0 * 0.5 + x * 0.5;
        this._context.bezierCurveTo(x1,this.y0,x1,y,x,y); // bezierCurveTo(controlPoint1X,controlPoint1Y,controlPoint2X,controlPoint2Y,endPointX,endPointY)
        this.x0 = x; this.y0 = y;        
        break;
    }
  }
  return custom;
}

我为每个控制点使用相同的x值,这可能并不理想,因为它们的末端可能不够平坦,但很容易更改

我们可以使用d3.curveLinear并替换为这个新的点函数来创建自定义曲线:

We can create a custom curve by using d3.curveLinear and substituting in this new point function:

var curve = function(context) {
  var custom = d3.curveLinear(context);
  custom._context = context;
  custom.point = function(x,y) {
    x = +x, y = +y;
    switch (this._point) {
      case 0: this._point = 1; 
        this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y);
        this.x0 = x; this.y0 = y;        
        break;
      case 1: this._point = 2;
      default: 
        var x1 = this.x0 * 0.5 + x * 0.5;
        this._context.bezierCurveTo(x1,this.y0,x1,y,x,y); 
        this.x0 = x; this.y0 = y;        
        break;
    }
  }
  return custom;
}

这很容易工作:

var curve = function(context) {
  var custom = d3.curveLinear(context);
  custom._context = context;
  custom.point = function(x,y) {
    x = +x, y = +y;
    switch (this._point) {
      case 0: this._point = 1; 
        this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y);
        this.x0 = x; this.y0 = y;        
        break;
      case 1: this._point = 2;
      default: 
        var x1 = this.x0 * 0.5 + x * 0.5;
        this._context.bezierCurveTo(x1,this.y0,x1,y,x,y);
        this.x0 = x; this.y0 = y;        
        break;
    }
  }
  return custom;
}

var data = [
 [10,10],
 [160,50],
 [310,100]
];

var line = d3.line()
  .curve(curve);
  
d3.select("svg")
  .append("path")
  .attr("d",line(data));
  
d3.select("svg")
  .selectAll("circle")
  .data(data)
  .enter()
  .append("circle")
  .attr("transform", function(d) {
    return "translate("+d+")";
  })
  .attr("r",3)

path {
  fill: none;
  stroke: black;
  stroke-width:1px;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="500" height="500"></svg>

这是一个区域演示,它为每个阶段绘制一个漏斗. 根据您的数据,这可能是可取的,也可能不是最佳的.我的假数据是按阶段构造的,因此最容易分别绘制每个阶段.将所有阶段统一到一个路径/区域可能要困难一些.

And here's an areal demonstration that draws a funnel for each stage. Depending on your data this may or may not be preferable. My fake data is structured by stage, so it is easiest to draw each stage individually. Unifying all the stages into one path/area may be a bit more difficult.

var curve = function(context) {
  var custom = d3.curveLinear(context);
  custom._context = context;
  custom.point = function(x,y) {
    x = +x, y = +y;
    switch (this._point) {
      case 0: this._point = 1; 
        this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y);
        this.x0 = x; this.y0 = y;        
        break;
      case 1: this._point = 2;
      default: 
        var x1 = this.x0 * 0.5 + x * 0.5;
        this._context.bezierCurveTo(x1,this.y0,x1,y,x,y);
        this.x0 = x; this.y0 = y;        
        break;
    }
  }
  return custom;
}

var data = [
  {stage:1, start:1,end:0.5},
  {stage:2, start:0.5,end:0.2},
  {stage:3, start:0.2,end:0.1},
  {stage:4, start:0.1,end:0.005}
]

var yRangeMax = 100;
var y = d3.scaleLinear()
  .range([yRangeMax,0]);
  
var x = d3.scaleBand()
  .range([50,400])
  .domain(data.map(function(d) {
    return d.stage;
  }))

var svg = d3.select("svg");
 
var area = d3.area()
  .curve(curve)
  .y1(function(d) { return yRangeMax*2-d[1]; })
  .y0(function(d) { return d[1]; })

svg.selectAll(null)
  .data(data)
  .enter()
  .append("path")
  .attr("d", function(d) {
    var p1 = [x(d.stage),y(d.start)]
    var p2 = [x(d.stage)+x.step(),y(d.end)]
    return area([p1,p2])
  })

path{
  stroke: #bbb;
  stroke-width: 1px;
  fill:#ccc;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.6.0/d3.min.js"></script>
<svg width="600" height="400"></svg>

关于自定义曲线的指导,我没有看到很多资源.但是,这些答案( a b )可能会有所帮助.

As for guidance on custom curves, there are not a lot of resources that I've seen. However, these answers (a,b) might be of some assistance.

这篇关于d3 + vx反应曲线在每个数据点处平坦的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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