草庐IT

记录-有意思的气泡 Loading 效果

林恒 2024-01-16 原文

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

今日,群友提问,如何实现这么一个 Loading 效果:

这个确实有点意思,但是这是 CSS 能够完成的?

没错,这个效果中的核心气泡效果,其实借助 CSS 中的滤镜,能够比较轻松的实现,就是所需的元素可能多点。参考我们之前的:

圆弧的实现

首先,我们可能需要实现这样一段圆弧:

这里需要用到的技术是:

角向渐变 conic-gradient() + mask 以及两个伪元素。图片示意如下:

 核心代码如下图:

HTML:

<div class="g-container">
  <div class="g-circle"></div>
</div>

CSS:

:root {
    --headColor: hsl(130, 75%, 75%);
    --endColor: hsl(60, 75%, 40%);
}
.g-container {
    position: relative;
    background: #000;
}
.g-circle {
    position: relative;
    width: 300px;
    height: 300px;
    border-radius: 50%;
    background: conic-gradient(
        var(--headColor) 0, 
        var(--headColor) 10%,
        hsl(120, 75%, 70%), 
        hsl(110, 75%, 65%), 
        hsl(100, 75%, 60%),
        hsl(90, 75%, 55%), 
        hsl(80, 75%, 50%),
        hsl(70, 75%, 45%),
        var(--endColor) 30%,
        var(--endColor) 35%,
        transparent 35%
    );
    mask: radial-gradient(transparent, transparent 119px, #000 120px, #000 120px, #000 100%);
    
    &::before,
    &::after {
        content: "";
        position: absolute;
        inset: 0;
        width: 30px;
        height: 30px;
        background: var(--headColor);
        top: 0;
        left: 135px;
        border-radius: 50%;
    }
    
    &::after {
        background: var(--endColor);
        left: unset;
        top: 214px;
        right: 26px;
    }
}

这样,我们就得到了这样一个图形:

气泡的实现

接下来,我们来实现尾部气泡向外扩散的效果。

由于这里涉及了多个气泡的不同运动动画,多个标签元素肯定是少不了了。

因此,接下来我们要做的事情:

  1. 我们需要多一组元素,将其绝对定位到上述圆环的头部或者尾部
  2. 给每个子元素随机设置多个大小不一的圆,颜色保持一致
  3. 给每个子元素随机设置不同方向的,向外扩散的位移动画
  4. 给每个子元素随机设置负的 animation-delay,造成动画上的先后顺序,并以此形成整个无限循环的气泡扩散动画

这里,由于有许多小气泡的动画,这个数量,我设置成了 100。那肯定是不能一个一个手写它们的动画代码,需要借助 SASS/LESS 等预处理器的循环、随机等函数。

核心代码如下:

HTML:

<div class="g-container">
  <div class="g-circle"></div>
  <ul class="g-bubbles">
    <li class="g-bubble"></li>
    // ... 共 100 个 bubble 元素 
    <li class="g-bubble"></li>
  </ul>
</div>

CSS:

// 上面圆环的代码,保持一致,下面只补充气泡动画的代码
.g-bubbles {
    position: absolute;
    width: 30px;
    height: 30px;
    border-radius: 50px;
    top: 100px;
    left: 235px;
    background: var(--headColor);
}

.g-bubble {
    position: absolute;
    border-radius: 50%;
    background-color: inherit;
}

@for $i from 1 through 100 { 
    .g-bubble:nth-child(#{$i}) {
        --rotate: calc(#{random(360)} * 1deg);
        --dis: calc(#{random(100)} * 1px);
        --width: calc(3px + #{random(25)} * 1px);
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: var(--width);
        height: var(--width);
        animation: move #{(random(1500) + 1500) / 1000}s ease-in-out -#{random(3000) / 1000}s infinite;
    }
}

@keyframes move {
    0% {
        transform: translate(-50%, -50%) rotate(0deg);
    }
    75% {
        opacity: .9;
    }
    100% {
        transform: rotateZ(var(--rotate)) translate(-50%, var(--dis));
        opacity: .4;
    }
}

核心在于 @for $i from 1 through 100 { } 这段 SASS 代码内部,我们实现了上面说的 (2)(3)(4) 的功能点!

这样,我们就得到了这样一个效果,在尾部有大量气泡动画,不断向外扩散的效果:

借助滤镜实现粘性气泡效果

OK,到这里整个效果基本就做完了。当然,也是剩下最后最重要的一步,需要让多个气泡之间产生一种粘性融合的效果。

这个技巧在此前非常多篇文章中,也频繁提及过,就是利用 filter: contrast() 滤镜与 filter: blur() 滤镜。

如果你还不了解这个技巧,可以戳我的这篇文章看看:你所不知道的 CSS 滤镜技巧与细节

简述下该技巧:

单独将两个滤镜拿出来,它们的作用分别是:

  1. filter: blur(): 给图像设置高斯模糊效果。
  2. filter: contrast(): 调整图像的对比度。

但是,当他们“合体”的时候,产生了奇妙的融合现象。

仔细看两圆相交的过程,在边与边接触的时候,会产生一种边界融合的效果,通过对比度滤镜把高斯模糊的模糊边缘给干掉,利用高斯模糊实现融合效果。

基于此,我们再简单改造下我们的 CSS 代码,所需要加的代码量非常少:

  1. 加上滤镜 blur() 和 contrast() ,形成融合粘性效果
  2. 加上整个圆环的旋转即可效果
  3. 加上滤镜 hue-rotate(),实现色彩的变换动画
.g-container {
    // ... 保持一致
    background: #000;
    filter: blur(3px) contrast(5);
    animation: rotate 4s infinite linear;
}
@keyframes rotate {
    100% {
        transform: rotate(360deg);
        filter: blur(3px) contrast(5) hue-rotate(360deg);
    }
}

就这样,我们就大致还原了题图的效果:

完整的代码,你可以戳这里:CodePen Demo -- Pure CSS Loading Animation

修复违和感

当然,上面的效果,乍一看还行,仔细看,违和感很重。

原因在于,扩散出来的小球也跟着半圆环一起进行了旋转动画,看上去就有点奇怪。

正确的做法应该是,圆环尾部的气泡应该是原地发散消失的。

那么,怎么能够做到气泡效果,一直发生在圆环的尾部,同时消失的时候又不跟着整个圆环一起进行旋转呢?我们想要的最终效果,应该是这样:

这里,我们可以拆解一下。想象,如果去掉圆环的旋转,其实我们只需要实现这样一个效果即可:

整个动画的核心就转变成了如何实现这么一个效果。看似复杂,其实也很好做。

首先,我们重新改造一下上述的 .g-bubbles

  1. 生成 N 个一样大小的小球元素,定位在整个容器的中间
HTML:
<div class="g-container">
  <div class="g-circle"></div>
  <ul class="g-bubbles">
    <li class="g-bubble"></li>
    // ... 共 200 个 bubble 元素 
    <li class="g-bubble"></li>
  </ul>
</div>

CSS:

.g-bubbles {
    position: absolute;
    width: 30px;
    height: 30px;
    transform: translate(-50%, -50%);
    left: 50%;
    top: 50%;
    border-radius: 50px;
}
.g-bubble {
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: hsl(60, 75%, 40%);
}

得到这么一个效果,所有圆形小点,都暂时汇聚在容器的中心:

这里需要简单解释一下:

其次,我们借助 SASS,按照元素的顺序,把它们顺序排列到圆环轨迹之上:

$count: 200;
@for $i from 1 through $count { 
    .g-bubble:nth-child(#{$i}) {
        --rotate: calc(#{360 / $count} * #{$i} * 1deg);
        transform: 
            rotateZ(var(--rotate)) 
            translate(135px, 0);
        opacity: 1;
    }
}

由于我们设置了 div 小球的个数为 200 个,这样,我们就得到了一圈由 200 个圆形小球形成的圆环:

接下来这一步非常重要,我们设定一个动画:

  1. 让每个小球在动画的 75% ~ 100% 阶段做透明度从 1 到 0 的变换,而 0% ~ 75% 的阶段保持透明度为 0
  2. 让 200 个 div 依次进行这个动画效果(利用负的 animation-delay,从 -0 到 -4000ms),整体上就能形成逐渐消失的效果
@for $i from 1 through $count { 
    .g-bubble:nth-child(#{$i}) {
        --rotate: calc(#{360 / $count} * #{$i} * 1deg);
        --delayTime: calc(4000 * #{$i / $count} * -1ms);
        transform: 
            rotateZ(var(--rotate)) 
            translate(135px, 0);
        opacity: 1;
        animation: showAndHide 4000ms linear var(--delayTime) infinite;
    }
}
@keyframes showAndHide {
    0% {
        opacity: 0;
    }
    75% {
        opacity: 0;
    }
    75.1% {
        opacity: 1;
    }
    100% {
        opacity: 0;
    }
}

这样,我们就得到了一个圆形小球气泡围绕圆环渐次消失的效果:

配合上整个圆环,效果就会是这样:

很接近了,但是没有随机的感觉,气泡也没有散开的动画。解决的方案:

  1. 所以我们需要让气泡在执行透明度变化的同时,进行一个随机的发散位移
  2. 小圆形气泡的大小也可以带上一点随机,同时,在动画过程逐渐缩小

当然,整个动画的基础,还是在容器设置了 滤镜 blur() 和 contrast() 的加持之下的,这样,我们给气泡再补上随机动画散开及缩放的动画:

@for $i from 1 through $count { 
    .g-bubble:nth-child(#{$i}) {
        --rotate: calc(#{360 / $count} * #{$i} * 1deg);
        --delayTime: calc(4000 * #{$i / $count} * -1ms);
        --scale: #{0.4 + random(10) / 10};
        --x: #{-100 + random(200)}px;
        --y: #{-100 + random(200)}px;
        transform: 
            rotateZ(var(--rotate)) 
            translate(135px, 0);
        opacity: 1;
        animation: showAndHide 4000ms linear var(--delayTime) infinite;
    }
}

@keyframes showAndHide {
    0% {
        transform: 
            rotateZ(var(--rotate)) 
            translate(135px, 0);
        opacity: 0;
    }
    75% {
        opacity: 0;
    }
    75.1% {
        transform: 
            rotateZ(var(--rotate)) 
            translate(135px, 0)
            scale(var(--scale));
        opacity: 1;
    }
    100% {
        transform: 
            rotateZ(var(--rotate)) 
            translate(calc(135px + var(--x)), var(--y))
            scale(.2);
        opacity: 0;
    }
}

只看一圈的气泡圆形,我们能得到了这样的效果:

配合上圆环的效果:

配合上父容器的 filter: hue-rotate() 动画,就能实现颜色的动态变换,得到我们最终想要的效果:

这样,没有了第一版本的违和感,整个效果也显得比较自然。

整体代码:

HTML:

<div class="g-container">
  <div class="g-circle"></div>
  <ul class="g-bubbles">
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
    <li class="g-bubble"></li>
  </ul>
</div>

CSS:

body, html {
    width: 100%;
    height: 100%;
    display: grid;
    place-content: center;
    background: #000;
    overflow: hidden;
}
$count: 200;

:root {
    --headColor: hsl(130, 75%, 75%);
    --endColor: hsl(60, 75%, 40%);
}

.g-container {
    position: relative;
    width: 300px;
    height: 300px;
    padding: 100px;
    filter: blur(3px) contrast(3);
    background: #000;
    animation: hueRotate 8s infinite linear;
}

.g-circle {
    position: relative;
    width: 300px;
    height: 300px;
    border-radius: 50%;
    background: conic-gradient(
        var(--headColor) 0, 
        var(--headColor) 2%,
        hsl(120, 75%, 70%), 
        hsl(110, 75%, 65%), 
        hsl(100, 75%, 60%),
        hsl(90, 75%, 55%), 
        hsl(80, 75%, 50%),
        hsl(70, 75%, 45%),
        var(--endColor) 16%,
        var(--endColor) 18%,
        transparent 18%
    );
    mask: radial-gradient(transparent, transparent 119px, #000 120px, #000);
    -webkit-mask: radial-gradient(transparent, transparent 119px, #000 120px, #000);
    animation: rotate 4s infinite -700ms linear;
    
    &::before,
    &::after {
        content: "";
        position: absolute;
        inset: 0;
        width: 32px;
        height: 32px;
        background: var(--headColor);
        top: 0;
        left: 135px;
        border-radius: 50%;
    }
    
    &::after {
        background: var(--endColor);
        left: unset;
        top: 80px;
        right: 10px;
    }
}

.g-bubbles {
    position: absolute;
    width: 30px;
    height: 30px;
    transform: translate(-50%, -50%);
    left: 50%;
    top: 50%;
    border-radius: 50px;
}

.g-bubble {
    position: absolute;
    border-radius: 50%;
    background: var(--endColor);
}

@for $i from 1 through $count { 
    .g-bubble:nth-child(#{$i}) {
        --rotate: calc(#{360 / $count} * #{$i} * 1deg);
        --delayTime: calc(4000 * #{$i / $count} * -1ms);
        --width: 30px;
        --scale: #{0.4 + random(10) / 10};
        --x: #{-100 + random(200)}px;
        --y: #{-100 + random(200)}px;
        width: var(--width);
        height: var(--width);
        transform: 
            rotateZ(var(--rotate)) 
            translate(135px, 0);
        opacity: 1;
        animation: showAndHide 4000ms linear var(--delayTime) infinite;
    }
}

@keyframes showAndHide {
    0% {
        transform: 
            rotateZ(var(--rotate)) 
            translate(135px, 0);
        opacity: 0;
    }
    75% {
        opacity: 0;
    }
    75.1% {
        transform: 
            rotateZ(var(--rotate)) 
            translate(135px, 0)
            scale(var(--scale));
        opacity: 1;
    }
    100% {
        transform: 
            rotateZ(var(--rotate)) 
            translate(calc(135px + var(--x)), var(--y))
            scale(.2);
        opacity: 0;
    }
}

@keyframes rotate {
    100% {
        transform: rotate(-360deg);
    }
}

@keyframes hueRotate {
    100% {
        filter: blur(3px) contrast(3) hue-rotate(360deg);
    }
}

本文转载于:

https://juejin.cn/post/7221320687430942781

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 

有关记录-有意思的气泡 Loading 效果的更多相关文章

  1. ruby - Sinatra:运行 rspec 测试时记录噪音 - 2

    Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/

  2. ruby-on-rails - Rails 5 Active Record 记录无效错误 - 2

    我有两个Rails模型,即Invoice和Invoice_details。一个Invoice_details属于Invoice,一个Invoice有多个Invoice_details。我无法使用accepts_nested_attributes_forinInvoice通过Invoice模型保存Invoice_details。我收到以下错误:(0.2ms)BEGIN(0.2ms)ROLLBACKCompleted422UnprocessableEntityin25ms(ActiveRecord:4.0ms)ActiveRecord::RecordInvalid(Validationfa

  3. ruby-on-rails - 事件记录 : Select max of limit - 2

    我正在尝试将以下SQL查询转换为ActiveRecord,它正在融化我的大脑。deletefromtablewhereid有什么想法吗?我想做的是限制表中的行数。所以,我想删除少于最近10个条目的所有内容。编辑:通过结合以下几个答案找到了解决方案。Temperature.where('id这给我留下了最新的10个条目。 最佳答案 从您的SQL来看,您似乎想要从表中删除前10条记录。我相信到目前为止的大多数答案都会如此。这里有两个额外的选择:基于MurifoX的版本:Table.where(:id=>Table.order(:id).

  4. ruby -::在 Ruby 语法中是什么意思? - 2

    这个问题在这里已经有了答案:WhatisRuby'sdouble-colon`::`?(12个答案)关闭8年前。什么是::?@song||=::TwelveDaysSong.new

  5. ruby - __FILE__ == $PROGRAM_NAME 在 ruby​​ 中是什么意思? - 2

    这个问题在这里已经有了答案:Whatdoes`if__FILE__==$0`meaninRuby(6个答案)关闭6年前。我在审查Ruby代码时偶然发现了这个语法。代码是:if__FILE__==$PROGRAM_NAME#somecode...end我想__FILE__是一个变量,可以让我获取我所在文件的名称?但是$PROGRAM_NAME简化了什么?另外,为什么这个if语句是必需的,因为程序可以使用或不使用它?

  6. ruby-on-rails - 没有参数的 `<<`(小于两倍)是什么意思? - 2

    我在一个我想在formtasticGem中覆盖的方法中找到了这个。该方法如下所示:defto_htmlinput_wrappingdohidden_field_html是什么意思?在第三行做什么?我知道它对数组有什么作用,但在这里我不知道。 最佳答案 你可以这样读:hidden_field_htmllabel_with_nested_checkbox是连接到hidden_​​field_html末尾的参数-为了“清晰”,他们将其分成两行 关于ruby-on-rails-没有参数的`

  7. ruby - Ruby 的 AST 中的 'send' 关键字是什么意思? - 2

    我正在尝试学习Ruby词法分析器和解析器(whitequarkparser)以了解更多有关从Ruby脚本进一步生成机器代码的过程。在解析以下Ruby代码字符串时。defadd(a,b)returna+bendputsadd1,2它导致以下S表达式符号。s(:begin,s(:def,:add,s(:args,s(:arg,:a),s(:arg,:b)),s(:return,s(:send,s(:lvar,:a),:+,s(:lvar,:b)))),s(:send,nil,:puts,s(:send,nil,:add,s(:int,1),s(:int,3))))任何人都可以向我解释生成的

  8. Ruby 守护进程导致 ActiveRecord 记录器 IOError - 2

    我目前正在用Ruby编写一个项目,它使用ActiveRecordgem进行数据库交互,我正在尝试使用ActiveRecord::Base.logger记录所有数据库事件具有以下代码的属性ActiveRecord::Base.logger=Logger.new(File.open('logs/database.log','a'))这适用于迁移等(出于某种原因似乎需要启用日志记录,因为它在禁用时会出现NilClass错误)但是当我尝试运行包含调用ActiveRecord对象的线程守护程序的项目时脚本失败并出现以下错误/System/Library/Frameworks/Ruby.frame

  9. ruby-on-rails - 在 Rails 中更高效地查找或创建多条记录 - 2

    我有一个应用需要发送用户事件邀请。当用户邀请friend(用户)参加事件时,如果尚不存在将用户连接到该事件的新记录,则会创建该记录。我的模型由用户、事件和events_user组成。classEventdefinvite(user_id,*args)user_id.eachdo|u|e=EventsUser.find_or_create_by_event_id_and_user_id(self.id,u)e.save!endendend用法Event.first.invite([1,2,3])我不认为以上是完成我的任务的最有效方法。我设想了一种方法,例如Model.find_or_cr

  10. ruby - 在模块/类之间共享全局记录器 - 2

    在许多ruby​​类之间共享记录器实例的最佳(正确)方法是什么?现在我只是将记录器创建为全局$logger=Logger.new变量,但我觉得有更好的方法可以在不使用全局变量的情况下执行此操作。如果我有以下内容:moduleFooclassAclassBclassC...classZend在所有类之间共享记录器实例的最佳方式是什么?我是以某种方式在Foo模块中声明/创建记录器还是只是使用全局$logger没问题? 最佳答案 在模块中添加常量:moduleFooLogger=Logger.newclassAclassBclassC..

随机推荐