[css3-images] Proposed Gradients changes

This is an announcement of my planned changes to gradients in the
Image Values spec (which turned out to be minor), based on my previous
discussions with the group, particularly Brad and Simon.  If nobody
objects in a few days I'll make the edits.


Simplify linear-gradient
------------------------

In retrospect, allowing you to mix together endpoints and angles was a
bad idea.  There's basically no use-case, so it's just unneeded
complexity in the descriptions and implementations.

I'll be changing the syntax so that you can provide *either* one or
two endpoints *or* an angle, not both.  The one-endpoint syntax and
angle syntax will work identically to how they do now; the
two-endpoint syntax should be obvious, and its omission was frankly
just an oversight.

I'll also be very slightly tweaking the treatment of an angle value.
This will have no effect on the display of gradients, but will affect
interpolating them (see below).


Complete radial-gradient
------------------------

With the addition of the two-endpoint form of linear-gradients, you
can now explicitly express any possible linear gradient.  The same is
not true of radial gradients, which currently rely very extensively on
implicitly sizing things relative to the box's shape and size.

I'll be changing the syntax so that the second argument, which
currently determines the shape and size, can instead take two lengths,
which determine the lengths of the ellipse axes in the x and y
directions.  Combined with the existing ability to specify an
arbitrary center point in the first argument, this will allow you to
express any possible radial gradient.  (The current "<shape> <size>"
value will still be allowed too, of course.)


Fixing interpolation
--------------------

Simon was concerned that there's no clear way to interpolate between
two gradients that aren't specified in the same way - for example,
transitioning between two linear-gradient backgrounds, one specified
as "left" and the other with "45deg".

With the above additions I have fixed this issue.  When transitioning
a gradient image, first convert the two endpoint forms into the
explicit forms given above (for linear gradients, the two-point
syntax; for radial gradient, the point-and-two-lengths syntax).  Then,
naively interpolate each component separately.

This isn't perfect in some cases - for example, the midpoint between
"0deg" and "90deg" for a linear-gradient background on a 100px by
200px box is *not* a "45deg" gradient, but rather a "25px 150px to
75px 50px" gradient, which is angled at about 63deg and has endpoints
inside the box.

I don't believe this is a problem in practice - I believe that
rotating a gradient in a transition is a somewhat odd thing to do.  As
well, this can be addressed with additions to Transitions to allow
keyframes to be used for a transition.  (This has been previously
discussed, and is something I'll be heavily lobbying for in
Transitions 4.)


Intermediate Forms during interpolation
---------------------------------------

Simon was additional concerned with what value to return for the
intermediate forms while a gradient was being interpolated.

There are two possible approaches.  The first is simply to return the
explicit-form gradient that was calculated for rendering purposes, per
the previous section.  This has a major downside, though, that
round-tripping it changes the essentially nature of the gradient.  For
example, if the two endpoint forms were "radial-gradient(ellipse
contain, ...)" and "radial-gradient(ellipse cover, ..)", both change
shape/size if the view box does, but an explicit intermediate form
(something like "radial-gradient(center center, 100px 50px, ...)")
won't.

So, I will instead be pursuing a slightly abstracted approach.  I'll
introduce an "interpolate()" function which takes two images and a
percentage, and represents the interpolated image between them at that
percentage of interpolation.  The interpolate() function can exist as
a specified or computed value; it is converted into an explicit form
per the previous section at used-value time.

For now interpolate() will only be defined for gradient arguments, but
it can potentially be used for *any* interpolable value.  If this is
interesting, we can lift the general definition out into Transitions,
and change Image Values to just specify its effect when passed
gradients.

To provide a concrete example, say you are transitioning the
background-image property, which is changing from
"radial-gradient(ellipse contain, white, black)" to
"radial-gradient(ellipse cover, white, black)".  If the author queries
for the animated value 20% of the way through the transition, the
value returned to them is "interpolate(radial-gradient(ellipse
contain, white, black), radial-gradient(ellipse cover, white, black),
20%)".

Any objections?  If not, I'll make the edits next week.

~TJ

Received on Thursday, 18 November 2010 02:07:12 UTC