• JavaScript动画库:Anime.js


    前言

    今天简单学习一下JavaScript动画库:Anime.js。官网的介绍是:

    Anime.js (/ˈæn.ə.meɪ/) 是一个轻量的JavaScript 动画库, 拥有简单而强大的API。
    可对 CSS 属性、 SVG、 DOM 和JavaScript 对象进行动画。
    开源、免费、极小、简单易用

    中文文档:https://www.animejs.cn/

    下面会按照官方文档的顺序进行简单学习。

    安装及引入

    安装

    npm install animejs --save
    
    • 1

    引入

    import anime from 'animejs';
    
    • 1

    如果你像我一样用的是ts 那么你还需要下载

    npm i --save-dev @types/animejs
    
    • 1

    动画的目标对象

    CSS选择器

    <div class="item"> </div>
    <el-button type="primary" @click="move">移动</el-button>
    
    let move = () => {
        anime({
            targets: '.item',
            translateX: 250
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述
    通过.item 类获取到该元素,让后使其水平移动250px

    DOM元素 /元素序列

    使用DOM节点或节点的集合作为动画目标

    let move = () => {
        let elements = document.querySelectorAll('.item');
        anime({
            targets: elements,
            translateX: 250
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    数组

    以数组作为动画目标。

    let move = () => {
        anime({
            targets: ['.item1', '.item2'],
            translateX: 250
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

    可动画的目标属性

    css属性

    对目标的CSS属性进行动画

    这里官网提示我们:大多数CSS属性都会导致布局更改或重新绘制,并会导致动画不稳定。 因此尽可能优先考虑opacity和CSS transforms。
    一些常见的会引起重绘的属性比如:widthheighttopleftrightbottom

    let move = () => {
        anime({
            targets: '.item',
            left: '240px',
            backgroundColor: 'blue',
            borderRadius: ['0%', '50%'],
            easing: 'easeInOutQuad'
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    CSS3 TRANSFORMS 属性

    针对CSS的transforms属性动画。单位可以省略。

     anime({
         targets: '.item',
         translateX: 300,
         scale: 2,
         easing: 'easeInOutQuad'
     })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

    JAVASCRIPT对象属性

    包含数值的任何Object属性都可以设置动画。

        var objPropLogEl = document.querySelector('.item');
    
        var myObject = {
            prop1: 0,
            prop2: '0%'
        }
    
        anime({
            targets: myObject,
            prop1: 50,
            prop2: '100%',
            easing: 'linear',
            round: 1,
            update: function () {
                objPropLogEl.innerHTML = myObject.prop1 + '    ' + myObject.prop2;
            }
        });
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在这里插入图片描述

    DOM属性

    任何包含数值的DOM属性都可以设置动画。

    anime({
      targets: '.dom-attribute-demo input',
      value: [0, 1000],
      round: 1,
      easing: 'easeInOutExpo'
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

    SVG属性

    与任何其他DOM属性一样,包含至少一个数值的所有SVG属性都可以设置动画。

    anime({
      targets: ['.svg-attributes-demo polygon', 'feTurbulence', 'feDisplacementMap'],
      points: '64 128 8.574 96 8.574 32 64 0 119.426 32 119.426 96',
      baseFrequency: 0,
      scale: 1,
      loop: true,
      direction: 'alternate',
      easing: 'easeInOutExpo'
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    动画基础参数

    duration: 持续时间,默认1000毫秒

    anime({
         targets: '.item',
         translateX: 300,
         duration: 3000
     });
    
    • 1
    • 2
    • 3
    • 4
    • 5

    delay: 延迟,默认0毫秒

    endDelay: 末端延时,默认0毫秒

    easing: 时间曲线,默认值easeOutElastic(1, .5),有些值不清楚,可以自己看一下文档
    可选值:

    • linear (匀速)

    • 不匀速
      在这里插入图片描述

    • 三次贝塞尔,比如:easing: 'cubicBezier(.5, .05, .1, .3)',这名词是啥我也不清楚。

    • 弹簧,这也不太清楚,具体见:弹簧

    • 弹跳,不清楚,具体见:弹跳

    • 台阶,定义动画到达其结束值所需的跳转次数,例如: easing: 'steps(5)'

    • 自定义,通过函数返回当前动画的时间

    anime({
      targets: '.custom-easing-demo .el',
      translateX: 270,
      direction: 'alternate',
      loop: true,
      duration: 2000,
      easing: function(el, i, total) {
        return function(t) {
          return Math.pow(Math.sin(t * (i + 1)), total);
        }
      }
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    round: 四舍五入,说实话没太弄明白,不过1的时候没有小数点

    anime({
         targets: '.item',
         innerHTML: [0, 100],
         easing: 'linear',
         round: 1,
         duration: 2000
     });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述
    特殊属性
    使用Object作为值为动画的每个属性定义特定参数。未在Object中指定的其他属性继承自主动画。

    anime({
      targets: '.specific-prop-params-demo .el',
      translateX: {
        value: 250,
        duration: 800
      },
      rotate: {
        value: 360,
        duration: 1800,
        easing: 'easeInOutSine'
      },
      scale: {
        value: 2,
        duration: 1600,
        delay: 800,
        easing: 'easeInOutQuart'
      },
      delay: 250 
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    先在800毫秒内平移250px,然后在1800毫秒内旋转360度,最后放大两倍
    在这里插入图片描述

    函数
    为动画的每个目标和属性设置不同的值。函数接收三个参数,分别是:

    • target,目标元素
    • index,动画目标的索引
    • targetsLength,总动画目标数
    anime({
      targets: '.function-based-params-demo .el',
      translateX: 270,
      direction: 'alternate',
      loop: true,
      delay: function(el, i, l) {
        return i * 100;
      },
      endDelay: function(el, i, l) {
        return (l - i) * 100;
      }
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    方向和循环

    direction: 方向
    normal,正方向动画;reverse,反方向动画;alternate往返动画

    loop: 循环,可以是具体的次数。如果是true则表示无限循环

    autoplay: 自动播放,truefalse

    动画赋值方式

    无单位赋值

    前面已经说过了对于px之类的单位可以省略,例如

    anime({
      targets: '.unitless-values-demo .el',
      translateX: 250, // -> '250px'
      rotate: 540 // -> '540deg'
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5

    有单位数值
    强制动画使用某个单位并自动转换初始目标值。

    想对数值
    添加,减去或乘以原始值。有+=-=*= 这三个值
    例如宽度变为原来的两倍,宽度减少50px

     anime({
         targets: '.item',
         width: {
             value: '*=2',
             duration: 1800,
             easing: 'easeInOutSine'
         },
         height: {
             value: '-=50px',
             duration: 1000,
             delay: 1800,
             easing: 'easeInOutSine'
         }
     });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述
    颜色
    anime.js 接受并转换Haxadecimal(十六进制),RGB,RGBA,HSL和HSLA颜色值。注:不支持颜色名称,比如red

    示例

    .item {
        position: relative;
        width: 100px;
        height: 100px;
        margin-bottom: 10px;
        background-color: #61afff;
    }
    
     anime.timeline({
            endDelay: 1000,
            easing: 'easeInOutQuad',
            direction: 'alternate',
            loop: true
        })
            .add({ targets: '.item', background: '#555851' }, 0)
            .add({ targets: '.item', translateX: 270 }, 0);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述
    设定动画初始值
    强制动画以指定值开始。必须以数组的形式给定,第一个元素是起始值,第二个元素是终止值

    anime({
      targets: '.el.from-to-values',
      translateX: [100, 250], // from 100 to 250
      delay: 500,
      direction: 'alternate',
      loop: true
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    关键帧

    动画关键帧
    动画关键帧是使用keyframes属性中的数组定义的。如果关键帧内没有指定duration(持续时间),则每个关键帧的持续时间将等于动画总持续时间除以关键帧数。

    anime({
            targets: '.item',
            keyframes: [
                { translateY: -40, duration: 1000 },
                { translateX: 250, duration: 1000 },
                { translateY: 40, duration: 1000 },
                { translateX: 0, duration: 500 },
                { translateY: 0, duration: 500 }
            ],
            duration: 4000,
            easing: 'easeOutElastic(1, .8)',
            loop: true
        })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述
    属性关键帧

    与动画关键帧类似,属性关键帧是使用属性对象的Array定义的。 属性关键帧允许重叠动画,因为每个属性都有自己的关键帧数组。
    如果关键帧内没有指定duration(持续时间),则每个关键帧的持续时间将等于动画总持续时间除以关键帧数。

    官方demo

    anime({
      targets: '.property-keyframes-demo .el',
      translateX: [
        { value: 250, duration: 1000, delay: 500 },
        { value: 0, duration: 1000, delay: 500 }
      ],
      translateY: [
        { value: -40, duration: 500 },
        { value: 40, duration: 500, delay: 1000 },
        { value: 0, duration: 500, delay: 1000 }
      ],
      scaleX: [
        { value: 4, duration: 100, delay: 500, easing: 'easeOutExpo' },
        { value: 1, duration: 900 },
        { value: 4, duration: 100, delay: 500, easing: 'easeOutExpo' },
        { value: 1, duration: 900 }
      ],
      scaleY: [
        { value: [1.75, 1], duration: 500 },
        { value: 2, duration: 50, delay: 1000, easing: 'easeOutExpo' },
        { value: 1, duration: 450 },
        { value: 1.75, duration: 50, delay: 1000, easing: 'easeOutExpo' },
        { value: 1, duration: 450 }
      ],
      easing: 'easeOutElastic(1, .8)',
      loop: true
    });
    
    • 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

    在这里插入图片描述

    交错动画

    基础交错动画

     anime({
         targets: '.item',
         translateX: 270,
         delay: anime.stagger(1000) // 每个元素的延迟增加1000毫秒。
     })
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    设定交错开始值
    从特定值开始产生交错效果。

    anime({
      targets: '.staggering-start-value-demo .el',
      translateX: 270,
      delay: anime.stagger(100, {start: 500}) // 延迟从500ms开始,然后每个元素增加100ms。
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5

    设定交错范围值
    在两个数字之间均匀分配值。

    官方demo:

    anime({
      targets: '.range-value-staggering-demo .el',
      translateX: 270,
      rotate: anime.stagger([-360, 360]), // 旋转将在-360deg到360deg之间均匀分布在所有元素之间
      easing: 'easeInOutQuad'
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

    交错动画开始位置
    从特定位置开始交错效果。

    • first(默认),从第一个元素开始效果
    • laster,从最后一个元素开始效果
    • center,从中间开始效果
    • index,从指定索引开始效果
    anime({
      targets: '.staggering-from-demo .el',
      translateX: 270,
      delay: anime.stagger(100, {from: 'center'})   //从中间开始执行效果,然后每个元素增加100毫秒
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    交错动画方向
    更改交错动画的顺序。

    • normal(默认),正常交错方向,从第一个元素到最后一个元素。
    • reverse,倒退交错方向,从最后一个元素到第一个元素
    anime({
      targets: '.staggering-direction-demo .el',
      translateX: 270,
      delay: anime.stagger(100, {direction: 'reverse'})
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    交错的时间曲线
    使用easing函数设置交错值

    anime({
      targets: '.staggering-easing-demo .el',
      translateX: 270,
      delay: anime.stagger(300, {easing: 'easeOutQuad'})
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    网格交错
    基于数组的交错值,以产生“波纹”效应。两个值的数组,第一个值是列数,第二个值是行数

    anime({
      targets: '.staggering-grid-demo .el',
      scale: [
        {value: .1, easing: 'easeOutSine', duration: 500},
        {value: 1, easing: 'easeInOutQuad', duration: 1200}
      ],
      delay: anime.stagger(200, {grid: [14, 5], from: 'center'})
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述
    网格交错方向
    定义网格交错 效果的方向

    • x 沿着x轴
    • y 沿着y轴
    anime({
      targets: '.staggering-axis-grid-demo .el',
      translateX: anime.stagger(10, {grid: [14, 5], from: 'center', axis: 'x'}),
      translateY: anime.stagger(10, {grid: [14, 5], from: 'center', axis: 'y'}),
      rotateZ: anime.stagger([0, 90], {grid: [14, 5], from: 'center', axis: 'x'}),
      delay: anime.stagger(200, {grid: [14, 5], from: 'center'}),
      easing: 'easeInOutQuad'
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    时间轴

    基础时间轴

    时间轴可让你将多个动画同步在一起。
    默认情况下,添加到时间轴的每个动画都会在上一个动画结束时开始。

    创建时间轴

    var myTimeline = anime.timeline(parameters);
    
    • 1

    将动画添加到时间轴

    myTimeline.add(parameters, offset);
    
    • 1

    基本示例

    // 使用默认参数创建时间轴
    var tl = anime.timeline({
      easing: 'easeOutExpo',
      duration: 750
    });
    
    // 增加子项
    tl
    .add({
      targets: '.basic-timeline-demo .el.square',
      translateX: 250,
    })
    .add({
      targets: '.basic-timeline-demo .el.circle',
      translateX: 250,
    })
    .add({
      targets: '.basic-timeline-demo .el.triangle',
      translateX: 250,
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在这里插入图片描述

    时间轴偏移量

    可以使用时间轴的 .add()函数的第二个可选参数指定时间偏移。它定义动画在时间轴中的开始时间,如果未指定偏移,则动画将在上一个动画结束后开始。
    偏移可以相对于最后一个动画,也可以相对于整个时间轴。

    在这里插入图片描述

    // 使用默认参数创建时间轴
    var tl = anime.timeline({
      easing: 'easeOutExpo',
      duration: 750
    });
    
    tl
    .add({
      targets: '.offsets-demo .el.square',
      translateX: 250,
    })
    .add({
      targets: '.offsets-demo .el.circle',
      translateX: 250,
    }, '-=600') // 相对偏移量
    .add({
      targets: '.offsets-demo .el.triangle',
      translateX: 250,
    }, 0); // 绝对偏移量
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    参数继承

    父时间轴实例中设置的参数将由所有子项继承。

    可被继承的参数: targetsdurationdelayendDelayround

    官方示例
    先向右平移250;然后放大两倍,透明度变为0.5;接着三角形渲染180度,最后平移回到0

    var tl = anime.timeline({
      targets: '.params-inheritance-demo .el',
      delay: function(el, i) { return i * 200 },
      duration: 500,
      easing: 'easeOutExpo',
      direction: 'alternate',
      loop: true
    });
    
    tl
    .add({
      translateX: 250,
      // override the easing parameter
      easing: 'spring',
    })
    .add({
      opacity: .5,
      scale: 2
    })
    .add({
      // override the targets parameter
      targets: '.params-inheritance-demo .el.triangle',
      rotate: 180
    })
    .add({
      translateX: 0,
      scale: 1
    });
    
    • 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

    在这里插入图片描述

    动画控制

    播放与暂停

    需要将自动播放autoplay 设置为false

    //播放
    animation.play();
    //暂停
    animation.pause();
    
    • 1
    • 2
    • 3
    • 4

    官方示例

    var animation = anime({
      targets: '.play-pause-demo .el',
      translateX: 270,
      delay: function(el, i) { return i * 100; },
      direction: 'alternate',
      loop: true,
      autoplay: false,
      easing: 'easeInOutSine'
    });
    
    document.querySelector('.play-pause-demo .play').onclick = animation.play;
    document.querySelector('.play-pause-demo .pause').onclick = animation.pause;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    重新开始

    从动画的初始值重新开始动画。

    animation.restart();
    
    • 1

    反转方向

    animation.reverse();
    
    • 1

    瞬移

    跳转到特定时间(以毫秒为单位)。

    animation.seek(timeStamp);
    
    • 1

    回调函数(事件)

    更新事件

    动画开始播放后,每帧都会触发此回调。函数的返回值是当前动画对象

    let update = ref(0)
    let progress = ref(0)
    let move = () => {
        anime({
            targets: '.item',
            translateX: 270,
            duration: 1500,
            update: function (anim) {
                update.value++;
                progress.value = Math.round(anim.progress)
            }
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述

    开始和结束事件

    当动画开始播放时,begin()回调被触发一次。
    动画完成后,会触发一次complete()回调。
    如果动画的持续时间为0,则begin()和complete()都会被调用。

     begin: function(anim) {
        beginLogEl.value = 'began : ' + anim.began;
      },
      complete: function(anim) {
        completeLogEl.value = 'completed : ' + anim.completed;
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    循环开始和结束事件

    每次循环开始时都会触发一次loopBegin() 回调。
    每次循环结束时,就会触发一次loopComplete()回调函数。

    loopBegin: function(anim) {
        loopBegan++;
        beginLogEl.value = 'loop began : ' + loopBegan;
      },
      loopComplete: function(anim) {
        loopCompleted++;
        completeLogEl.value = 'loop completed : ' + loopCompleted;
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    改变事件

    在动画的delay和endDelay之间的每个帧上触发此回调。
    注: 使用该函数需要设置delayendDelay

    **var changes = 0;
    
    anime({
      targets: '.change-demo .el',
      translateX: 270,
      delay: 1000,
      endDelay: 1000,
      direction: 'alternate',
      loop: true,
      easing: 'easeInOutCirc',
      update: function(anim) {
        progressLogEl.value = 'progress : '+Math.round(anim.progress)+'%';
      },
      change: function() {
        changes++;
        changeLogEl.value = 'changes : ' + changes;
      }
    });**
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    改变开始事件和改变结束事件

    每次动画改变开始时都会触发changeBegin()回调
    每次动画改变结束时都会触发changeComplete()回调
    动画方向将影响触发changeBegin()和changeComplete()的顺序

    注: 使用该函数需要设置delayendDelay

    var changeBegan = 0;
    var changeCompleted = 0;
    
    anime({
      targets: '.changeBegin-chnageComplete-demo .el',
      translateX: 240,
      delay: 1000,
      endDelay: 1000,
      loop: true,
      direction: 'alternate',
      easing: 'easeInOutCirc',
      update: function(anim) {
        progressLogEl.value = 'progress : '+Math.round(anim.progress)+'%';
      },
      changeBegin: function(anim) {
        changeBegan++;
        beginLogEl.value = 'change began : ' + changeBegan;
      },
      changeComplete: function(anim) {
        changeCompleted++;
        completeLogEl.value = 'change completed : ' + changeCompleted;
      }
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    SVG动画

    略,具体见:svg动画

    ANIME.JS方法

    删除目标

    从正在运行的动画或时间轴中删除目标。targets参数接受与targets 属性相同的值。

    anime.remove(targets)
    
    • 1

    官方示例

    anime({
      targets: '.remove-demo .el',
      translateX: 270,
      direction: 'alternate',
      loop: true,
      easing: 'easeInOutQuad'
    });
    
    document.querySelector('.remove-el-button').addEventListener('click', function() {
      anime.remove('.remove-demo .line:nth-child(2) .el');
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    其他

    略,具体见 ANIME.JS方法

  • 相关阅读:
    校园二手物品交易平台
    大力说企微第一课:企业微信的注册验证和认证
    【狂神说Java】Docker概述 | Docker安装 | Docker的常用命令
    类加载器ClassLoader
    Node.js在携程的落地和最佳实践
    C# 插入排序
    运行pytorch时出现version `CXXABI_1.3.9‘ not found
    【毕设教程】YOLOv7 目标检测网络解读
    Oracle故障案例之-19C时区补丁DSTV38更新
    利用IoDriverObjectType控制内核驱动加载
  • 原文地址:https://blog.csdn.net/weixin_41897680/article/details/126109622