我们将使SVG来动态地插入路径坐标。首先, 我们将确保整个 SVG 和覆盖路径都延伸到屏幕的大小。为此, 我们将 preserveAspectRatio属性设置为 none。根据所需的层数, 我们将创建该数量的路径:
<svg class="shape-overlays" viewBox="0 0 100 100" preserveAspectRatio="none"> <path class="shape-overlays__path"></path> <path class="shape-overlays__path"></path> <path class="shape-overlays__path"></path> </svg>
允许 SVG 与浏览器窗口大小相匹配的样式如下所示:
.shape-overlays { width: 100vw; height: 100vh; position: fixed; top: 0; left: 0; }
每个路径元素对应于覆盖层的一个层。 我们将在CSS中为每个图层指定填充。 最后一个路径元素是在叠加扩展之后保留的背景:
.shape-overlays path:nth-of-type(1) { fill: #c4dbea; } .shape-overlays path:nth-of-type(2) { fill: #4c688b; } .shape-overlays path:nth-of-type(3) { fill: #2e496a; }
请注意,在我们的演示中,我们利用CSS自定义属性来设置路径颜色。
JavaScript
对于我们的演示,我们定义了一个覆盖控件类,允许我们设置和控制几件事情。 通过更改每个值,您可以创建独特的外观形状和效果:
class ShapeOverlays { constructor(elm) { this.elm = elm; // Parent SVG element. this.path = elm.querySelectorAll('path'); // Path elements in parent SVG. These are the layers of the overlay. this.numPoints = 18; // Number of control points for Bezier Curve. this.duration = 600; // Animation duration of one path element. this.delayPointsArray = []; // Array of control points for Bezier Curve. this.delayPointsMax = 300; // Max of delay value in all control points. this.delayPerPath = 60; // Delay value per path. this.timeStart = Date.now(); this.isOpened = false; } ... } const elmOverlay = document.querySelector('.shape-overlays'); const overlay = new ShapeOverlays(elmOverlay);
确定覆盖层外观的其他方法是ShapeOverlays.toggle()方法和ShapeOverlays.updatePath()方法。
ShapeOverlays.toggle()方法具有打开和关闭叠加层的功能,并且还可以在每次打开和关闭时设置每个控制点的延迟值。 没有必要每次都设置延迟值,但通过改变它,会产生一些很好的随机性。
ShapeOverlays.updatePath()通过指定缓动功能来控制动画。
例如,在演示1中,对于所有的控制点都使用相同的缓动功能,并且使用三角函数将延迟值设置为细波,以便我们得到“融化”外观。
toggle() { const range = 4 * Math.random() + 6; for (var i = 0; i < this.numPoints; i++) { const radian = i / (this.numPoints - 1) * Math.PI; this.delayPointsArray[i] = (Math.sin(-radian) + Math.sin(-radian * range) + 2) / 4 * this.delayPointsMax; } ... } updatePath(time) { const points = []; for (var i = 0; i < this.numPoints; i++) { points[i] = ease.cubicInOut(Math.min(Math.max(time - this.delayPointsArray[i], 0) / this.duration, 1)) * 100 } ... }
在我们的演示中,我们使用这个效果来创建一个覆盖,以便在动画的结尾显示一个菜单。 但它也可以用于其他类型的转换,如页面转换或滚动效果。
我们希望你喜欢这个效果,并发现它有用!