mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 1598156 - Part 6: Build path for basic shapes. r=emilio
Basically, the fuzzy happens because the direction angle in circle(), ellipse(), and inset() can not be equal to the degree perfectly (due to the arc drawing implementation and the anti-alias around the element), so we need some tolerance. And drop offset-path-shape(-ref).html because it has been removed from the upstream repo. Differential Revision: https://phabricator.services.mozilla.com/D179630
This commit is contained in:
parent
48208132f5
commit
99508a94f6
@ -509,8 +509,8 @@ AnimationStorageData AnimationHelper::ExtractAnimations(
|
||||
|
||||
RefPtr<gfx::PathBuilder> builder =
|
||||
MotionPathUtils::GetCompositorPathBuilder();
|
||||
storageData.mCachedMotionPath =
|
||||
MotionPathUtils::BuildPath(offsetPath.AsSVGPathData(), builder);
|
||||
storageData.mCachedMotionPath = MotionPathUtils::BuildSVGPath(
|
||||
offsetPath.AsSVGPathData(), builder);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -262,20 +262,18 @@ Maybe<ResolvedMotionPathData> MotionPathUtils::ResolveMotionPath(
|
||||
double directionAngle = 0.0;
|
||||
gfx::Point point;
|
||||
if (aPath.IsShape()) {
|
||||
const auto& path = aPath.AsShape();
|
||||
if (!path.mGfxPath) {
|
||||
// Empty gfx::Path means it is path('') (i.e. empty path string).
|
||||
return Nothing();
|
||||
}
|
||||
const auto& data = aPath.AsShape();
|
||||
RefPtr<gfx::Path> path = data.mGfxPath;
|
||||
MOZ_ASSERT(path, "The empty path is not allowed");
|
||||
|
||||
// Per the spec, we have to convert offset distance to pixels, with 100%
|
||||
// being converted to total length. So here |gfxPath| is built with CSS
|
||||
// pixel, and we calculate |pathLength| and |computedDistance| with CSS
|
||||
// pixel as well.
|
||||
gfx::Float pathLength = path.mGfxPath->ComputeLength();
|
||||
gfx::Float pathLength = path->ComputeLength();
|
||||
gfx::Float usedDistance =
|
||||
aDistance.ResolveToCSSPixels(CSSCoord(pathLength));
|
||||
if (path.mIsClosedIntervals) {
|
||||
if (data.mIsClosedIntervals) {
|
||||
// Per the spec, let used offset distance be equal to offset distance
|
||||
// modulus the total length of the path. If the total length of the path
|
||||
// is 0, used offset distance is also 0.
|
||||
@ -291,8 +289,14 @@ Maybe<ResolvedMotionPathData> MotionPathUtils::ResolveMotionPath(
|
||||
usedDistance = clamped(usedDistance, 0.0f, pathLength);
|
||||
}
|
||||
gfx::Point tangent;
|
||||
point = path.mGfxPath->ComputePointAtLength(usedDistance, &tangent);
|
||||
directionAngle = (double)atan2(tangent.y, tangent.x); // In Radian.
|
||||
point = path->ComputePointAtLength(usedDistance, &tangent);
|
||||
// Basically, |point| should be a relative distance between the current
|
||||
// position and the target position. The built |path| is in the coordinate
|
||||
// system of its containing block. Therefore, we have to take the current
|
||||
// position of this box into account to offset the translation so it's final
|
||||
// position is not affected by other boxes in the same containing block.
|
||||
point -= NSPointToPoint(data.mCurrentPosition, AppUnitsPerCSSPixel());
|
||||
directionAngle = atan2((double)tangent.y, (double)tangent.x); // in Radian.
|
||||
} else if (aPath.IsRay()) {
|
||||
const auto& ray = aPath.AsRay();
|
||||
MOZ_ASSERT(ray.mRay);
|
||||
@ -360,6 +364,12 @@ Maybe<ResolvedMotionPathData> MotionPathUtils::ResolveMotionPath(
|
||||
angle, shift});
|
||||
}
|
||||
|
||||
static inline bool IsClosedPath(const StyleSVGPathData& aPathData) {
|
||||
return !aPathData._0.AsSpan().empty() &&
|
||||
aPathData._0.AsSpan().rbegin()->IsClosePath();
|
||||
}
|
||||
|
||||
// Generate data for motion path on the main thread.
|
||||
static OffsetPathData GenerateOffsetPathData(const nsIFrame* aFrame) {
|
||||
const StyleOffsetPath& offsetPath = aFrame->StyleDisplay()->mOffsetPath;
|
||||
if (offsetPath.IsNone()) {
|
||||
@ -389,13 +399,36 @@ static OffsetPathData GenerateOffsetPathData(const nsIFrame* aFrame) {
|
||||
aFrame->GetProperty(nsIFrame::OffsetPathCache());
|
||||
MOZ_ASSERT(gfxPath || pathData._0.IsEmpty(),
|
||||
"Should have a valid cached gfx::Path or an empty path string");
|
||||
return OffsetPathData::Shape(pathData, gfxPath.forget());
|
||||
// FIXME: Bug 1836847. Once we support "at <position>" for path(), we have
|
||||
// to give it the current box position.
|
||||
return OffsetPathData::Shape(gfxPath.forget(), {}, IsClosedPath(pathData));
|
||||
}
|
||||
|
||||
// The rest part is to handle "<basic-shape> || <coord-box>".
|
||||
MOZ_ASSERT(offsetPath.IsBasicShapeOrCoordBox());
|
||||
// TODO: Implement this in the following patches.
|
||||
return OffsetPathData::None();
|
||||
|
||||
nsRect coordBox;
|
||||
const nsIFrame* containingFrame =
|
||||
MotionPathUtils::GetOffsetPathReferenceBox(aFrame, coordBox);
|
||||
if (!containingFrame || coordBox.IsEmpty()) {
|
||||
return OffsetPathData::None();
|
||||
}
|
||||
|
||||
const nsStyleDisplay* disp = aFrame->StyleDisplay();
|
||||
nsPoint currentPosition = aFrame->GetOffsetTo(containingFrame);
|
||||
RefPtr<gfx::PathBuilder> builder = MotionPathUtils::GetPathBuilder();
|
||||
// TODO: If offset-path is coord-box only, create inset(0 round X), where X is
|
||||
// the value of border-radius on the element that establishes the containing
|
||||
// block for this element.
|
||||
const StyleBasicShape& shape =
|
||||
disp->mOffsetPath.AsOffsetPath().path->AsShape();
|
||||
RefPtr<gfx::Path> path = MotionPathUtils::BuildPath(
|
||||
shape, disp->mOffsetPosition, coordBox, currentPosition, builder);
|
||||
if (!path) {
|
||||
return OffsetPathData::None();
|
||||
}
|
||||
|
||||
return OffsetPathData::Shape(path.forget(), std::move(currentPosition), true);
|
||||
}
|
||||
|
||||
/* static*/
|
||||
@ -417,6 +450,7 @@ Maybe<ResolvedMotionPathData> MotionPathUtils::ResolveMotionPath(
|
||||
transformOrigin, aRefBox, ComputeAnchorPointAdjustment(*aFrame));
|
||||
}
|
||||
|
||||
// Generate data for motion path on the compositor thread.
|
||||
static OffsetPathData GenerateOffsetPathData(
|
||||
const StyleOffsetPath& aOffsetPath,
|
||||
const layers::MotionPathData& aMotionPathData,
|
||||
@ -444,9 +478,11 @@ static OffsetPathData GenerateOffsetPathData(
|
||||
if (!path) {
|
||||
RefPtr<gfx::PathBuilder> builder =
|
||||
MotionPathUtils::GetCompositorPathBuilder();
|
||||
path = MotionPathUtils::BuildPath(pathData, builder);
|
||||
path = MotionPathUtils::BuildSVGPath(pathData, builder);
|
||||
}
|
||||
return OffsetPathData::Shape(pathData, path.forget());
|
||||
// FIXME: Bug 1836847. Once we support "at <position>" for path(), we have
|
||||
// to give it the current box position.
|
||||
return OffsetPathData::Shape(path.forget(), {}, IsClosedPath(pathData));
|
||||
}
|
||||
|
||||
// The rest part is to handle "<basic-shape> || <coord-box>".
|
||||
@ -482,7 +518,7 @@ Maybe<ResolvedMotionPathData> MotionPathUtils::ResolveMotionPath(
|
||||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<gfx::Path> MotionPathUtils::BuildPath(
|
||||
already_AddRefed<gfx::Path> MotionPathUtils::BuildSVGPath(
|
||||
const StyleSVGPathData& aPath, gfx::PathBuilder* aPathBuilder) {
|
||||
if (!aPathBuilder) {
|
||||
return nullptr;
|
||||
@ -493,6 +529,60 @@ already_AddRefed<gfx::Path> MotionPathUtils::BuildPath(
|
||||
0.0);
|
||||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<gfx::Path> MotionPathUtils::BuildPath(
|
||||
const StyleBasicShape& aBasicShape,
|
||||
const StyleOffsetPosition& aOffsetPosition, const nsRect& aCoordBox,
|
||||
const nsPoint& aCurrentPosition, gfx::PathBuilder* aPathBuilder) {
|
||||
if (!aPathBuilder) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
switch (aBasicShape.tag) {
|
||||
case StyleBasicShape::Tag::Circle: {
|
||||
const nsPoint center =
|
||||
ComputePosition(aBasicShape.AsCircle().position, aOffsetPosition,
|
||||
aCoordBox, aCurrentPosition);
|
||||
return ShapeUtils::BuildCirclePath(aBasicShape, aCoordBox, center,
|
||||
AppUnitsPerCSSPixel(), aPathBuilder);
|
||||
}
|
||||
case StyleBasicShape::Tag::Ellipse: {
|
||||
const nsPoint center =
|
||||
ComputePosition(aBasicShape.AsEllipse().position, aOffsetPosition,
|
||||
aCoordBox, aCurrentPosition);
|
||||
return ShapeUtils::BuildEllipsePath(aBasicShape, aCoordBox, center,
|
||||
AppUnitsPerCSSPixel(), aPathBuilder);
|
||||
}
|
||||
case StyleBasicShape::Tag::Inset:
|
||||
return ShapeUtils::BuildInsetPath(aBasicShape, aCoordBox,
|
||||
AppUnitsPerCSSPixel(), aPathBuilder);
|
||||
case StyleBasicShape::Tag::Polygon:
|
||||
return ShapeUtils::BuildPolygonPath(aBasicShape, aCoordBox,
|
||||
AppUnitsPerCSSPixel(), aPathBuilder);
|
||||
case StyleBasicShape::Tag::Path:
|
||||
// FIXME: Bug 1836847. Once we support "at <position>" for path(), we have
|
||||
// to also check its containing block as well. For now, we are still
|
||||
// building its gfx::Path directly by its SVGPathData without other
|
||||
// reference. https://github.com/w3c/fxtf-drafts/issues/504
|
||||
return BuildSVGPath(aBasicShape.AsPath().path, aPathBuilder);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<gfx::PathBuilder> MotionPathUtils::GetPathBuilder() {
|
||||
// Here we only need to build a valid path for motion path, so
|
||||
// using the default values of stroke-width, stoke-linecap, and fill-rule
|
||||
// is fine for now because what we want is to get the point and its normal
|
||||
// vector along the path, instead of rendering it.
|
||||
RefPtr<gfx::PathBuilder> builder =
|
||||
gfxPlatform::GetPlatform()
|
||||
->ScreenReferenceDrawTarget()
|
||||
->CreatePathBuilder(gfx::FillRule::FILL_WINDING);
|
||||
return builder.forget();
|
||||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<gfx::PathBuilder> MotionPathUtils::GetCompositorPathBuilder() {
|
||||
// FIXME: Perhaps we need a PathBuilder which is independent on the backend.
|
||||
|
@ -45,6 +45,9 @@ struct OffsetPathData {
|
||||
|
||||
struct ShapeData {
|
||||
RefPtr<gfx::Path> mGfxPath;
|
||||
// The current position of this transfromed box in the coordinate system of
|
||||
// its containing block.
|
||||
nsPoint mCurrentPosition;
|
||||
bool mIsClosedIntervals;
|
||||
};
|
||||
|
||||
@ -66,11 +69,10 @@ struct OffsetPathData {
|
||||
};
|
||||
|
||||
static OffsetPathData None() { return OffsetPathData(); }
|
||||
static OffsetPathData Shape(const StyleSVGPathData& aPath,
|
||||
already_AddRefed<gfx::Path>&& aGfxPath) {
|
||||
const auto& path = aPath._0.AsSpan();
|
||||
return OffsetPathData(std::move(aGfxPath),
|
||||
!path.empty() && path.rbegin()->IsClosePath());
|
||||
static OffsetPathData Shape(already_AddRefed<gfx::Path>&& aGfxPath,
|
||||
nsPoint&& aCurrentPosition, bool aIsClosedPath) {
|
||||
return OffsetPathData(std::move(aGfxPath), std::move(aCurrentPosition),
|
||||
aIsClosedPath);
|
||||
}
|
||||
static OffsetPathData Ray(const StyleRayFunction& aRay, nsRect&& aCoordBox,
|
||||
nsPoint&& aPosition,
|
||||
@ -139,8 +141,10 @@ struct OffsetPathData {
|
||||
|
||||
private:
|
||||
OffsetPathData() : mType(Type::None) {}
|
||||
OffsetPathData(already_AddRefed<gfx::Path>&& aPath, bool aIsClosed)
|
||||
: mType(Type::Shape), mShape{std::move(aPath), aIsClosed} {}
|
||||
OffsetPathData(already_AddRefed<gfx::Path>&& aPath,
|
||||
nsPoint&& aCurrentPosition, bool aIsClosed)
|
||||
: mType(Type::Shape),
|
||||
mShape{std::move(aPath), std::move(aCurrentPosition), aIsClosed} {}
|
||||
OffsetPathData(const StyleRayFunction* aRay, nsRect&& aCoordBox,
|
||||
nsPoint&& aPosition, CSSCoord&& aContainReferenceLength)
|
||||
: mType(Type::Ray),
|
||||
@ -217,11 +221,26 @@ class MotionPathUtils final {
|
||||
TransformReferenceBox&, gfx::Path* aCachedMotionPath);
|
||||
|
||||
/**
|
||||
* Build a gfx::Path from the computed svg path. We should give it a path
|
||||
* builder. If |aPathBuilder| is nullptr, we return null path.
|
||||
* */
|
||||
static already_AddRefed<gfx::Path> BuildPath(const StyleSVGPathData& aPath,
|
||||
gfx::PathBuilder* aPathBuilder);
|
||||
* Build a gfx::Path from the svg path data. We should give it a path builder.
|
||||
* If |aPathBuilder| is nullptr, we return null path.
|
||||
* This can be used on the main thread or on the compositor thread.
|
||||
*/
|
||||
static already_AddRefed<gfx::Path> BuildSVGPath(
|
||||
const StyleSVGPathData& aPath, gfx::PathBuilder* aPathBuilder);
|
||||
|
||||
/**
|
||||
* Build a gfx::Path from the computed basic shape.
|
||||
*/
|
||||
static already_AddRefed<gfx::Path> BuildPath(const StyleBasicShape&,
|
||||
const StyleOffsetPosition&,
|
||||
const nsRect& aCoordBox,
|
||||
const nsPoint& aCurrentPosition,
|
||||
gfx::PathBuilder*);
|
||||
|
||||
/**
|
||||
* Get a path builder for motion path on the main thread.
|
||||
*/
|
||||
static already_AddRefed<gfx::PathBuilder> GetPathBuilder();
|
||||
|
||||
/**
|
||||
* Get a path builder for compositor.
|
||||
|
@ -1389,16 +1389,9 @@ void nsIFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle) {
|
||||
if (!oldPath || *oldPath != newPath) {
|
||||
// FIXME: Bug 1837042. Cache all basic shapes.
|
||||
if (newPath.IsPath()) {
|
||||
// Here we only need to build a valid path for motion path, so
|
||||
// using the default values of stroke-width, stoke-linecap, and fill-rule
|
||||
// is fine for now because what we want is to get the point and its normal
|
||||
// vector along the path, instead of rendering it.
|
||||
RefPtr<gfx::PathBuilder> builder =
|
||||
gfxPlatform::GetPlatform()
|
||||
->ScreenReferenceDrawTarget()
|
||||
->CreatePathBuilder(gfx::FillRule::FILL_WINDING);
|
||||
RefPtr<gfx::PathBuilder> builder = MotionPathUtils::GetPathBuilder();
|
||||
RefPtr<gfx::Path> path =
|
||||
MotionPathUtils::BuildPath(newPath.AsSVGPathData(), builder);
|
||||
MotionPathUtils::BuildSVGPath(newPath.AsSVGPathData(), builder);
|
||||
if (path) {
|
||||
// The newPath could be path('') (i.e. empty path), so its gfx path
|
||||
// could be nullptr, and so we only set property for a non-empty path.
|
||||
|
@ -1,2 +0,0 @@
|
||||
[offset-path-shape-circle-001.html]
|
||||
expected: FAIL
|
@ -1,2 +0,0 @@
|
||||
[offset-path-shape-circle-002.html]
|
||||
expected: FAIL
|
@ -1,2 +0,0 @@
|
||||
[offset-path-shape-circle-003.html]
|
||||
expected: FAIL
|
@ -1,2 +0,0 @@
|
||||
[offset-path-shape-circle-004.html]
|
||||
expected: FAIL
|
@ -1,2 +0,0 @@
|
||||
[offset-path-shape-circle-005.html]
|
||||
expected: FAIL
|
@ -1,2 +0,0 @@
|
||||
[offset-path-shape-ellipse-001.html]
|
||||
expected: FAIL
|
@ -1,2 +0,0 @@
|
||||
[offset-path-shape-ellipse-002.html]
|
||||
expected: FAIL
|
@ -1,2 +0,0 @@
|
||||
[offset-path-shape-ellipse-003.html]
|
||||
expected: FAIL
|
@ -1,2 +0,0 @@
|
||||
[offset-path-shape-ellipse-004.html]
|
||||
expected: FAIL
|
@ -1,2 +0,0 @@
|
||||
[offset-path-shape-ellipse-005.html]
|
||||
expected: FAIL
|
@ -1,2 +0,0 @@
|
||||
[offset-path-shape-inset-001.html]
|
||||
expected: FAIL
|
@ -1,2 +0,0 @@
|
||||
[offset-path-shape-inset-002.html]
|
||||
expected: FAIL
|
@ -1,2 +0,0 @@
|
||||
[offset-path-shape-polygon-001.html]
|
||||
expected: FAIL
|
@ -1,2 +0,0 @@
|
||||
[offset-path-shape-polygon-002.html]
|
||||
expected: FAIL
|
@ -1,2 +0,0 @@
|
||||
[offset-path-shape-polygon-003.html]
|
||||
expected: FAIL
|
@ -13,7 +13,8 @@
|
||||
}
|
||||
#box {
|
||||
background-color: green;
|
||||
transform: translate(250px, 350px);
|
||||
transform: translate(250px, 350px) rotate(180deg);
|
||||
border-radius: 50% 50% 0 0;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Motion Path test: <basic-shape> circle() path with explicit arguments</title>
|
||||
<meta name=fuzzy content="0-1;0-200">
|
||||
<meta name=fuzzy content="0-35;0-200">
|
||||
<link rel="author" title="Daniil Sakhapov" href="sakhapov@google.com">
|
||||
<link rel="match" href="offset-path-shape-circle-001-ref.html">
|
||||
<link rel="help" href="https://drafts.fxtf.org/motion/#valdef-offset-path-basic-shape">
|
||||
@ -19,6 +19,7 @@
|
||||
position: relative;
|
||||
offset-path: circle(closest-side at center);
|
||||
offset-distance: 25%;
|
||||
border-radius: 50% 50% 0 0;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
background-color: green;
|
||||
position: relative;
|
||||
transform: translate(420.231px, 311.969px) rotate(154.813deg);
|
||||
border-radius: 50% 50% 0 0;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Motion Path test: <basic-shape> circle() path with offset-distance</title>
|
||||
<meta name=fuzzy content="0-10;0-20">
|
||||
<meta name=fuzzy content="0-110;0-500">
|
||||
<link rel="author" title="Daniil Sakhapov" href="sakhapov@google.com">
|
||||
<link rel="match" href="offset-path-shape-circle-003-ref.html">
|
||||
<link rel="help" href="https://drafts.fxtf.org/motion/#valdef-offset-path-basic-shape">
|
||||
@ -19,6 +19,7 @@
|
||||
position: relative;
|
||||
offset-path: circle(farthest-side at top);
|
||||
offset-distance: 18%;
|
||||
border-radius: 50% 50% 0 0;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
@ -8,13 +8,14 @@
|
||||
top: 100px;
|
||||
left: 100px;
|
||||
position: relative;
|
||||
width: 600px;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
}
|
||||
#box {
|
||||
background-color: green;
|
||||
position: relative;
|
||||
transform: translate(400px, 199px) translate(-50px, -50px);
|
||||
transform: translate(200px, 160px);
|
||||
border-radius: 50% 50% 0 0;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Motion Path test: <basic-shape> circle() path with offset-distance and offset-anchor</title>
|
||||
<meta name=fuzzy content="0-80;0-310">
|
||||
<link rel="author" title="Daniil Sakhapov" href="sakhapov@google.com">
|
||||
<link rel="match" href="offset-path-shape-circle-004-ref.html">
|
||||
<link rel="help" href="https://drafts.fxtf.org/motion/#valdef-offset-path-basic-shape">
|
||||
@ -10,7 +11,7 @@
|
||||
top: 100px;
|
||||
left: 100px;
|
||||
position: relative;
|
||||
width: 600px;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
}
|
||||
#box {
|
||||
@ -19,6 +20,7 @@
|
||||
offset-path: circle(10% at bottom 25% right 25%);
|
||||
offset-anchor: 100% 100%;
|
||||
offset-distance: 75%;
|
||||
border-radius: 50% 50% 0 0;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Motion Path test: <basic-shape> circle() path with offset-position</title>
|
||||
<meta name=fuzzy content="0-18;0-400">
|
||||
<link rel="author" title="Daniil Sakhapov" href="sakhapov@google.com">
|
||||
<link rel="match" href="offset-path-shape-circle-005-ref.html">
|
||||
<link rel="help" href="https://drafts.fxtf.org/motion/#valdef-offset-path-basic-shape">
|
||||
|
@ -13,7 +13,8 @@
|
||||
}
|
||||
#box {
|
||||
background-color: green;
|
||||
transform: translate(250px, 350px);
|
||||
transform: translate(250px, 350px) rotate(180deg);
|
||||
border-radius: 50% 50% 0 0;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Motion Path test: <basic-shape> ellipse() path with explicit arguments</title>
|
||||
<meta name=fuzzy content="0-1;0-200">
|
||||
<meta name=fuzzy content="0-24;0-200">
|
||||
<link rel="author" title="Daniil Sakhapov" href="sakhapov@google.com">
|
||||
<link rel="match" href="offset-path-shape-ellipse-001-ref.html">
|
||||
<link rel="help" href="https://drafts.fxtf.org/motion/#valdef-offset-path-basic-shape">
|
||||
@ -19,6 +19,7 @@
|
||||
position: relative;
|
||||
offset-path: ellipse(closest-side closest-side at center);
|
||||
offset-distance: 25%;
|
||||
border-radius: 50% 50% 0 0;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
@ -8,13 +8,14 @@
|
||||
top: 100px;
|
||||
left: 100px;
|
||||
position: relative;
|
||||
width: 600px;
|
||||
height: 400px;
|
||||
width: 400px;
|
||||
height: 200px;
|
||||
}
|
||||
#box {
|
||||
background-color: green;
|
||||
position: relative;
|
||||
transform: translate(393.93px, 300.959px) rotate(143.905deg);
|
||||
transform: translate(8.6px, 91.4px) rotate(-135deg);
|
||||
border-radius: 50% 50% 0 0;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Motion Path test: <basic-shape> ellipse() path with offset-distance</title>
|
||||
<meta name=fuzzy content="0-25;0-450">
|
||||
<link rel="author" title="Daniil Sakhapov" href="sakhapov@google.com">
|
||||
<link rel="match" href="offset-path-shape-ellipse-003-ref.html">
|
||||
<link rel="help" href="https://drafts.fxtf.org/motion/#valdef-offset-path-basic-shape">
|
||||
@ -10,14 +11,15 @@
|
||||
top: 100px;
|
||||
left: 100px;
|
||||
position: relative;
|
||||
width: 600px;
|
||||
height: 400px;
|
||||
width: 400px;
|
||||
height: 200px;
|
||||
}
|
||||
#box {
|
||||
background-color: green;
|
||||
position: relative;
|
||||
offset-path: ellipse(farthest-side farthest-side at top);
|
||||
offset-distance: 18%;
|
||||
offset-distance: 37.5%;
|
||||
border-radius: 50% 50% 0 0;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Motion Path test: <basic-shape> ellipse() path with offset-position</title>
|
||||
<meta name=fuzzy content="0-18;0-400">
|
||||
<link rel="author" title="Daniil Sakhapov" href="sakhapov@google.com">
|
||||
<link rel="match" href="offset-path-shape-ellipse-005-ref.html">
|
||||
<link rel="help" href="https://drafts.fxtf.org/motion/#valdef-offset-path-basic-shape">
|
||||
|
@ -8,12 +8,14 @@
|
||||
top: 100px;
|
||||
left: 100px;
|
||||
position: relative;
|
||||
width: 600px;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
}
|
||||
#box {
|
||||
background-color: green;
|
||||
transform: translate(512.786px, 283.444px) rotate(133.055deg) translate(50px, 50px);
|
||||
transform: translate(306px, 94px) rotate(45deg);
|
||||
transform-origin: 0 0;
|
||||
border-radius: 50% 50% 0 0;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Motion Path test: <basic-shape> inset() path with explicit arguments and radius</title>
|
||||
<meta name=fuzzy content="0-75;0-500">
|
||||
<link rel="author" title="Daniil Sakhapov" href="sakhapov@google.com">
|
||||
<link rel="match" href="offset-path-shape-inset-002-ref.html">
|
||||
<link rel="help" href="https://drafts.fxtf.org/motion/#valdef-offset-path-basic-shape">
|
||||
@ -10,15 +11,16 @@
|
||||
top: 100px;
|
||||
left: 100px;
|
||||
position: relative;
|
||||
width: 600px;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
}
|
||||
#box {
|
||||
background-color: green;
|
||||
position: relative;
|
||||
offset-path: inset(10px 10px 10px 10px round 30%);
|
||||
offset-path: inset(50px round 50%);
|
||||
offset-anchor: 0 0;
|
||||
offset-distance: 40%;
|
||||
offset-distance: 12.5%;
|
||||
border-radius: 50% 50% 0 0;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Motion Path: path(basic-shape) paths</title>
|
||||
<style>
|
||||
#target {
|
||||
position: absolute;
|
||||
left: 300px;
|
||||
top: 0px;
|
||||
width: 300px;
|
||||
height: 200px;
|
||||
background-color: lime;
|
||||
transform-origin: 0px 0px;
|
||||
transform: translate(35px, 44px);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="target"></div>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user