×

【SVG】使用SVG完成悬浮时形状样式变化的效果

作者:Terry2016.09.23来源:Web前端之家浏览:11755评论:0
关键词:html5SVG

在这篇教程里,我们将重新创建一个类似The Christmas Experiments网站中看到的hover样式。我们将通过SVG制作出形状,然后使用Snap.svg做出hover时的动画效果。

如果你已经访问过The Christmas Experiments最新版本的网站,你可能会注意到其中Christmas calendar很酷的三角状的hover效果。那个形状其实是一个带边框的三角形。今天我会向您展示,如何使用SVG和Snap.svg做出同样的效果。我们的想法是,使用一条路径创建一个SVG,用它来表示caption的形状背景,然后在hover时改变这个路径。完成这一任务有很多种创作的可能性,今天我们将做出三个不同的示例。使用SVG的好处是,我们可以根据父容器的大小调整形状的大小,使一切都成为流动的。

demo里使用的插画由Isaac Montemayor创作。可以在他的websiteDribbble中查看原始作品。

那么,现在开始吧!

标记

首先我们要做的,是在类似Adobe Illustrator 或 Inkscape的矢量图编辑器中绘制两个形状。每个形状将包括一条路径,完成之后,复制路径的各个点,这些点将在标记中使用。注意我们已经将一个多边形装换成了一条路径。如果你使用的是Inkscape,你可以通过这样的步骤实现:选择对象,Path>Object to Path。路径的点可以通过Edit>XML Editor…获取到。这将会打开如下面截图中看到的视图:

使用SVG完成悬浮时形状样式变化的效果

“d”(路径数据)值就是你需要的。

对于这个标记,我们将有一个class为“grid”的区域,其中包括被包在锚点中的figure。你也可以在这儿使用一个列表,这样将会需要一些额外的标记。

这个figure将包含图象、最初可见的形状和一个figcaption

<section id="grid" class="grid clearfix">
    <a href="#" data-path-hover="m 180,34.57627 -180,0 L 0,0 180,0 z">
        <figure>
            <img src="img/1.png" />
            <svg viewBox="0 0 180 320" preserveAspectRatio="none"><path d="M 180,160 0,218 0,0 180,0 z"/></svg>
            <figcaption>
                <h2>Crystalline</h2>
                <p>Soko radicchio bunya nuts gram dulse.</p>
                <button>View</button>
            </figcaption>
        </figure>
    </a>
    <!-- ... -->
</section>

对于每个图象,SVG都会有其相应的viewBox值,并且设置属性preserveAspectRatio的值为“none”。这将允许我们缩放和伸展形状到我们想要的尺寸,即100%。我们将在样式表中定义宽度和高度。hover路径的信息将会存储在锚点的数据属性data-path-hover中。

CSS

注意CSS将不会包括任何vendor prefixes(-webkit、-moz等),但你可以在文件中找到它们。

我们将看到的样式是为全部三个示例而写的。首先,我们将查看公共样式,然后为不同demo分别设置样式。

让我们从grid开始吧。我们需要使它居中,然后设置一个max-width和一个百分比表示的width,让其成为流体的:

.grid {
    margin: 40px auto 120px;
    max-width: 1000px;
    width: 90%;
}

锚点应该向左浮动,由于我们想让它们成为流式的,并且一行显示4个项,我们需要为它们设置一个250px的max-width,并且有一个值为25%的width。稍后我们将会为更小尺寸的屏幕定义样式:

.grid a {
    float: left;
    max-width: 250px;
    width: 25%;
    color: #333;
}

要为奇数项创建一些偏移,我们需要设置margin-top为30px,margin-bottom为-30px。这将使grid看起来更加漂亮,如The Christmas Experiments网站中显示的那样:

.grid a:nth-child(odd) {
    margin: 30px 0 -30px 0;
}

因为我们需要一些绝对定位的子元素,figure应该使用相对定位。由于hover效果可能引起一些溢出,而我们不想这些溢出被看到,因此设置overflow为“hidden”:

.grid figure {
    position: relative;
    overflow: hidden;
    margin: 5px;
    background: #333;
}

图象将占据其父元素的全部宽度,并且其opacity为0.7。hover时,我们要使opacity动态变化,因此增加了一个transition:

.grid figure img {
    position: relative;
    display: block;
    width: 100%;
    opacity: 0.7;
    transition: opacity 0.3s;
}

figcaption需要被绝对定位,我们将拉伸它直到覆盖整个项:

.grid figcaption {
    position: absolute;
    top: 0;
    z-index: 11;
    padding: 10px;
    width: 100%;
    height: 100%;
    text-align: center;
}

标题和段落在hover时都将会动态变化,因此我们给它们添加上相应的transition,然后稍微移动它们:

.grid figcaption h2 {
    margin: 0 0 20px 0;
    color: #3498db;
    text-transform: uppercase;
    letter-spacing: 1px;
    font-weight: 300;
    font-size: 130%;
    transition: transform 0.3s;
}

.grid figcaption p {
    padding: 0 20px;
    color: #aaa;
    font-weight: 300;
    transition: opacity 0.3s, transform 0.3s;
}

.grid figcaption h2,
.grid figcaption p {
    transform: translateY(50px);
}

下面是三个示例中button的公共样式。button也是动态变化的,因此我们将为其opacity和transform添加一个transition:

.grid figure button {
    position: absolute;
    padding: 4px 20px;
    border: none;
    text-transform: uppercase;
    letter-spacing: 1px;
    font-weight: bold;
    transition: opacity 0.3s, transform 0.3s;
}

为了避免一些闪烁和毛刺,我们需要给动画元素及其父元素的backface-visibility设为hidden:

.grid figcaption,
.grid figcaption h2,
.grid figcaption p,
.grid figure button {
    backface-visibility: hidden;
}

SVG也将是绝对定位的,并且我们会通过把width和height都设置为100%来拉伸它,直到覆盖整个项。top值为-1px而不是0确保了它在Firefox (26.0 / Mac)中不会出现奇怪的行。

.grid svg {
    position: absolute;
    top: -1px; /* fixes rendering issue in FF */
    z-index: 10;
    width: 100%;
    height: 100%;
}

路径的颜色将被填充为白色:

.grid svg path {
    fill: #fff;
}

在这里你也可以为路径填加一些过渡效果,如hover时改变上面的填充颜色。

通常的锚点hover效果如下所示:

.grid a:hover figure img {
    opacity: 1;
}

.grid a:hover figcaption h2,
.grid a:hover figcaption p {
    transform: translateY(0);
}

.grid a:hover figcaption p {
    opacity: 0;
}

当段落标题滑上去并隐藏之后,图像的透明度将被设置成1,并且,标题行也会上移。

在第一个和第三个示例中,我们想为按钮设置一个白色的边框,并将按钮置于父容器的中间。它最初是隐藏并缩小的。其它的transform则用于将按钮拉至目标位置然后居中。hover时,button会放大、渐渐显示出来。

.demo-1 body {
    background: #3498db;
}

.demo-1 .grid figure button,
.demo-3 .grid figure button {
    top: 50%;
    left: 50%;
    border: 3px solid #fff;
    background: transparent;
    color: #fff;
    opacity: 0;
    transform: translateY(-50%) translateX(-50%) scale(0.25);
}

.demo-1 .grid a:hover figure button,
.demo-3 .grid a:hover figure button {
    opacity: 1;
    transform: translateY(-50%) translateX(-50%) scale(1);
}

在第二个demo中,我们将重定义一些颜色,并将button隐藏在figure的底部。为此我们设置bottom为0,并且定义其高度为100%。hover时,它会通过“ease-out”这个函数实现上滑效果。

.demo-2 body {
    background: #e74c3c;
}

.demo-2 .grid figcaption h2 {
    color: #e74c3c;
}

.demo-2 .grid figcaption p {
    transition-delay: 0.05s;
}

.demo-2 .grid figure button {
    bottom: 0;
    left: 0;
    padding: 15px;
    width: 100%;
    background: #fff;
    color: #333;
    font-weight: 300;
    transform: translateY(100%);
}

.demo-2 .grid a:hover figure button {
    transition-timing-function: ease-out;
    transform: translateY(0);
}

第二个和第三个示例中的标题行与段落将使用cubic-bezier 函数模拟弹性过渡效果。段落的hover效果中也将设置另一个无延迟的时间。这将确保SVG形状到达顶部之前段落快速消失。

.demo-2 .grid figcaption h2, 
.demo-2 .grid figcaption p,
.demo-3 .grid figcaption h2,
.demo-3 .grid figcaption p {
    timing-function: cubic-bezier(0.250, 0.250, 0.115, 1.445);
}

.demo-2 .grid a:hover figcaption p,
.demo-3 .grid a:hover figcaption p {
    transition-delay: 0s;
    transition-duration: 0.1s;
}

对于第三个demo,我们将改变一些颜色,使标题行hover时平移一点儿而不是设置为0.

.demo-3 body {
    background: #52be7f;
}

.demo-3 .grid figcaption h2 {
    color: #52be7f;
}

.demo-3 .grid a:hover figcaption h2 {
    transform: translateY(5px);
}

对于更小的屏幕,我们想改变每一行显示的项目数量,因此我们将重置其width和偶数子元素的margin。第2、5、8、11(3n-1序列)等等这些个锚点应该有一个margin。Tips:如果你想快速寻找一行数字的序列,你可以去WolframAlpha这样的网站,然后键入你的数字,你会在“Possible sequence identification”对应的位置找到序列定义。

对于再小一些的屏幕,我们将调整grid的max-width,重定义标题元素的一些margin:

@media screen and (max-width: 58em) {
    .grid a {
        width: 33.333%;
    }

    .grid a:nth-child(odd) {
        margin: 0;
    }

    .grid a:nth-child(3n-1) {
        margin: 30px 0 -30px 0;
    }
}

@media screen and (max-width: 45em) {
    .grid {
        max-width: 500px;
    }

    .grid a {
        width: 50%;
    }

    .grid a:nth-child(3n-1) {
        margin: 0;
    }

    .grid a:nth-child(even) {
        margin: 30px 0 -30px 0;
    }


    .grid figcaption h2 {
        margin-bottom: 0px;
        transform: translateY(30px);
    }

    .grid figcaption p {
        margin: 0;
        padding: 0 10px;
    }
}

@media screen and (max-width: 27em) {
    .grid {
        max-width: 250px;
    }

    .grid a {
        width: 100%;
    }

    .grid a:nth-child(even) {
        margin: 0;
    }
}

这就是所有的style啦!让我们来看看JavaScript部分怎么写。

JavaScript

我们将使用Snap.svg,一个同SVG一起工作的强大的类库。为了更好地理解它的用法,请查看documentationinteractive Getting Started tutorial

让我们从定义变量speed和easing开始。我们也将定义一个变量,它会包含路径及其hover状态的信息。当锚点处于hover状态时,路径会动态变为“to”路径。当脱离hover状态时,动态变回“from”路径:

(function() {

    function init() {
        var speed = 250,
            easing = mina.easeinout;

        [].slice.call ( document.querySelectorAll( '#grid > a' ) ).forEach( function( el ) {
            var s = Snap( el.querySelector( 'svg' ) ), path = s.select( 'path' ),
                pathConfig = {
                    from : path.attr( 'd' ),
                    to : el.getAttribute( 'data-path-hover' )
                };

            el.addEventListener( 'mouseenter', function() {
                path.animate( { 'path' : pathConfig.to }, speed, easing );
            } );

            el.addEventListener( 'mouseleave', function() {
                path.animate( { 'path' : pathConfig.from }, speed, easing );
            } );
        } );
    }

    init();

})();

以上就是全部内容了!我们已经向大家展示了三个示例,但是除此之外仍然会有很多的酷炫图形和动态、颜色效果。

您的支持是我们创作的动力!
温馨提示:本文作者系Terry ,经Web前端之家编辑修改或补充,转载请注明出处和本文链接:
https://jiangweishan.com/article/svg1474560000610.html

网友评论文明上网理性发言 已有0人参与

发表评论: