网页按钮点击动画

2023-11-18

要求

一个按钮,每点击一次在大小可随时变化的按钮表面生成一个实心圆形,对每个圆形配置的时间 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_i<T ti<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>

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;
    }
</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>

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;
    }
</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>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

网页按钮点击动画 的相关文章

随机推荐

  • Android SDK的安装教程

    Android SDK的安装教程 Android4 1虽说已经发布了好些天 但由于的我手机比较坑 系统依旧保持在2 3 4 0的都是可望不可即的了 就别说4 1 由于资金的问题 没法换手机 只能另想方法 通过在笔记本上装android4 1
  • java实现,如何在当前时间往后推三十天

    Calendar cal Calendar getInstance cal add Calendar Date 30 Date date cal getTime
  • topaz全家桶中文_apache 开源项目全家桶 2020年12月中文介绍

    apache项目全家桶 很多apache开源项目特别好 但是没什么能汇总的文档 我来整一个 不定期更新 big data 50 Project Apache Accumulo star 838 github https github com
  • shell脚本基础4——function函数、expect

    文章目录 一 function函数 1 1 函数的定义使用 1 2 函数参数 1 2 1 脚本内传参 1 2 2 脚本外传参 1 3 引用局部变量 1 3 1 区分局部变量 1 3 2 全局变量在函数外 1 3 3 全局变量在函数体 1 3
  • windows检测文件夹是否更新.bat脚本 windows循环检查文件夹

    最近在写windows脚本 记录一下一个很有用的信息 参考 https zhidao baidu com question 2208474390884363868 html 转载于 https www cnblogs com ChenCha
  • Python3 使用 matplotlib 画折线图

    ChartUtil py import matplotlib pyplot as plt from pylab import mpl def plotLine xData yData xLabel chartTitle mpl rcPara
  • matlab:基本操作与矩阵输入

    学习素材 MATLAB教程 台大郭彦甫 14课 原视频补档 MATLAB教程 台大郭彦甫 14课 原视频补档 哔哩哔哩 bilibili 部分素材使用视频截图 目录 一 基本运算 二 关键字 三 format 四 符号 1 2 colon
  • [ACTF 2020 新生赛] Exec

    Exec ping 127 0 0 1 ls ping 127 0 0 1 nl f
  • ABAP实现粘贴板的操作,复制粘贴_SAP刘梦_新浪博客

    ABAP可以实现复制粘贴的操作 自己玩儿 项目里暂时用不到 在ABAP中的 CLASS CL GUI FRONTEND SERVICES中提供了两个方法来控制与剪贴板内容的导入导出 分别是 CLIPBOARD EXPORT和CLIPBOAR
  • Git学习笔记【1】---本地操作

    声明 本教程参考自https www bilibili com video BV1Zz4y1C7vg p 17 一 Git的安装 官网下载即可 https git scm com 二 初始化本地仓库 1 创建一个文件夹 2 打开Git终端
  • Java常用System类

    java lang System类中提供了大量的静态方法 可以获取与系统相关的信息或系统级操作 在System类的API文档中 常用的方法有 public static long currentTimeMillis 返回以毫秒为单位的当前时
  • 移动互联网终端的touch事件,touchstart, touchend, touchmove

    前言 如果我们允许用户在页面上用类似桌面浏览器鼠标手势的方式来控制WEB APP 这个页面上肯定是有很多可点击区域的 如果用户触摸到了那些可点击区域怎么办呢 诸如智能手机和平板电脑一类的移动设备通常会有一个电容式触摸屏 capacitive
  • 微信小游戏关系链能不能获取到服务器,关系链互动数据

    关系链互动数据 在开放 关系链数据能力 的基础上 小游戏新增 互动型托管数据 提供关系链互动能力 用于实现小游戏内微信好友互动 点赞 送礼物等 的功能 关系链互动数据能力支持 好友间互赠 50 种游戏内道具 提供成功互动后的主域回调 满足互
  • maven项目引入外部文件(资源)

    1 maven项目如何引入外部文件 maven项目一般在main目录下分为java和resources 前者是源码 后者是资源 含外部文件 在maven的pom xml中指定resources所在目录后 当maven编译时 resource
  • python3+requests:接口自动化测试(二)

    前言 上篇文章python3 requests unittest 接口自动化测试 一 已经介绍了基于unittest框架的实现接口自动化 但是也存在一些问题 比如最明显的测试数据和业务没有区分开 接口用例不便于管理等 所以又对此修改完善 接
  • OPENCV角点检测和亚像素级检测

    首先进行粗检测 函数goodFeaturesToTrack 存储进入corners中 然后cornerSubPix函数进行亚像素精确匹配 设置结束条件 由于实际应用中线条较粗 因此 CORNER BLOCKSIZE 9 CORNER QUA
  • STM32 ---deley延时两行代码实现【为方便移植文件】

    一 前提简述 优点 无需定时器 仅两行代码 缺点 不够精准 应用理由 很多文件移植后 发现delay都需要外部文件支持 那 不如在文件内定义一个 方便各文件移植 应用要求 STM32F103系列 默认72MHz系统时钟 任何一个工程 复制粘
  • ERP仓库管理系统需求

    ERP仓库管理系统需求 目录 1 系统管理 2 2 供货管理 12 3 仓库管理 24 4 出货管理 27 一 系统管理 1 输入账号 密码进入系统 功能 可能出现以下情况 1 1账号或密码错误 或者员工已经辞职离开 1 2账号不存在 1
  • 信号和槽

    信号和槽用于对象间的通讯 信号 槽机制是Qt的一个中心特征并且也许是Qt与 其它工具包的最不相同的部分 在图形用户界面编程中 我们经常希望一个窗口部件的一个变化被通知给另一个 窗口部件 更一般地 我们希望任何一类的对象可以和其它对象进行通讯
  • 网页按钮点击动画

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