zoukankan      html  css  js  c++  java
  • css3加js做一个简单的3D行星运转效果

    前几天在园子里看到一篇关于CSS3D行星运转的文章,原文在这里,感觉这个效果也太酷炫了,于是自己也就心血来潮的来尝试的做了一下。因为懒得去用什么插件了,于是就原生的JS写,效果有点粗超,还有一些地方处理的不是很好,如果有好的建议万望留言告知,不胜感谢。源代码已上传到github上,点这里获取。好了不说废话了,下面附上代码。

    HTML部分

    <div class="path-Saturn">
            <div id="Saturn" title="土星">
                <div class="x"></div>  
                <div class="y"></div>
                <div class="z"></div>
                <div class="space space-x"></div>
                <div class="space space-x1"></div>
                <div class="space space-x2"></div>
    
                <div class="space space-y"></div>
                <div class="space space-y1"></div>
                <div class="space space-y2"></div>
    
                <div class="space space-z"></div>
                <div class="space space-z1"></div>
                <div class="space space-z2"></div>
        
                <!-- 卫星 -->
                <div class="path-satellite">
                    <div id="satellite" title="卫星">
                        <div class="x"></div>
                        <div class="y"></div>
                        <div class="z"></div>
                        <div class="space space-x"></div>
                        <div class="space space-x1"></div>
                        <div class="space space-x2"></div>
    
                        <div class="space space-y"></div>
                        <div class="space space-y1"></div>
                        <div class="space space-y2"></div>
    
                        <div class="space space-z"></div>
                        <div class="space space-z1"></div>
                        <div class="space space-z2"></div>
                    </div>
                </div>
            </div>
        </div>

    这里用前三个类为x、y、z的div来画的每一个星球的x、y、z轴,然后这些星球之间是可以嵌套的,就是像上面的代码一样,里面的星球是外面星球的卫星。

    css部分

    .path-Saturn, .path-earth, .path-Venus, .path-Neptune, .path-Jupiter, .path-Mercury, .path-satellite, .path-moon{
        position: absolute;
        width: 95%;
        height: 95%;
        top: 2.5%;
        left: 2.5%;
        border: 1px solid #ddd;
        border-radius: 50%;
        transform: rotateX(60deg);
        transform-style: preserve-3d;
    }
    #sun, #earth, #Saturn, #Venus, #Neptune, #Jupiter, #Mercury, #satellite, #moon{
        width: 160px;
        height: 160px;
        position: absolute;
        transform-style: preserve-3d;
        top: 50%;
        left: 50%;
        margin: -80px 0 0 -80px;
        animation: rotateForward 10s linear infinite;
        cursor: pointer;
        transform: translateZ(-80px);
    }
    /*x, y, z轴*/
    .x, .y, .z{  
        position: absolute;
        height: 100%;
        border: 1px solid #999;
        left: 50%;
        margin-left: -1px;
    }
    .y{
        transform: rotateZ(90deg);
    }
    .z{
        transform: rotateX(90deg);
    }
    @keyframes  rotateForward {
        0%{
            transform: rotate3d(1, 1, 1, 0deg);
        }
        100%{
            transform: rotate3d(1, 1, 1, -360deg);
        }
    }
    /*Saturn*/
    #Saturn{
        width: 80px;
        height: 80px;
        left: 0%;
        margin: -40px 0 0 -40px;
        animation: rotateForward 4s linear infinite;
        transform: translateZ(-40px);
    }
    #Saturn .space{
        width: 80px;
        height: 80px;
        box-shadow: 0 0 60px rgba(90, 80, 53, 1);
        background-color: rgba(90, 80, 53, .3);
    }
    #Saturn .space-x1, #Saturn .space-x2, #Saturn .space-y1, #Saturn .space-y2, #Saturn .space-z1, #Saturn .space-z2{
        width: 87.5%;
        height: 87.5%;
        top: 6.25%;
        left: 6.25%;
        transform: rotate3d(0, 0, 0, 0deg) translateZ(20px);
    }
    #Saturn .space-x1{
        transform: rotate3d(0, 0, 0, 0deg) translateZ(-20px);
    }
    #Saturn .space-y{
        transform: rotate3d(0, 1, 0, 90deg) translateZ(0px);
    }
    #Saturn .space-y1{
        transform: rotate3d(0, 1, 0, 90deg) translateZ(-20px);
    }
    #Saturn .space-y2{
        transform: rotate3d(0, 1, 0, 90deg) translateZ(20px);
    }
    #Saturn .space-z{
        transform: rotate3d(1, 0, 0, 90deg) translateZ(0px);
    }
    #Saturn .space-z1{
        transform: rotate3d(1, 0, 0, 90deg) translateZ(-20px);
    }
    #Saturn .space-z2{
        transform: rotate3d(1, 0, 0, 90deg) translateZ(20px);
    }
    CSS部分

    主要就是用九个面通过各种旋转、平移来拼凑出一个球体。然后因为这里没有写兼容方面的代码,所以有兴趣down下来源代码的朋友,尽量用chrome浏览器打开。这里有几个CSS3属性需要说一下:

          1、transform-style: preserve-3d;   用来让设置了该属性的容器的子元素以3D效果展示。

          2、transform-origin: 设置旋转元素的旋转、平移的基点位置。

          3、perspective:  设置元素被查看位置的视图。 

    JS部分

    (function(planetObj, TimeArr, judgeDirec) {
        //检测参数是否规范
        var timeRegexp = /^[1-9][0-9]*$/,
            direcRegexp = /^[01]$/;
        function checkArgs (arg, ele, regexp) {
            if(arg){
                $(arg).each(function (i, item) {
                    if(arg.length != planetObj.length || !regexp.test(item)){
                        throw Error('an error occured');
                        return;
                    }else{
                        return arg;
                    }
                })
            }else{
                arg = [];
                for(var i = 0; i < planetObj.length; i++){
                    arg.push(ele);
                }
            }
            return arg;
        }
        TimeArr = checkArgs(TimeArr, 50, timeRegexp);
        judgeDirec = checkArgs(judgeDirec, 1, direcRegexp);
    
        var PathArr = [];
        $(planetObj).each(function (i, item) {
            var n = 0;  //定义一个标识,来判断当前是怎么运动的
            PathArr.push({
                a : $(item).parent().width() / 2,
                b : $(item).parent().height() / 2
            });
    
            //变化x坐标,然后根据椭圆轨迹,获得y坐标,以达到运动的效果
            function getEllopsePath (x, PathObj) {
                x = x - PathObj.a;
                var m;
    
                n ? (judgeDirec[i] ? m = 1 : m = -1) : (judgeDirec[i] ? m = -1 : m = 1); //判断开根号求得的y值是否为负数,从而确定旋转方向
                // if(judgeDirec[i]){
                //     n ? (m = judgeDirec[i]) : (m = judgeDirec[i]-2);  
                // }else{
                //     n ? (m = judgeDirec[i] - 1) : (m = judgeDirec[i] + 1);
                // }
                return Math.sqrt((1 - x * x / (PathObj.a * PathObj.a)) * PathObj.b * PathObj.b) * m + PathObj.b; 
            }
    
            function moving () {
                var x = parseInt($(item).css('left'), 10);
                if(x == 2 * PathArr[i].a){  //到达轨迹的右零界点的时候x减小
                    n--;
                }else if (x == 0) {   //到达轨迹的左临界点的时候,x增加
                    n++;
                }
                n ? x++ : x--;
                $(item).css({
                    'top' : getEllopsePath(x, PathArr[i]) + 'px',
                    'left' : x + 'px'
                });
            }
    
            setInterval(moving, TimeArr[i]);
        });
    })(['#Saturn', '#earth', '#Venus', '#Neptune', '#Mercury', '#Jupiter', '#satellite', '#moon'], [40, 180, 240, 20, 120, 200, 30, 10]/*option默认为50毫秒*/, [1, 0, 0, 0, 1, 0, 1, 1]/*option 判断运动方向,0为顺时针,1为逆时针,默认为逆时针*/);

    这里在实现星球运动的时候,有一些地方处理的不是很好,因为我是按照每隔一定的时间,让星球的left的位置变化,然后根据椭圆的公式,求出top的值。因为椭圆是不均匀的,所以这会使得星球的运动看起来时快时慢,因为他的top值,变化是不均匀的。

    然后这里还有个地方需要注意下,就是Math.sqrt()这个方法开出来的值全是正数,而我们要让星球环绕一周,就需要在轨迹的左右两端动态的改变Math.sqrt()这个方法开出来的值的正负数。

    下面附上一张效果图

    好了,今天就先写到这里了,作者敲键盘码字也不容易,如果你觉得你对本文还能提得上来那么一点点兴趣的话,请稍微移动下你的右手,帮点下赞,谢谢^_^。

  • 相关阅读:
    多测师讲解python _练习题002_高级讲师肖sir
    多测师讲解python _练习题002_高级讲师肖sir
    多测师讲解python _类(原始版)_高级讲师肖sir
    多测师讲解python _练习题003_高级讲师肖sir
    多测师讲解python _re模块_高级讲师肖sir
    多测师讲解python_os模块_高级讲师肖sir
    多测师讲解python _string_高级讲师肖sir
    MySQL介绍
    linux平台mysql密码设破解
    linux平台mysql密码设置
  • 原文地址:https://www.cnblogs.com/ww-ervin-72/p/5510402.html
Copyright © 2011-2022 走看看