0

我需要有关此处提供的解决方案的帮助。

创建简单的功能 40% 折扣

1,1我需要对其进行修改,以便在拆分后推断返回的左右。这是因为如果我不推断,我不能使用返回的分割三次贝塞尔曲线作为 css 过渡。

所以这是我做的测试。请帮忙,因为 real 不匹配 mike way :( 我认为问题是我需要将结果推断为 1,1。虽然我很确定,但我不能简单地将值加倍。

用于获取 Mike 方式的代码是这样的:

var result = split({
    z: .5,
    x: [0, 0.42, 0.58, 1],
    y: [0, 0, 1, 1]
});
alert(result.toSource());
4

2 回答 2

1

前半部分是三次贝塞尔曲线(.42,0,1,1),图形上是http://cubic-bezier.com/#.42,0,1,1

请验证这个假设。(曲线原始端点是css计时函数中的0,0和1,1 )贝塞尔曲线的前半部分[0,0,.42,0,.58,1,1,1]不应该是[ 0,0 .42,0, 1,1, 1,1] 端点是正确的(缩放到 1,1 之后),但是您在那里失去了连续性。

Mike 算法返回的值是正确的。

试试这个可视化来解释为什么你的假设可能是错误的。

您用于拆分的算法是一种众所周知的算法,称为 de Casteljau 算法。这种方法可以用非常简单的方式在几何上表示。查看有关如何在任意点进行这种拆分的动画可视化https://en.wikipedia.org/wiki/B%C3%A9zier_curve

但是,您可能很快就会遇到问题,尝试正确缩放贝塞尔曲线的分割部分以适合单位正方形,端点固定在 0,0 和 1,1。这可能你可以很容易地在纸上尝试。最简单的方法可能是线性缩放贝塞尔曲线的控制点,但在大多数情况下你会得到一条压扁的曲线。

于 2014-05-06T22:00:33.733 回答
0

我创建了 Mike 的 split 函数的修改版本,因此它适合一个单位正方形 :) 它使用 hkrish 的指针来进行坐标归一化。

只需将参数设置fitUnitCell为true。:)

function splitCubicBezier(options) {
  var z = options.z,
      cz = z-1,
      z2 = z*z,
      cz2 = cz*cz,
      z3 = z2*z,
      cz3 = cz2*cz,
      x = options.x,
      y = options.y;

  var left = [
    x[0],
    y[0],
    z*x[1] - cz*x[0], 
    z*y[1] - cz*y[0], 
    z2*x[2] - 2*z*cz*x[1] + cz2*x[0],
    z2*y[2] - 2*z*cz*y[1] + cz2*y[0],
    z3*x[3] - 3*z2*cz*x[2] + 3*z*cz2*x[1] - cz3*x[0],
    z3*y[3] - 3*z2*cz*y[2] + 3*z*cz2*y[1] - cz3*y[0]];

  var right = [
    z3*x[3] - 3*z2*cz*x[2] + 3*z*cz2*x[1] - cz3*x[0],
    z3*y[3] - 3*z2*cz*y[2] + 3*z*cz2*y[1] - cz3*y[0],
                    z2*x[3] - 2*z*cz*x[2] + cz2*x[1],
                    z2*y[3] - 2*z*cz*y[2] + cz2*y[1],
                                    z*x[3] - cz*x[2], 
                                    z*y[3] - cz*y[2], 
                                                x[3],
                                                y[3]];

  if (options.fitUnitSquare) {
    return {
      left: left.map(function(el, i) {
        if (i % 2 == 0) {
          //return el * (1 / left[6])
          var Xmin = left[0];
          var Xmax = left[6]; //should be 1
          var Sx = 1 / (Xmax - Xmin);
          return (el - Xmin) * Sx;
        } else {
          //return el * (1 / left[7])
          var Ymin = left[1];
          var Ymax = left[7]; //should be 1
          var Sy = 1 / (Ymax - Ymin);
          return (el - Ymin) * Sy;
        }
      }),
      right: right.map(function(el, i) {
        if (i % 2 == 0) {
          //xval
          var Xmin = right[0]; //should be 0
          var Xmax = right[6];
          var Sx = 1 / (Xmax - Xmin);
          return (el - Xmin) * Sx;
        } else {
          //yval
          var Ymin = right[1]; //should be 0
          var Ymax = right[7];
          var Sy = 1 / (Ymax - Ymin);
          return (el - Ymin) * Sy;
        }
      })
    }
  } else {
   return { left: left, right: right};
  }
}

var easeInOut = {
  xs: [0, .42, .58, 1],
  ys: [0,   0,   1, 1]
};


var splitRes = splitCubicBezier({
  z: .5,
  x: easeInOut.xs,
  y: easeInOut.ys,
  fitUnitSquare: false
});

alert(splitRes.toSource())
于 2014-10-15T03:24:54.040 回答