问题
I need help with the solution provided here.
Create easy function 40% off set
I need to modify it so that the returned left and rights are extrapolated to 1,1
after splitting. This is because if I don't extrapolate, I can't use the returned split cubic-bezier as a css transition.
So this is the test I did. Please help because real does not match mike way :( I think the issue is I need to extrapolate the result to 1,1. I can't simply double the values though I'm pretty sure.
- REAL
ease-in-out
iscubic-bezier(.42,0,.58,1)
and graphically is http://cubic-bezier.com/#.42,0,.58,1- first half is
ease-in
which iscubic-bezier(.42,0,1,1)
and graphically is http://cubic-bezier.com/#.42,0,1,1 - seoncd half is
ease-out
which iscubic-bezier(0,0,.58,1)
and grpahically is http://cubic-bezier.com/#0,0,.58,1
- The function posted above returns the following
ease-in-out
is same as this is starting point- first half, left, is given to be
cubic-bezier(0.21, 0, 0.355, 0.25)
and graphically is http://cubic-bezier.com/#.21,0,.35,.25- code returned:
left:[0, 0, 0.21, 0, 0.355, 0.25, 0.5, 0.5]
- code returned:
- second half, right, is given to be
cubic-bezier(0.645, 0.75, 0.79, 1)
and graphically is http://cubic-bezier.com/#.64,.75,.79,1- code returned
right:[0.5, 0.5, 0.645, 0.75, 0.79, 1, 1, 1]
- code returned
Code used for getting it the Mike way is this:
var result = split({
z: .5,
x: [0, 0.42, 0.58, 1],
y: [0, 0, 1, 1]
});
alert(result.toSource());
回答1:
first half is ease-in which is cubic-bezier(.42,0,1,1) and graphically is http://cubic-bezier.com/#.42,0,1,1
Please verify this assumption. (curves original end points are 0,0, and 1,1 in a css timing function) The first half of the bezier curve [0,0, .42,0, .58,1, 1,1] should not be [0,0 .42,0, 1,1, 1,1] The end points are correct (after scaling to 1,1), but you have lost continuity there.
The values returned by Mike's algorithm is correct.
Try this visualisation for an explanation on why your assumption might be wrong.
The algorithm you are using to split is a well known algorithm called de Casteljau algorithm. This method can be geometrically expressed in a very simple manner. Check out the animated visualisations on how this splitting at any arbitrary point is possible https://en.wikipedia.org/wiki/B%C3%A9zier_curve.
However, You may soon hit an issue trying to correctly scale a split portion of a bezier curve to fit in a unit square, with endpoints fixed at 0,0 and 1,1. This probably you can try out quite easily on paper. The easiest way probably is to just linearly scale the control points of the bezier, you will get a squashed curve in most cases though.
回答2:
I created a modified version of Mike's split function so it fits it to a unit square :) It uses hkrish's pointers to do coordinate normalization.
Just set parameter fitUnitCell
to 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())
来源:https://stackoverflow.com/questions/23475372/extrapolate-split-cubic-bezier-to-1-1