当按钮处于“加载”状态时,如何给按钮添加一个旋转图标?

202

Twitter Bootstrap的按钮有一个漂亮的Loading...状态可用。

问题是它只是像这样通过data-loading-text属性传递了一个消息:Loading...

<button type="button" class="btn btn-primary start" id="btnStartUploads"
        data-loading-text="@Localization.Uploading">
    <i class="icon-upload icon-large"></i>
    <span>@Localization.StartUpload</span>
</button>

浏览 Font Awesome,你会看到现在有一个动画旋转图标

我试图在上传操作中运用这个旋转图标,像这样:

$("#btnStartUploads").button('loading');
$("#btnStartUploads i").removeAttr('class');
$("#btnStartUploads i").addClass('icon-spinner icon-spin icon-large');

然而这完全没有任何作用,也就是说,我只在按钮上看到 上传中... 的文字。

在按钮处于加载状态时添加一个图标是否有可能?看起来Bootstrap在加载状态下会删除按钮内部的图标<i class="icon-upload icon-large"></i>


这里有一个简单的演示,展示了我上面描述的行为。正如您所看到的,当它进入加载状态时,图标就会消失。在时间间隔后,它又重新出现了。


1
你可以查看我的解决方案来实现旋转图标的出现效果: https://dev59.com/b2Qo5IYBdhLWcg3whPvI - Andrew Dryga
我建议使用这种方法 https://dev59.com/b2Qo5IYBdhLWcg3whPvI#15988830 - limitium
10个回答

339

使用CSS3动画为 Bootstrap 3 提供简单解决方案。

将以下内容放入您的CSS中:

.glyphicon.spinning {
    animation: spin 1s infinite linear;
    -webkit-animation: spin2 1s infinite linear;
}

@keyframes spin {
    from { transform: scale(1) rotate(0deg); }
    to { transform: scale(1) rotate(360deg); }
}

@-webkit-keyframes spin2 {
    from { -webkit-transform: rotate(0deg); }
    to { -webkit-transform: rotate(360deg); }
}

只需要在加载时将 spinning 类添加到 glyphicon,即可获得旋转图标:

<button class="btn btn-lg btn-warning">
    <span class="glyphicon glyphicon-refresh spinning"></span> Loading...    
</button>

基于 http://www.bootply.com/128062#

  • 注意:IE9及以下版本不支持CSS3动画。

注意:IE9及以下版本不支持CSS3动画。

4
应该是“动画”而不是“-动画”吧? - Andrey Mikhaylov - lolmaus
3
优秀的解决方案。我在Safari浏览器上的桌面和iPad上遇到了动画问题。它显示图标但没有动画效果。你有类似的经历吗? - JayhawksFan93
2
答案已经更新为animation而不是-animation。通过这个更改,Firefox和IE都可以正常工作。但是,Firefox的动画效果看起来并不是很流畅。 - Flion
1
+1。在这里找到了一个类似的例子(http://bootsnipp.com/snippets/featured/glyphicon-animate-rotation-and-flip)... 为了记录而发布... - Fr0zenFyr
这对我来说是有效的,但如果我进行AJAX调用,则旋转器直到我收到响应后才显示出来(尽管“正在加载...”显示得很好),这有些失去了目的。 - TiggerToo
显示剩余5条评论

101

如果你查看 bootstrap-button.js 的源代码,你会发现在调用$(myElem).button('loading')时,Bootstrap插件将按钮内部的HTML替换为data-loading-text中的任何内容。

对于您的情况,我认为您只需要这样做:

<button type="button"
        class="btn btn-primary start"
        id="btnStartUploads"
        data-loading-text="<i class='icon-spinner icon-spin icon-large'></i> @Localization.Uploading">
    <i class="icon-upload icon-large"></i>
    <span>@Localization.StartUpload</span>
</button>

11
Safari 6.0.5 (7536.30.1) 和 Chrome 31.0.1604.0 canary 在 Mac OS X 上无法使用 Fiddle。请检查。 - Burak Erdem
16
已修复:http://jsfiddle.net/6U5q2/270/。请注意,这是针对v2.3.2版本的。不确定是否适用于3.x版本。 - Eric Freese
1
在XHTML中,我不能在属性值中使用 <>。将它们分别更改为 &lt;&gt; 时,它们会按原样显示在按钮上(用户可以看到纯HTML)。有任何想法如何解决这个问题吗? - Sergiy Belozorov
14
data-loading-text自v3.3.5起已被弃用,并将在v4中删除。 - Jonathan
4
@Jonathan 如果在v3.3.5中已经废弃了,那么在v3.3.5之后和v4中的替代方案是什么? - PaladiN
显示剩余4条评论

66

1
嗨,@Eru Penkman。你的版本和原版有什么区别? - Ivan Wang
嗨,伊万,抱歉我一直没有更新我的ladda副本!它仍然是原始版本,我已经删除了之前的评论。对此感到抱歉! - actual_kangaroo

14
为了让 @flion 的解决方案看起来非常好,你可以调整图标的中心点,这样它就不会上下晃动。在小字体大小下,这看起来很正确:
.glyphicon-refresh.spinning {
  transform-origin: 48% 50%;
}

1
.glyphicon-refresh.spinning { transform-origin: 50% 58%; } 对我有效。 - oluckyman
嗯,{ transform-origin: 50% 49%; } 在我使用 cog 的情况下解决了我的问题。 - Vitor Canova
我也注意到了这种晃动,但是更改这些数字的理由是什么?我应该如何进行调整? - elachell

5

一种懒人的方法是使用UTF-8实体代码表示半圆:\25E0(也称为&#x25e0;),看起来像◠,然后通过关键帧动画实现。具体步骤如下:

.busy
{
animation: spin 1s infinite linear;
display:inline-block;
font-weight: bold;
font-family: sans-serif;
font-size: 35px;
font-style:normal;
color:#555;
}

.busy::before
{
content:"\25E0";
}

@keyframes spin
{
0% {transform: rotate(0deg);}
100% {transform: rotate(359deg);}
}
<i class="busy"></i>


2
这是我针对Bootstrap 4的解决方案:
<button id="search" class="btn btn-primary" 
data-loading-text="<i class='fa fa-spinner fa-spin fa-fw' aria-hidden='true'></i>Searching">
  Search
</button>

var setLoading = function () {
  var search = $('#search');
  if (!search.data('normal-text')) {
    search.data('normal-text', search.html());
  }
  search.html(search.data('loading-text'));
};

var clearLoading = function () {
  var search = $('#search');
  search.html(search.data('normal-text'));
};

setInterval(() => {
  setLoading();
  setTimeout(() => {
    clearLoading();
  }, 1000);
}, 2000);

请在JSFiddle上查看。


2

这些是我基于纯SVG和CSS动画制作的。不要关注下面片段中的JS代码,它只是用于演示目的。随意根据我的样式制作自定义样式,非常容易。

原始答案翻译为“最初的回答”

var svg = d3.select("svg"),
    columnsCount = 3;

['basic', 'basic2', 'basic3', 'basic4', 'loading', 'loading2', 'spin', 'chrome', 'chrome2', 'flower', 'flower2', 'backstreet_boys'].forEach(function(animation, i){
  var x = (i%columnsCount+1) * 200-100,
      y = 20 + (Math.floor(i/columnsCount) * 200);
  
  
  svg.append("text")
    .attr('text-anchor', 'middle')
    .attr("x", x)
    .attr("y", y)
    .text((i+1)+". "+animation);
  
  svg.append("circle")
    .attr("class", animation)
    .attr("cx",  x)
    .attr("cy",  y+40)
    .attr("r",  16)
});
circle {
  fill: none;
  stroke: #bbb;
  stroke-width: 4
}

.basic {
  animation: basic 0.5s linear infinite;
  stroke-dasharray: 20 80;
}

@keyframes basic {
  0%    {stroke-dashoffset: 100;}
  100%  {stroke-dashoffset: 0;}
}

.basic2 {
  animation: basic2 0.5s linear infinite;
  stroke-dasharray: 80 20;
}

@keyframes basic2 {
  0%    {stroke-dashoffset: 100;}
  100%  {stroke-dashoffset: 0;}
}

.basic3 {
  animation: basic3 0.5s linear infinite;
  stroke-dasharray: 20 30;
}

@keyframes basic3 {
  0%    {stroke-dashoffset: 100;}
  100%  {stroke-dashoffset: 0;}
}

.basic4 {
  animation: basic4 0.5s linear infinite;
  stroke-dasharray: 10 23.3;
}

@keyframes basic4 {
  0%    {stroke-dashoffset: 100;}
  100%  {stroke-dashoffset: 0;}
}

.loading {
  animation: loading 1s linear infinite;
  stroke-dashoffset: 25;
}

@keyframes loading {
  0%    {stroke-dashoffset: 0;    stroke-dasharray: 50 0; }
  50%   {stroke-dashoffset: -100; stroke-dasharray: 0 50;}
  100%  { stroke-dashoffset: -200;stroke-dasharray: 50 0;}
}

.loading2 {
  animation: loading2 1s linear infinite;
}

@keyframes loading2 {
  0% {stroke-dasharray: 5 28.3;   stroke-dashoffset: 75;}
  50% {stroke-dasharray: 45 5;    stroke-dashoffset: -50;}
  100% {stroke-dasharray: 5 28.3; stroke-dashoffset: -125; }
}

.spin {
  animation: spin 1s linear infinite;
  stroke-dashoffset: 25;
}

@keyframes spin {
  0%    {stroke-dashoffset: 0;    stroke-dasharray: 33.3 0; }
  50%   {stroke-dashoffset: -100; stroke-dasharray: 0 33.3;}
  100%  { stroke-dashoffset: -200;stroke-dasharray: 33.3 0;}
}

.chrome {
  animation: chrome 2s linear infinite;
}

@keyframes chrome {
  0%    {stroke-dasharray: 0 100; stroke-dashoffset: 25;}
  25%   {stroke-dasharray: 75 25; stroke-dashoffset: 0;}
  50%   {stroke-dasharray: 0 100;  stroke-dashoffset: -125;}
  75%    {stroke-dasharray: 75 25; stroke-dashoffset: -150;}
  100%   {stroke-dasharray: 0 100; stroke-dashoffset: -275;}
}

.chrome2 {
  animation: chrome2 1s linear infinite;
}

@keyframes chrome2 {
  0%    {stroke-dasharray: 0 100; stroke-dashoffset: 25;}
  25%   {stroke-dasharray: 50 50; stroke-dashoffset: 0;}
  50%   {stroke-dasharray: 0 100;  stroke-dashoffset: -50;}
  75%   {stroke-dasharray: 50 50;  stroke-dashoffset: -125;}
  100%  {stroke-dasharray: 0 100;  stroke-dashoffset: -175;}
}

.flower {
  animation: flower 1s linear infinite;
}

@keyframes flower {
  0%    {stroke-dasharray: 0  20; stroke-dashoffset: 25;}
  50%   {stroke-dasharray: 20 0;  stroke-dashoffset: -50;}
  100%  {stroke-dasharray: 0 20;  stroke-dashoffset: -125;}
}

.flower2 {
  animation: flower2 1s linear infinite;
}

@keyframes flower2 {
  0%    {stroke-dasharray: 5 20;  stroke-dashoffset: 25;}
  50%   {stroke-dasharray: 20 5;  stroke-dashoffset: -50;}
  100%  {stroke-dasharray: 5 20;  stroke-dashoffset: -125;}
}

.backstreet_boys {
  animation: backstreet_boys 3s linear infinite;
}

@keyframes backstreet_boys {
  0%    {stroke-dasharray: 5 28.3;  stroke-dashoffset: -225;}
  15%    {stroke-dasharray: 5 28.3;  stroke-dashoffset: -300;}
  30%   {stroke-dasharray: 5 20;  stroke-dashoffset: -300;}
  45%    {stroke-dasharray: 5 20;  stroke-dashoffset: -375;}
  60%   {stroke-dasharray: 5 15;  stroke-dashoffset: -375;}
  75%    {stroke-dasharray: 5 15;  stroke-dashoffset: -450;}
  90%   {stroke-dasharray: 5 15;  stroke-dashoffset: -525;}
  100%   {stroke-dasharray: 5 28.3;  stroke-dashoffset: -925;}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<svg width="600px" height="700px"></svg>

也可在CodePen上找到: https://codepen.io/anon/pen/PeRazr,这是"最初的回答"。

1
这是一种受Bulma启发的完整CSS解决方案。只需添加:
    .button {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      position: relative;
      min-width: 200px;
      max-width: 100%;
      min-height: 40px;
      text-align: center;
      cursor: pointer;
    }

    @-webkit-keyframes spinAround {
      from {
        -webkit-transform: rotate(0deg);
        transform: rotate(0deg);
      }
      to {
        -webkit-transform: rotate(359deg);
        transform: rotate(359deg);
      }
    }
    @keyframes spinAround {
      from {
        -webkit-transform: rotate(0deg);
        transform: rotate(0deg);
      }
      to {
        -webkit-transform: rotate(359deg);
        transform: rotate(359deg);
      }
    }

    .button.is-loading {
      text-indent: -9999px;
      box-shadow: none;
      font-size: 1rem;
      height: 2.25em;
      line-height: 1.5;
      vertical-align: top;
      padding-bottom: calc(0.375em - 1px);
      padding-left: 0.75em;
      padding-right: 0.75em;
      padding-top: calc(0.375em - 1px);
      white-space: nowrap;
    }

    .button.is-loading::after  {
      -webkit-animation: spinAround 500ms infinite linear;
      animation: spinAround 500ms infinite linear;
      border: 2px solid #dbdbdb;
      border-radius: 290486px;
      border-right-color: transparent;
      border-top-color: transparent;
      content: "";
      display: block;
      height: 1em;
      position: relative;
      width: 1em;
    }

1

我发现唯一有效的方法是在这里发布的帖子: https://dev59.com/dnA75IYBdhLWcg3wT3L8#44548729

我进行了改进,现在它提供了所有这些功能:

  • 点击后禁用按钮
  • 使用本机bootstrap显示动画加载图标
  • 在页面加载完成后重新启用按钮
  • 页面加载完成时文本恢复原样

Javascript:

$(document).ready(function () {
    $('.btn').on('click', function() {
        var e=this;
        setTimeout(function() {
            e.innerHTML='<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Searching...';
            e.disabled=true;
        },0);
        return true;
    });
});

欢迎来到 Stack Overflow。我没有看到您使用 Andreas 使用的解决方案,也没有在提供的代码中看到按钮何时重新启用或恢复。 - Jason Aller
你说得对,那是另一个答案,我已经更新了链接。至于按钮如何重新启用,它是有效的。我认为这与它被禁用在setTimeout()函数内有关,当页面完成加载时,该函数内发生的所有事情都会被撤消。这是一个非常干净的解决方案。 - Colin
可能是Bootstrap正在处理重新启用和文本恢复。请在测试页面上尝试运行此代码,而不使用Bootstrap JavaScript。 - Jason Aller
这对我在表单提交按钮上起作用。 - Thimira Dunuville

0
你可以使用Bootstrap spinner。使用“position:absolute”将两个按钮叠在一起。使用JavaScript代码,您可以删除前面的按钮,后面的按钮将显示出来。

        button {
            position: absolute;
            top: 50px;
            left: 150px;
            width: 150px;
            font-size: 120%;
            padding: 5px;
            background: #B52519;
            color: #EAEAEA;
            border: none;
            margin: 120px;
            border-radius: 5px;
            display: flex;
            align-content: center;
            justify-content: center;
            transition: all 0.5s;
            height: 40px
        }

        #orderButton:hover {
            color: #c8c8c8;
        }
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">

<button><div class="spinner-border"></div></button>
<button id="orderButton" onclick="this.style.display= 'none';">Order!</button>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接