xml地图|网站地图|网站标签 [设为首页] [加入收藏]
实例对比,波纹效果按钮
分类:web前端

SVG 创建 Material Design 波纹效果按钮

2017/10/16 · HTML5 · SVG

原文出处: Dennis Gaebel   译文出处:码农网 – 小峰   

随着Google Material Design的出现,一种旨在跨平台和设备创建统一体验的视觉语言由此横空出世。Google通过“Material Guidelines”动画部分描述的例子是如此地拟真,以致于许多人将这些互动视为Google品牌的一部分。

在本教程中,我们将向大家展示如何在Google Material Design规范的Radial Action下构建波纹效果,并结合SVG和GreenSock功能。

图片 1

在线演示  源码下载

CSS Grid VS Flexbox:实例对比

2017/04/21 · CSS · Flexbox, Grid

原文出处: Danny Markov   译文出处:IT程序狮   

图片 2

  • DEMO 地址:【传送门】
  • 示例下载地址: 【传送门】

不久以前,所有 HTML 页面的布局还都是通过 tables、floats 以及其他的 CSS 属性来完成的。面对复杂页面的布局,却没有很好的办法。

然而Flexbox的出现,便轻松的解决了复杂的 Web 布局。它是一种专注于创建稳定的响应式页面的布局模式,并可以轻松地正确对齐元素及其内容。如今已是大多数 Web 开发人员首选的 CSS 布局方式。

现在,又出现了一个构建 HTML 最佳布局体系的新竞争者。(冠军头衔正在争夺中…)它就是强大的CSS Grid布局。直到本月月底,它也将在Firefox 52和Chrome 57上得到原生支持,相信不久也会得到其他浏览器兼容性的支持。

两行 CSS 代码实现图片任意颜色赋色技术

2017/12/21 · CSS · 6 评论 · 颜色

本文作者: 伯乐在线 - chokcoco 。未经作者许可,禁止转载!
欢迎加入伯乐在线 专栏作者。

很久之前在张鑫旭大大的博客看到过一篇 PNG格式小图标的CSS任意颜色赋色技术,当时惊为天人,感慨还可以这样玩,私底下也曾多次想过有没有其他方法可以实现,又或者不仅仅局限于 PNG 图片。

 

联结点样式

当编写CSS的时候,要达到预期的效果你所要做的并不多。

.ripple-obj { height: 100%; pointer-events: none; position: absolute; top: 0; left: 0; width: 100%; z-index: 0; fill: #0c7cd5; } .ripple-obj use { opacity: 0; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.ripple-obj {
  height: 100%;
  pointer-events: none;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 0;
  fill: #0c7cd5;
}
 
.ripple-obj use {
  opacity: 0;
}

这就是在删除用于一般样式的声明时,还留下的内容。pointer-events的使用消除了SVG纹波成为鼠标事件的目标,因为我们只需要父对象反应:button元素。

纹波最初必须是不可见的,因此要将不透明度值设置为零。我们还将波纹对象定位在button的左上方。我们可以使波纹形状居中,但是由于此事件是基于用户交互而发生的,所以担心位置没有意义。

挑战 3:对齐标头组件

Flexbox 解决方案

我们的标头包含了导航和一个按钮的相关链接。我们希望导航朝左对齐,按钮向右对齐。而导航中的链接务必正确对齐,且彼此相邻。

XHTML

<header> <nav> <li><a href="#"><h1>Logo</h1></a></li> <li><a href="#">Link</a></li> <li><a href="#">Link</a></li> </nav> <button>Button</button> </header>

1
2
3
4
5
6
7
8
<header>
    <nav>
        <li><a href="#"><h1>Logo</h1></a></li>
        <li><a href="#">Link</a></li>
        <li><a href="#">Link</a></li>
    </nav>
    <button>Button</button>
</header>

我们曾在一篇较早的文章中使用 Flexbox 做了类似的布局:响应式标头最简单的制作方法。这个技术很简单:

header { display: flex; justify-content: space-between; }

1
2
3
4
header {
    display: flex;
    justify-content: space-between;
}

现在导航列表和按钮已正确对齐。下来我们将使``

`内的 items 进行水平移动。这里最简单的方法就是使用display:inline-block`属性,但目前我们需要使用一个 Flexbox 解决方案:

header nav { display: flex; align-items: baseline; }

1
2
3
4
header nav {
    display: flex;
    align-items: baseline;
}

仅两行代码就搞定了! 还不错吧。接下来让我们看看如何使用 CSS Grid 解决它。

CSS Grid 解决方案

为了拆分导航和按钮,我们要为标头定义display: grid属性,并设置一个 2 列的网格。同时,我们还需要两行额外的 CSS 代码,将它们定位在相应的边界上。

header{ display: grid; grid-template-columns: 1fr 1fr; } header nav { justify-self: start; } header button { justify-self: end; }

1
2
3
4
5
6
7
8
9
10
header{
    display: grid;
    grid-template-columns: 1fr 1fr;
}
header nav {
    justify-self: start;
}
header button {
    justify-self: end;
}

至于导航中的内链 – 这是我们使用 CSS grid 最好的布局展示:

图片 3

虽然链接为内链形式,但它们不能正确的对齐。由于 CSS grid 不具备基线选项(不像 Flexbox 具备的align-items属性),所以我们只能再定义一个子网格。

header nav { display: grid; grid-template-columns: auto 1fr 1fr; align-items: end; }

1
2
3
4
5
header nav {
    display: grid;
    grid-template-columns: auto 1fr 1fr;
    align-items: end;
}

CSS grid 在此步骤中,存在一些明显的布局上的缺陷。但你也不必过于惊讶。因为它的目标是对齐容器,而不是内部的内容。所以,用它来处理收尾工作,或许不是很好的选择哦。

打赏支持我写出更多好文章,谢谢!

任选一种支付方式

图片 4 图片 5

1 赞 8 收藏 6 评论

赋予它生机

赋予生机正是这个互动所有的意义。

<script src="; <script src="js/ripple.js"/>

1
2
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.17.0/TweenMax.min.js"/>
<script src="js/ripple.js"/>

为了动画化波纹,我们将使用GreenSock的TweenMax库,因为它是使用JavaScript对对象进行动画处理的最佳库之一;特别是涉及与动画SVG跨浏览器有关的问题。

var ripplyScott = (function() {} return { init: function() {} }; })();

1
2
3
4
5
var ripplyScott = (function() {}
  return {
    init: function() {}
  };
})();

我们将要使用的模式是所谓的模块模式,因为它有助于隐藏和保护全局命名空间。

var ripplyScott = (function() {} var circle = document.getElementById('js-ripple'), ripple = document.querySelectorAll('.js-ripple'); function rippleAnimation(event, timing) {…} })();

1
2
3
4
5
6
var ripplyScott = (function() {}
  var circle = document.getElementById('js-ripple'),
      ripple = document.querySelectorAll('.js-ripple');
 
  function rippleAnimation(event, timing) {…}
})();

为了解决问题,我们将抓取一些元素并将它们存储在变量中;特别是use元素,它包含button内的svg。整个动画逻辑将驻留在rippleAnimation函数中。该函数将接受动画序列和事件信息的时序参数。

var ripplyScott = (function() {} var circle = document.getElementById('js-ripple'), ripple = document.querySelectorAll('.js-ripple'); function rippleAnimation(event, timing) { var tl = new TimelineMax(); x = event.offsetX, y = event.offsetY, w = event.target.offsetWidth, h = event.target.offsetHeight, offsetX = Math.abs( (w / 2) - x ), offsetY = Math.abs( (h / 2) - y ), deltaX = (w / 2) + offsetX, deltaY = (h / 2) + offsetY, scale_ratio = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2)); } })();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var ripplyScott = (function() {}
  var circle = document.getElementById('js-ripple'),
      ripple = document.querySelectorAll('.js-ripple');
 
  function rippleAnimation(event, timing) {
    var tl           = new TimelineMax();
        x            = event.offsetX,
        y            = event.offsetY,
        w            = event.target.offsetWidth,
        h            = event.target.offsetHeight,
        offsetX      = Math.abs( (w / 2) - x ),
        offsetY      = Math.abs( (h / 2) - y ),
        deltaX       = (w / 2) + offsetX,
        deltaY       = (h / 2) + offsetY,
        scale_ratio  = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
  }
})();

我们定义了大量的变量,所以让我们一个一个地讨论这些变量所负责的内容。

var tl = new TimelineMax();

1
var tl = new TimelineMax();

此变量创建动画序列的时间轴实例以及所有时间轴在TweenMax中实例化的方式。

var x = event.offsetX; var y = event.offsetY;

1
2
var x = event.offsetX;
var y = event.offsetY;

事件偏移量是一个只读属性,它将鼠标指针的偏移值报告给目标节点的填充边。在这个例子中,就是我们的button。x的事件偏移量从左到右计算,y的事件偏移量从上到下计算;都从零开始。

var w = event.target.offsetWidth; var h = event.target.offsetHeight;

1
2
var w = event.target.offsetWidth;
var h = event.target.offsetHeight;

这些变量将返回按钮的宽度和高度。最终计算结果将包括元素边框和填充的大小。我们需要这个值才能知道我们的元素有多大,这样我们才可以将波纹传播到最远的边缘。

var offsetX = Math.abs( (w / 2) - x ); var offsetY = Math.abs( (h / 2) - y );

1
2
var offsetX = Math.abs( (w / 2) - x );
var offsetY = Math.abs( (h / 2) - y );

偏移值是点击距离元素中心的偏移距离。为了填满目标的整个区域,波纹必须足够大,可以从接触点覆盖到最远的角落。使用初始x和y坐标将不会再次将其从零开始,对于x,是从左到右的值,对于y,是从上到下的值。这种方法让我们使用这些值的时候无论目标的中心点点击在哪一边,都会检测距离。

图片 6

注意圆将如何覆盖整个元素的过程,无论输入的起始点何处发生。根据起始点的交互来覆盖整个表面,我们需要做一些数学。

以下是我们如何使用464 x 82作为宽和高,391和45作为x和y坐标来计算偏移量的过程:

var offsetX = (464 / 2) - 391 = -159 var offsetY = (82 / 2) - 45 = -4

1
2
var offsetX = (464 / 2) - 391 = -159
var offsetY = (82 / 2) - 45 = -4

通过将宽度和高度除以2来找到中心,然后减去由x和y坐标检测到的报告值。

Math.abs()方法返回数字的绝对值。使用上面的算术得到值159和4。

var deltaX = 232 + 159 = 391; var deltaY = 41 + 4 = 45;

1
2
var deltaX  = 232 + 159 = 391;
var deltaY  = 41 + 4 = 45;

三角计算点击的整个距离,而不是距离中心的距离。选择三角的原因是x和y总是从零开始从左到右,所以当相反方向(从右到左)点击的时候,我们需要方法来检测点击。

图片 7

学过基础数学课程的小伙伴应该都知道勾股定理。公式为:高(a)的平方加底(b)的平方,得到斜边(c)的平方。

a2 + b2 = c2

var scale_ratio = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));

1
var scale_ratio = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));

使用这个公式让我们来看一下计算:

var scale_ratio = Math.sqrt(Math.pow(391, 2) + Math.pow(45, 2));

1
var scale_ratio = Math.sqrt(Math.pow(391, 2) + Math.pow(45, 2));

Math.pow()方法返回第一个参数的幂;在这个例子中增加了一倍。391的2次方为152881。后面45的2次方等于2025。将这两个值相加并取结果的平方根将留下393.58099547615353,这就是我们需要的波纹比例。

var ripplyScott = (function() { var circle = document.getElementById('js-ripple'), ripple = document.querySelectorAll('.js-ripple'); function rippleAnimation(event, timing) { var tl = new TimelineMax(); x = event.offsetX, y = event.offsetY, w = event.target.offsetWidth, h = event.target.offsetHeight, offsetX = Math.abs( (w / 2) - x ), offsetY = Math.abs( (h / 2) - y ), deltaX = (w / 2) + offsetX, deltaY = (h / 2) + offsetY, scale_ratio = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2)); tl.fromTo(ripple, timing, { x: x, y: y, transformOrigin: '50% 50%', scale: 0, opacity: 1, ease: Linear.easeIn },{ scale: scale_ratio, opacity: 0 }); return tl; } })();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
var ripplyScott = (function() {
  var circle = document.getElementById('js-ripple'),
      ripple = document.querySelectorAll('.js-ripple');
 
  function rippleAnimation(event, timing) {
    var tl           = new TimelineMax();
        x            = event.offsetX,
        y            = event.offsetY,
        w            = event.target.offsetWidth,
        h            = event.target.offsetHeight,
        offsetX      = Math.abs( (w / 2) - x ),
        offsetY      = Math.abs( (h / 2) - y ),
        deltaX       = (w / 2) + offsetX,
        deltaY       = (h / 2) + offsetY,
        scale_ratio  = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
 
    tl.fromTo(ripple, timing, {
      x: x,
      y: y,
      transformOrigin: '50% 50%',
      scale: 0,
      opacity: 1,
      ease: Linear.easeIn
    },{
      scale: scale_ratio,
      opacity: 0
    });
 
    return tl;
  }
})();

使用TweenMax中的fromTo方法,我们可以传递目标——波纹形状——并设置包含整个运动序列方向的对象文字。鉴于我们想要从中心向外形成动画,SVG需要将转换原点设置为中间位置。考虑到我们想要之后要进行动画处理,需要设置opacity 为1,因此缩放也需要调整到最小的位置。不知道你回想起了没有,之前我们在CSS中设置了opacity为0的use元素以及我们从值1开始并返回到零的原因。最后部分是返回时间轴实例。

var ripplyScott = (function() { var circle = document.getElementById('js-ripple'), ripple = document.querySelectorAll('.js-ripple'); function rippleAnimation(event, timing) { var tl = new TimelineMax(); x = event.offsetX, y = event.offsetY, w = event.target.offsetWidth, h = event.target.offsetHeight, offsetX = Math.abs( (w / 2) - x ), offsetY = Math.abs( (h / 2) - y ), deltaX = (w / 2) + offsetX, deltaY = (h / 2) + offsetY, scale_ratio = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2)); tl.fromTo(ripple, timing, { x: x, y: y, transformOrigin: '50% 50%', scale: 0, opacity: 1, ease: Linear.easeIn },{ scale: scale_ratio, opacity: 0 }); return tl; } return { init: function(target, timing) { var button = document.getElementById(target); button.addEventListener('click', function(event) { rippleAnimation.call(this, event, timing); }); } }; })();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
var ripplyScott = (function() {
  var circle = document.getElementById('js-ripple'),
      ripple = document.querySelectorAll('.js-ripple');
 
  function rippleAnimation(event, timing) {
    var tl           = new TimelineMax();
        x            = event.offsetX,
        y            = event.offsetY,
        w            = event.target.offsetWidth,
        h            = event.target.offsetHeight,
        offsetX      = Math.abs( (w / 2) - x ),
        offsetY      = Math.abs( (h / 2) - y ),
        deltaX       = (w / 2) + offsetX,
        deltaY       = (h / 2) + offsetY,
        scale_ratio  = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
 
    tl.fromTo(ripple, timing, {
      x: x,
      y: y,
      transformOrigin: '50% 50%',
      scale: 0,
      opacity: 1,
      ease: Linear.easeIn
    },{
      scale: scale_ratio,
      opacity: 0
    });
 
    return tl;
  }
 
  return {
    init: function(target, timing) {
      var button = document.getElementById(target);
 
      button.addEventListener('click', function(event) {
        rippleAnimation.call(this, event, timing);
      });
    }
  };
})();

返回的对象字面值将控制我们的波纹,方法是通过将事件侦听器附加到所需的目标,调用rippleAnimation,以及最后传递我们将在下一步讨论的参数。

ripplyScott.init('js-ripple-btn', 0.75);

1
ripplyScott.init('js-ripple-btn', 0.75);

最后通过使用模块并传递init函数来对按钮进行调用,init函数传递按钮和序列的时序。看,就是这样!

希望你喜欢这篇文章,并从中受到启迪!欢迎使用不同的形状来检查演示,并查看源代码。不妨尝试新的形状、新的图层形状,最重要的是发挥你的想象力,放飞你的创意。

注意:其中一些技术是试验性的,只能在现代浏览器中运行。

浏览器支持:Chrome Firefox Internet Explorer Safari Opera

在Github上查看这个项目

译文链接:
英文原文:Creating Material Design Ripple Effects with SVG
翻译作者:码农网 – 小峰
[ 转载必须在正文中标注并保留原文链接、译文链接和译者等信息。]

1 赞 1 收藏 评论

图片 8

结论

如果你已经浏览完整篇文章,那么结论不会让你感到意外。事实上,并不存在最好的布局方式。Flexbox 和 CSS grid 是两种不同的布局形式,我们应该根据具体的场景将它们搭配使用,而不是相互替代。

对于那些跳过文章只想看结论的朋友(不用担心,我们也这样做),这里是通过实例比较后的总结:

  1. CSS grids 适用于布局大画面。它们使页面的布局变得非常容易,甚至可以处理一些不规则和非对称的设计。
  2. Flexbox 非常适合对齐元素内的内容。你可以使用 Flex 来定位设计上一些较小的细节。
  3. 2D 布局适合使用 CSS grids(行与列)。
  4. Flexbox 适用于单一维度的布局(行或列)。
  5. 共同学习并使用它们。

感谢你的阅读。若你有所收获,欢迎点赞与分享。

1 赞 3 收藏 评论

图片 9

关于作者:chokcoco

图片 10

经不住流年似水,逃不过此间少年。 个人主页 · 我的文章 · 63 ·    

图片 11

编写标记

让我们写一个语义的button元素作为我们的对象,以显示此波纹。

JavaScript

<button>Click for Ripple</button>

1
<button>Click for Ripple</button>

大多数我们熟悉的button的标记结构是直截了当的,包括一些填充文本。

JavaScript

<button> Click for Ripple <svg> <use xlink:href="#ripply-scott"></use> </svg> </button>

1
2
3
4
5
6
<button>
  Click for Ripple
  <svg>
    <use xlink:href="#ripply-scott"></use>
  </svg>
</button>

为了利用先前创建的symbol元素,我们需要方法来引用它,通过使用按钮的SVG中的use元素来引用符号的ID属性值。

JavaScript

<button id="js-ripple-btn" class="button styl-material"> Click for Ripple <svg class="ripple-obj" id="js-ripple"> <use width="100" height="100" xlink:href="#ripply-scott" class="js-ripple"></use> </svg> </button>

1
2
3
4
5
6
<button id="js-ripple-btn" class="button styl-material">
  Click for Ripple
  <svg class="ripple-obj" id="js-ripple">
    <use width="100" height="100" xlink:href="#ripply-scott" class="js-ripple"></use>
  </svg>
</button>

最终标记具备了CSS和JavaScript hooks的附加属性。以“js-”开头的属性值表示仅存在于JavaScript中的值,因此删除它们将阻碍交互,但不会影响样式。这有助于区分CSS选择器和JavaScript hooks,以避免在将来需要删除或更新时相互混淆。

use元素必须有定义的宽度和高度,否则将不会对查看者可见。你也可以在CSS中定义,如果你直接在元素本身上决定不要的话。

基本布局测试

要了解这两个体系构建布局的方式,我们将通过相同的 HTML 页面,利用不同的布局方式 (即 Flexbox 与 CSS Grid)为大家区分。

同时,你也可以通过文章顶部附近的下载按钮,下载演示项目进行对比,或者通过在线演示来察看它们:

图片 12

简版静态页面布局

该页面的设计相对比较简单 – 它是由一个居中的容器组成,在其内部则包含了标头、主要内容部分、侧边栏和页脚。接下来,我们要完成同时保持 CSS 和 HTML 尽可能整洁的挑战事项:

  1. 在布局中将四个主要的部分进行定位。
  2. 将页面变为响应式页面;
  3. 对齐标头:导航朝左对齐,按钮向右对齐。

如你所见,为了便于比较,我们将所有事项从简处理。那么,让我们从第一个挑战事项开始吧!

局限性尝试 — 使用透明底色图片

上述方法要求了图片本身内容为纯色黑色,底色为白色。那么如果像 PNG 图片一样,只存在主色,而底色是透明的,是否能够同样实现效果呢?

假设我们有一张这样的 PNG 图片(灰色主色,透明底色):

图片 13

按照上面的方式实现一遍,结果如下:

图片 14

任意颜色赋色技术尝试 — PNG图片

 

很遗憾,当底色是透明的时候,会被混合模式混合上叠加层的颜色,无法使用。所有,这个技术也就存在了一个使用前提:

  • 图片的底色为白色,主色为黑色

当然主色也可以是其他颜色,只是这个时候叠加需要考虑颜色的融合,没有使用黑色直观。

 

本文由澳门新葡亰手机版发布于web前端,转载请注明出处:实例对比,波纹效果按钮

上一篇:没有了 下一篇:没有了
猜你喜欢
热门排行
精彩图文