整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

使用css3的动画模拟太阳系行星公转!

使用css3的动画模拟太阳系行星公转!

天小编给大家介绍使用css3的animation画一个太阳系行星公转的动画,再加以改进,讨论如何画椭圆的运行轨迹。然后分析京东和人人网使用animation的实际案例,最后结合css3的clip-path做一些比较特别的动画。

太阳系最终的效果图如下:

css3的animation是通过关键帧的形式做出来的,首先设定一个动画的运行时间,然后在这个时间轴上的若干位置处插入关键帧,浏览器根据关键帧设定的内容做过渡动画。animation常结合transform属性进行制作。以一个简单的例子说明,以一个div,让其从左到右运动,如下图左所未(没有动画请刷新下页面)

先用css画出静态的图,然后再加动画的属性。

整个工程完整的代码见这个Demo(

地址:http://codepen.io/yincheng/pen/PPKxYV)。

html如下:

<div class='space'>
 <div class='wheel'>
 <span class='line'></span>
 </div></div>

在轮子wheel加一个动画的属性,

.wheel{
  animation: move 3s linear infinite;
}

这个的意思是动画的名字是move,时间轴是3s,速度是匀速,播放次数无限。然后move的关键帧keyframes如下:

@keyframes move{
 100%{
 transform: translateX(350px);
 }
 }

即播放到末尾的时候,向X轴右移350px。在0%的时候值0,100%的时候值为350px,时间为3s,还有一个速度曲线的属性,根据这些信息做过渡动画。如果指定速度为线性linear,则动画的过渡效果是匀速的,对于上面来说就是匀速右移。默认的速度曲线为ease,就是渐进和渐出,中间播放比较快。

然后再给轮子添加一个滚动的效果rotate,用运行的距离除以轮子的周长得出需要滚动多少圈,即375 / (25 * 3.1415926 * 2) * 360=859.4度,也就是在这个区间向右移动的同时加上自转的效果,所以给transform添加多一个rotate的属性。

transform: translateX(350px) rotate(859.4deg);

这样就可以了:

这就是css3的animation动画,结合transform的大小、旋转、位移、斜切,通过两三行代码,便可做出很多有趣的效果。

接下来讨论太阳系的制作,跟上面不同的地方是行星是围绕着太阳转的,而轮子是围绕着自己的圆心转的,也就是说他们转的基点不同。可以看出,transform的基点默认是本身的中心center,所以我们要改变行星的进行转换的中心点transform-origin。

完整的Demo(地址:http://codepen.io/yincheng/pen/LpjMzP)。太阳系的html结构如下:

 <div class="galaxy">
 <div class='sun'></div>
 <div class='mercury'></div>
 <div class='venus'></div>
 <div class='earth'></div>
 </div>

太阳位于div galaxy的中间,让其它行星位于太阳的右边排成一条线。设置galaxy的width和height都为1300px。sun图片的大小为100px*100px,所以sun的left值和top值都为(1300 - 100) / 2=600px,这样sun就位于中间位置。设置水星mercury的left值为700px,top为625px,这样水星就位于太阳偏右的位置。然后再设置transform-origin:

transform-origin: -50px 25px;

transform-origin的原点是作用的元素左上角位置,所以往左移(700 - 1300 / 2)=50px,往下移60 / 2=30px(60为水星高度),水星转换的基点就变成了太阳的中心,在此基础上进行旋转:

animation: rotation 2.4s linear infinite;
@keyframes rotation{
 to{
 transform: rotate(1turn);
 }}

注意这里改变了同义的属性,0%和100%分别换成from和to,360deg换成1turn。

其它的行星,也按照这种方法进行设置,计算稍微繁琐。公转的周期以地球10s为基准,其它按比例换算。这样就可以做出一个太阳系公转的图,原理很简单,效果却很好。

注意到行星运行的轨迹其实是椭圆形的,上面是用了正圆形。因此,下面讨论如何做一个椭圆的运行轨迹。

查看完整的Demo(地址:http://codepen.io/yincheng/pen/QjMzZr)。

效果图如下:

上面的椭圆在Y轴上被压扁了,可以考虑在Y轴上添加一个位移变换,原理如下图所示,首先将地球的初始位置放到椭圆和其短轴的交点处,然后transform-origin设置为半径为800px的圆心的位置,但运行时间为50%即到初始位置对面的时候,插入一个关键帧:做一个位移转换,向y轴负方向移动200px,这样就可以形成一个半椭圆的轨迹,到了100%的时候逐渐恢复为初始值0,跟前面的半椭圆相反,就可以完成一个完整的椭圆轨迹。

需要在earth的外面包一层div,用来设置translateY的效果,因为这个效果的时间曲线需要设置为ease-in-out渐进渐出的效果,让椭圆运行起来更加的顺畅。html的结构如下:

<div class='planet'>
 <div class='origin-circle'></div>
 <div class='sun'></div>
 <div class='track'></div>
 <div class='moveY'>
 <div class='earth'></div>
 </div>
</div>

给moveY添加一个translateY的动画,其它的一样。

.moveY{  animation: moveY 2s ease-in-out infinite alternate; /* */
}
@keyframes moveY{
  to{
    transform: translateY(-200px);
  }
}

注意这里将moveY的周期设置为旋转的一半,同时使用了一个transition-direction为alternate的属性,alternate意为交替,效果等同于

@keyframes moveY{
 0%,100%{
 transform: translateY(0px);
 }  50%{    transform: translateY(-200px);
  }}

细心的读者会发现,这里的运行轨迹并不是严格的椭圆,旋转是匀速的,但是在y轴上的投影即在y轴上的速度是一条曲线,这条曲线理论上可以用贝赛尔曲线模拟出来,animation的速度参数改用cubic-bezier去模拟,ease-in-out等同于cubic-bezier(0.4,0,0.6,1)。通过一些数学换算理论上是可以模拟的,这里不再深入讨论。今天就讲到这里了哦!

太阳、地球、月球应该是我们人人都比较了解的天体,它们的运动轨迹是我们研究星系乃至宇宙的重要信息之一。那么我们如何使用HTML + CSS来模拟这么一个效果呢?


运动轨迹。

简单的来说就是转圈。

// 定义轨迹
@keyframes rotate {
  from {
    transform: rotateZ(0);
  }
  to {
    transform: rotateZ(360deg);
  }
}

定义太阳

/* 定义一个太阳 */
.sum {
  position: relative;
  margin: 100px auto 0;
  width: 200px;
  height: 200px;
  border-radius: 50%;
  background: radial-gradient(
    circle at center,
    #ff9b9b 0%,
    rgba(235, 36, 64, 0) 70%
    );
}

定义地球

地球绕太阳一圈的时间是365.24天左右,这被称为一年。每年有一个额外的日子被称为闰年,这一年会有366天,目的是为了弥补地球绕太阳的公转周期与我们日历的定义周期之间的不匹配。

/* 定义地球位置及公转信息 */
.earth {
  position: absolute;

  /* 定义地球与太阳的相对位置以及轨道线 */
  width: 300px;
  height: 300px;
  margin-left:-50px;
  margin-top:-50px;
  border:1px solid #dddddd;
  border-radius:50%;

  /*动画: 设定公转时间以及轨迹 */
  animation: rotate 36.524s infinite linear;
}
/* 地球本体 */
.earth::before{
  content: ' ';
  position:absolute;
  background-color: blue;
  width: 30px;
  height: 30px;
  margin-left:70px;
  border-radius: 30px;
}

定义月球

月球绕地球一圈的时间大约是27.32天。这被称为一个月(也称为地月周期)。月亮的运动轨迹略呈椭圆形,因此月球与地球的距离会随时间而变化,这也导致月球的运动速度略有不同,有时会更快,有时会更慢,但平均值仍然是27.32天左右。

/* 定义月球位置及公转信息 */
.moon {
  position: absolute;

  /* 定义月球与地球的相对位置以及轨道线 */
  width: 60px;
  height: 60px;
  margin-left:55px;
  margin-top:-15px;
  border:1px solid #dddddd;
  border-radius:50%;

  /*动画: 设定公转时间以及轨迹 */
  animation: rotate 2.732s infinite linear;
}

/* 月球本体 */
.moon::before{
  content: ' ';
  position:absolute;
  background-color: blue;
  width: 10px;
  height: 10px;
  margin-left:7px;
  border-radius: 10px;
}

html结构 / 天体结构

<div class="sum">
  <div class="earth">
      <div class="moon"></div>
  </div>
</div>

最终效果

t组件推荐:

  • QtitanRibbon: 遵循Microsoft Ribbon UI Paradigm for Qt技术的Ribbon UI组件,致力于为Windows、Linux和Mac OS X提供功能完整的Ribbon组件。
  • QtitanChart:是一个C ++库,代表一组控件,这些控件使您可以快速地为应用程序提供漂亮而丰富的图表。并且支持所有主要的桌面

文末附下载

Qt 3D:行星 QML 示例

Qt官方最新版免费下载试用,历史版本下载,在线文档和帮助文件下载-慧都网

演示结合 Qt 3D 渲染和 Qt Quick 2 元素。

本文演示了如何实现将 Qt 3D 渲染与 Qt Quick 2D 元素结合使用的应用程序。该示例显示了太阳系的八颗行星与太阳。

行星纹理贴图由 James Hastings-Trew 版权所有 (c) http://planetpixelemporium.com/planets.html经许可使用。

行星在给定时间根据它们的轨道围绕太阳旋转。轮换从 2000 Jan 0.0 UT 开始。行星位置是根据此处找到的公式计算的:http : //www.stjarnhimlen.se/comp/ppcomp.html和http://www.davidcolarusso.com/astro/。

运行示例

要从Qt Creator运行示例,请打开welcome模式并从Examples选择示例。有关更多信息,请访问构建和运行示例。

Qt 快速二维实现

planets-qml/PlanetsMain.qml示例中的 Qt Quick Implementation使用Scene3D类型呈现 3D 内容。

Scene3D {
    anchors.fill: parent
    aspects: ["render", "logic", "input"]

    SolarSystem { id: solarsystem }
}

行星相关信息存储在一个ListModel. 行星的选择按钮和信息表是基于模型创建的。2D 元素、选择按钮和滑块在planets-qml/PlanetsMain.qml.

选择按钮会更改 的focusedPlanet属性mainview。随着属性的变化,行星信息会更新,并且相机会动画到新的位置。

onFocusedPlanetChanged: {
    if (focusedPlanet==100) {
        info.opacity=0
        updatePlanetInfo()
    } else {
        updatePlanetInfo()
        info.opacity=1
    }

    solarsystem.changePlanetFocus(oldPlanet, focusedPlanet)
    oldPlanet=focusedPlanet
}

相机位置和相机观察点根据 中动画的值更新planets-qml/SolarSystem.qml,由changePlanetFocus()函数触发。

QQ2.NumberAnimation {
    id: lookAtOffsetAnimation
    target: sceneRoot
    properties: "xLookAtOffset, yLookAtOffset, zLookAtOffset"
    to: 0
    easing.type: Easing.InOutQuint
    duration: 1250
}

QQ2.NumberAnimation {
    id: cameraOffsetAnimation
    target: sceneRoot
    properties: "xCameraOffset, yCameraOffset, zCameraOffset"
    to: 0
    easing.type: Easing.InOutQuint
    duration: 2500
}

滑块用于调整旋转速度、行星大小和观看距离。当滑块值发生变化时,planets-qml/SolarSystem.qml会调用一个 JavaScript 函数来调整给定的属性。例如,更改观看距离滑块的值会调用该changeCameraDistance()方法。

onValueChanged: solarsystem.changeCameraDistance(value)

Qt 3D 实现

实现的主要部分,包括行星的运动和旋转数学,在planets-qml/SolarSystem.qml.

首先,添加 a Camera、 aLight和 a Configuration,然后是Effects 代表行星Materials,最后是行星本身。例如,地球的构造如下:

Entity {
    id: earthEntity

    Planet {
        id: earth
        tilt: planetData[Planets.EARTH].tilt
    }

    PlanetMaterial {
        id: materialEarth
        effect: effectDSB
        ambientLight: ambientStrengthPlanet
        diffuseMap: "qrc:/images/solarsystemscope/earthmap2k.jpg"
        specularMap: "qrc:/images/solarsystemscope/earthspec2k.jpg"
        normalMap: "qrc:/images/solarsystemscope/earthnormal2k.jpg"
        shininess: shininessSpecularMap
    }

    property Transform transformEarth: Transform {
        matrix: {
            var m=Qt.matrix4x4()
            m.translate(Qt.vector3d(earth.x, earth.y, earth.z))
            m.rotate(earth.tilt, tiltAxis)
            m.rotate(earth.roll, rollAxis)
            m.scale(earth.r)
            return m
        }
    }

    components: [ earth, materialEarth, transformEarth ]
}


移动和旋转计算等所需的行星数据是planets-qml/planets.js通过loadPlanetData()在组件完成时调用的JavaScript 来构建的。其他初始化,例如将行星插入数组以便于处理,计算土星环和天王星环的环半径,以及设置默认比例、速度和相机偏移,也已完成:


QQ2.Component.onCompleted: {
    planetData=Planets.loadPlanetData()
    // Push in the correct order
    planets.push(sun)
    planets.push(mercury)
    planets.push(venus)
    planets.push(earth)
    planets.push(mars)
    planets.push(jupiter)
    planets.push(saturn)
    planets.push(uranus)
    planets.push(neptune)
    planets.push(moon)
    // TODO: Once support for creating meshes from arrays is implemented take these into use
    //saturnRing.makeRing()
    //uranusRing.makeRing()
    saturnRingOuterRadius=planetData[Planets.SATURN].radius + Planets.saturnOuterRadius
    saturnRingInnerRadius=planetData[Planets.SATURN].radius + 0.006630
    uranusRingOuterRadius=planetData[Planets.URANUS].radius + Planets.uranusOuterRadius
    uranusRingInnerRadius=planetData[Planets.URANUS].radius + 0.002
    ready=true
    changeScale(1200)
    changeSpeed(0.2)
    setLookAtOffset(Planets.SUN)
}


场景通过调用该animate()函数进行动画处理。这也是时间提前的地方,计算所有行星的新位置。行星positionPlanet()根据它们的轴向倾斜和它们的恒星自转周期在函数中旋转。最后,在updateCamera()函数中计算新的相机位置。

function animate(focusedPlanet) {
    if (!ready)
        return

    advanceTime(focusedPlanet)
    for (var i=0; i <=Planets.NUM_SELECTABLE_PLANETS; i++)
        positionPlanet(i)

    updateCamera(focusedPlanet)
}
  • QtitanDataGrid官方最新版免费下载,中文资源,在线文档,视频教程,技术支持,QtitanDataGrid正版购买-慧都网
  • QtitanRibbon官方最新版免费下载,中文资源,在线文档,视频教程,技术支持,QtitanRibbon正版购买-慧都网