深入解析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>
原文地址:https://www.cnblogs.com/tengx/p/12409863.html