• 网页按钮点击动画


    要求

    一个按钮,每点击一次在大小可随时变化的按钮表面生成一个实心圆形,对每个圆形配置的时间 T T T(单位:毫秒)内有如下过程:

    1. i i i次点击生成一个圆形 C i C_i Ci,并设置 t i = 0 t_i=0 ti=0
    2. 时间 t i = 0 t_i=0 ti=0时实心圆形直径为0, t i = T t_i=T ti=T时整个按钮表面的任意一点都在圆形内, t i < T t_iti<T时整个按钮表面始终存在一点不在圆形内;
    3. t i = 0 t_i=0 ti=0时圆形透明度为半透明, t i = T t_i=T ti=T时为透明。

    实现

    动态添加DOM元素

    诶哟图丢了

    DOCTYPE html>
    <html>
    <style>
        body {
            text-align: center;
            padding: 5rem;
        }
    
        .content {
            display: inline-block;
            position: relative;
            overflow: hidden;
            margin: 20px;
            box-sizing: border-box;
            transition: all ease-in-out .2s;
        }
    
        .content:hover {
            background-color: #f001;
        }
    
        .circle {
            width: 0;
            height: 0;
            border-radius: 100%;
            border-style: solid;
            z-index: 1;
            position: absolute;
            border-color: #f003;
            box-sizing: border-box;
            opacity: 0;
        }
    
        .text {
            display: table-cell;
            width: 300px;
            height: 100px;
            text-align: center;
            vertical-align: middle;
        }
    
        @keyframes ani {
            0% {
                border-width: 0px;
                opacity: .8;
                transform: translate(0, 0);
            }
    
            100% {
                opacity: 0;
            }
        }
    style>
    
    <body>
        <div class="container">
            <span class="content" id="content">
                <div class="text">
                    button
                div>
            span>
        div>
    body>
    
    <script>
        const TIME = 500;
        document.getElementById('content').addEventListener(
            'click',
            (e) => {
                var e = event || window.event;
                var target = document.getElementById('content');
                var rect = target.getBoundingClientRect();
                var circle = document.createElement('div');
                circle.className = 'circle'
                var x = e.clientX - rect.left;
                var y = e.clientY - rect.top;
                var w = Math.max(target.offsetWidth - x, x);
                var h = Math.max(target.offsetHeight - y, y);
                var d = Math.sqrt(w * w + h * h);
                circle.style = `border-width:${d}px;left:${x}px;top:${y}px;animation:ani ${TIME}ms ease-out 0s 1;transform:translate(-${d}px,-${d}px)`;
                target.appendChild(circle);
                setTimeout(() => { circle.parentElement.removeChild(circle) }, TIME); // 动画结束就去掉元素,要不然元素越来越多
            }
        )
    script>
    
    html>
    
    • 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
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87

    canvas动画+Interval

    诶哟图丢了

    DOCTYPE html>
    <html>
    <style>
        body {
            text-align: center;
            padding: 5rem;
        }
    
        .content {
            display: inline-block;
            position: relative;
            overflow: hidden;
            margin: 20px;
            box-sizing: border-box;
            transition: all ease-in-out .2s;
        }
    
        .content:hover {
            background-color: #f001;
        }
    
        #canvas {
            position: absolute;
            left: 0;
            right: 0;
            top: 0;
            bottom: 0;
            width: 100%;
            height: 100%;
        }
    
        .text {
            display: table-cell;
            width: 30vw;
            height: 10vw;
            text-align: center;
            vertical-align: middle;
        }
    
        @keyframes ani {
            0% {
                border-width: 0px;
                opacity: .8;
                transform: translate(0, 0);
            }
    
            100% {
                opacity: 0;
            }
        }
    style>
    
    <body>
        <div class="container">
            <span class="content" id="content">
                <canvas id="canvas">canvas>
                <div class="text">
                    button
                div>
            span>
        div>
    body>
    
    <script>
        const TICK = 1000 / 30;
        const TIME = 500;
        const CONTENT = document.getElementById('content');
        const CANVAS = document.getElementById("canvas");
        const DEBUG = document.getElementById("debug");
        const ROUND_RAD = 2 * Math.PI;
        const ZOOM = 3;  // 因为动画很快所以图形边缘是否锐利没那么重要,故适度缩小绘图
        var circles = [];
    
        CONTENT.addEventListener(
            'click',
            (e) => {
                let rect = CONTENT.getBoundingClientRect();
                let w = CONTENT.offsetWidth;
                let h = CONTENT.offsetHeight;
                let x = (e.clientX - rect.left) / w;
                let y = (e.clientY - rect.top) / h;
                let dx = Math.max(x, 1 - x);
                let dy = Math.max(y, 1 - y);
                circles.push({
                    x: x,
                    y: y,
                    rMax: Math.sqrt(dx * dx + dy * dy) / Math.sqrt(2),
                    age: 0,
                })
            }
        )
    
        function callback () {
            let rect = CONTENT.getBoundingClientRect();  // 元素大小是可变的,考虑到css动画,元素大小和窗口大小也没必然联系
            let width = CONTENT.offsetWidth / ZOOM;
            let height = CONTENT.offsetHeight / ZOOM;
            let scale = Math.sqrt(width * width + height * height);
            CANVAS.width = width;
            CANVAS.height = height;
    
            var ctx = CANVAS.getContext("2d");
            while (circles[0] && circles[0].deleted) {
                circles.shift();
            }
            for (let i = 0, len = circles.length; i < len; i++) {
                const circle = circles[i];
    
                var age = circle.age * TICK / TIME;
                var opacity = (1 - age) * .3;
                if (opacity <= 0) {
                    circle.deleted = true;
                    continue;
                }
                circle.age += 1
    
                ctx.beginPath();
                ctx.fillStyle = `rgba(255,0,0,${opacity})`;
                ctx.arc(circle.x * width, circle.y * height, age * circle.rMax * scale, 0, ROUND_RAD);
                ctx.fill();
                ctx.closePath();
            }
        }
    
        setInterval(callback, TICK);
    script>
    
    html>
    
    • 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
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127

    canvas动画+requestAnimationFrame

    诶哟图丢了

    DOCTYPE html>
    <html>
    <style>
        body {
            text-align: center;
            padding: 5rem;
        }
    
        .content {
            display: inline-block;
            position: relative;
            overflow: hidden;
            margin: 20px;
            box-sizing: border-box;
            transition: all ease-in-out .2s;
        }
    
        .content:hover {
            background-color: #f001;
        }
    
        #canvas {
            position: absolute;
            left: 0;
            right: 0;
            top: 0;
            bottom: 0;
            width: 100%;
            height: 100%;
        }
    
        .text {
            display: table-cell;
            width: 30vw;
            height: 10vw;
            text-align: center;
            vertical-align: middle;
        }
    
        @keyframes ani {
            0% {
                border-width: 0px;
                opacity: .8;
                transform: translate(0, 0);
            }
    
            100% {
                opacity: 0;
            }
        }
    style>
    
    <body>
        <div class="container">
            <span class="content" id="content">
                <canvas id="canvas">canvas>
                <div class="text">
                    button
                div>
            span>
        div>
    body>
    
    <script>
        const TIME = 500;
        const CONTENT = document.getElementById('content');
        const CANVAS = document.getElementById("canvas");
        const DEBUG = document.getElementById("debug");
        const ROUND_RAD = 2 * Math.PI;
        const ZOOM = 3;
        var circles = [];
        var lastTime = new Date().getTime();
    
        CONTENT.addEventListener(
            'click',
            (e) => {
                let rect = CONTENT.getBoundingClientRect();
                let w = CONTENT.offsetWidth;
                let h = CONTENT.offsetHeight;
                let x = (e.clientX - rect.left) / w;
                let y = (e.clientY - rect.top) / h;
                let dx = Math.max(x, 1 - x);
                let dy = Math.max(y, 1 - y);
                circles.push({
                    x: x,
                    y: y,
                    rMax: Math.sqrt(dx * dx + dy * dy) / Math.sqrt(2),
                    age: 0,
                })
            }
        )
    
        function callback () {
            let now = new Date().getTime();
            let tick = now - lastTime;
            lastTime = now;
            let rect = CONTENT.getBoundingClientRect();
            let width = CONTENT.offsetWidth / ZOOM;
            let height = CONTENT.offsetHeight / ZOOM;
            let scale = Math.sqrt(width * width + height * height);
            CANVAS.width = width;
            CANVAS.height = height;
    
            var ctx = CANVAS.getContext("2d");
            while (circles[0] && circles[0].deleted) {
                circles.shift();
            }
            for (let i = 0, len = circles.length; i < len; i++) {
                const circle = circles[i];
    
                var age = circle.age * tick / TIME;
                var opacity = (1 - age) * .3;
                if (opacity <= 0) {
                    circle.deleted = true;
                    continue;
                }
                circle.age += 1
    
                ctx.beginPath();
                ctx.fillStyle = `rgba(255,0,0,${opacity})`;
                ctx.arc(circle.x * width, circle.y * height, age * circle.rMax * scale, 0, ROUND_RAD);
                ctx.fill();
                ctx.closePath();
            }
            requestAnimationFrame(callback);
        }
        requestAnimationFrame(callback);
    script>
    
    html>
    
    • 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
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
  • 相关阅读:
    28.STM32电阻与电容触摸屏幕
    [附源码]Python计算机毕业设计Django学习帮扶网站设计与实现
    L4W2KT作业 Keras教程
    CharacterEncodingFilter的用法
    Kubernetes PDB
    ElasticSearch第三讲:ES详解 - Elastic Stack生态和场景方案
    互联网快讯:吉利正式收购魅族;胰岛素集采在31省全面落地
    flutter sdk提供完整页面的ui
    Node学习笔记之Node简介
    Qt将GeoJson文件转为mif文件的示例
  • 原文地址:https://blog.csdn.net/dscn15848078969/article/details/126315378