• 深入解析CSS3圆周运动


    设想下图白色部分为显示器,我们要元素根据不同的角度围绕绿色圆形,做环形运动。

    那么我们首先要计算出在不同角度时,元素所在位置的XY坐标。

    已知信息圆心A,B,半径R,角度deg

    那么我们可以根据以上信息得出两个公式

    sin(deg) = (X - A) / R

    cos(deg) =  (B - Y) / R

    根据上述公式我们可以计算出我们需要的X Y位置

    X = A + R  * sin(deg) 

    Y = B - R * cos(deg)

    我们利用三角函数简单的原理获得X Y,下面简单代码演示

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            div:nth-child(1) {
                 30px;
                height: 30px;
                border-radius: 50%;
                background-color: pink;
                position: absolute;
                left: 0;
                top: 0;
            }
            
            div:nth-child(2) {
                 600px;
                height: 600px;
                border: solid 10px blue;
                border-radius: 50%;
                position: absolute;
                top: 200px;
                left: 300px;
            }
        </style>
    </head>
    
    <body>
        <div></div>
        <div></div>
        <script>
            // 设定圆心位置
            var A = 600;
            var B = 500;
            // 设定半径长度
            var R = 300;
            // 定义X,Y,deg
            var X, Y, angle = 0;
    
    
            setInterval(function() {
                angle++;
                angle = angle % 360;
                gotoDeg(angle);
            }, 20)
    
            // 根据角度变换位置
            function gotoDeg(deg) {
                X = A + Math.sin(degToRadianChange(deg)) * R;
                Y = B - Math.cos(degToRadianChange(deg)) * R;
                document.querySelectorAll('div')[0].style.left = X + 'px';
                document.querySelectorAll('div')[0].style.top = Y + 'px';
            }
    
            // 角度转弧度
            function degToRadianChange(deg) {
                return Math.PI / 180 * deg
            }
        </script>
    </body>
    
    </html>

     下面是面向对象的方式将其封装

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            body {
                position: relative;
            }
            
            div:nth-child(1) {
                 30px;
                height: 30px;
                border-radius: 50%;
                background-color: pink;
                position: absolute;
                left: 0;
                top: 0;
            }
            
            div:nth-child(2) {
                 600px;
                height: 600px;
                border: solid 10px blue;
                border-radius: 50%;
                position: absolute;
                top: 200px;
                left: 300px;
            }
        </style>
    </head>
    
    <body>
        <div></div>
        <div></div>
        <script>
            // 旋转元素类
            function rotateDom(dataJson) {
                this.timer = null;
                this.dom = dataJson.dom;
                // 参考元素
                this.referenceDom = dataJson.referenceDom;
                // 方向
                this.direcition = dataJson.direcition || 1;
                // 总时长
                this.time = dataJson.time || 1000;
                // 帧间隔
                this.interval = dataJson.interval || 10;
                // 总帧数
                this.allFrame = this.time / this.interval;
                // 每帧旋转角度
                this.everyAngle = 360 / this.allFrame;
                // 位置数据
                this.A = fetchAllOffsetLeft(this.referenceDom) + this.referenceDom.clientWidth / 2
                this.B = fetchAllOffsetTop(this.referenceDom) + this.referenceDom.clientHeight / 2
                this.R = this.referenceDom.clientHeight / 2
    
                this.X = this.A + Math.sin(degToRadianChange(0)) * this.R;
                console.log(this.X)
                this.Y = this.B - Math.cos(degToRadianChange(0)) * this.R;
                // 渲染
                this.render();
                this.move();
            }
            rotateDom.prototype.render = function() {
                this.dom.style.top = this.Y + 'px';
                this.dom.style.left = this.X + 'px';
            }
            rotateDom.prototype.move = function() {
                var self = this;
                var angle = 0;
                this.timer = setInterval(function() {
                    angle += self.everyAngle * self.direcition;
                    angle %= 360;
                    self.X = self.A + Math.sin(degToRadianChange(angle)) * self.R;
                    self.Y = self.B - Math.cos(degToRadianChange(angle)) * self.R;
                    self.render();
                }, this.interval)
            };
    
    
    
    
            // 角度转弧度
            function degToRadianChange(deg) {
                return Math.PI / 180 * deg
            }
            // 获取净offsetTop,此处忽略border
            function fetchAllOffsetTop(dom) {
                var allTop = dom.offsetTop;
                while (dom = dom.offsetParent) {
                    allTop += dom.offsetTop;
                }
                return allTop;
            }
    
            // 获取净offsetLeft
            function fetchAllOffsetLeft(dom) {
                var allLeft = dom.offsetLeft;
                while (dom = dom.offsetParent) {
                    allLeft += dom.offsetLeft;
                }
                return allLeft;
            }
            new rotateDom({
                "dom": document.querySelectorAll('div')[0],
                "referenceDom": document.querySelectorAll('div')[1],
                "time": 2000,
                "interval": 5,
            })
        </script>
    </body>
    
    </html>
  • 相关阅读:
    React实现新闻网站--使用动态路由获取不同列表内容
    Bootstrap4 轮播+模态框+提示框+弹出框
    JDK 升级问题小结
    JDK8 指南(译)
    如何学习一门编程语言
    redis 系列5 数据结构之字典(上)
    sql server 临时表(上) Tempdb概述
    redis 系列4 数据结构之链表
    redis 系列3 数据结构之简单动态字符串 SDS
    redis 系列2 知识点概述
  • 原文地址:https://www.cnblogs.com/tengx/p/12409863.html
Copyright © 2020-2023  润新知