RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1203375
Accepted
Alexandr_TT
Alexandr_TT
Asked:2021-11-12 03:40:55 +0000 UTC2021-11-12 03:40:55 +0000 UTC 2021-11-12 03:40:55 +0000 UTC

球沿抛物线轨迹反弹

  • 772

主题开始的问题:如何动画网球弹跳

在这个问题中,反弹是垂直的

<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"
       width="200" height="200" viewBox="0 0 200 200" preserveAspectRatio="xMinYMin meet" style="border:1px solid" >  
 
<image xlink:href="https://isstatic.askoverflow.dev/hXyA5.png" x="82" width="25px" height="25px" >
   <animateTransform id="anT"
     attributeName="transform"
     type="translate"
     dur="3s"
     begin="svg1.click+0.5s;anT.end+1s"
     values="
        0,0;
        0,168;
        0,84;
        0,168;
        0,126;
        0,168;
        0,148;
        0,168;
        0,158;
        0,168;
        0,163;
        0,168;
        0,166;
        0,168;
        "
        keyTimes="0;0.066;0.13;0.198;0.264;0.33;0.396;0.462;0.528;0.594;0.66;0.726;0.792;1"
        repeatCount="1"
        fill="freeze"
        restart="whenNotActive" />
</image>
   <polyline points="5,193 194,193" stroke="silver" stroke-width="4" />
 </svg>  

这个问题涉及具有不同高度和长度偏移的反弹。

在此处输入图像描述

很明显可以在矢量编辑器中画出小球的轨迹,如图,然后沿着轨迹实现运动,如上例。

但是很难实现运动和速度的不均匀性。

javascript
  • 4 4 个回答
  • 10 Views

4 个回答

  • Voted
  1. Best Answer
    Stranger in the Q
    2021-11-12T21:02:19Z2021-11-12T21:02:19Z

    期待你的下一个问题,我也让它旋转:

    let t, h, max = 176;
    
    function start() {
      t = Date.now(); 
      h = max;
    };
    
    addEventListener('click', start);
    start();
    
    requestAnimationFrame(function a(){
      const dt = Date.now() - t;
      h *= 0.97;
      const wave = Math.cos(dt/(200 - dt/25));
      ballGroup.setAttribute('transform', `translate(${dt/(10+dt/150)}, ${max - Math.abs(wave)*h})`);
      ball.setAttribute('transform', `rotate(${3*dt/(10+dt/150)})`);
      requestAnimationFrame(a)
    })
    <svg width="200" height="200"viewBox="0 0 200 200" style="border:1px solid" >  
      <g id="ballGroup">
        <image id="ball" xlink:href="https://isstatic.askoverflow.dev/hXyA5.png" x=-12.5 y=-12.5 width="25px" height="25px" />
      </g>
      <polyline points="5,190 190,190" stroke="silver" stroke-width="4" />
    </svg>

    • 15
  2. Barmaley
    2021-11-12T21:22:39Z2021-11-12T21:22:39Z

    我不擅长JavaScript,所以我会写一些伪代码。

    如您所知,球的回弹(又名抛物线)垂直由二次方程描述,水平由一个均匀方程描述,即:

    y = vY*t - G*t^2/2
    x = vX*t
    

    vY- 初始垂直速度,vX- 初始水平速度,t- 时间,G- 重力加速度,对于地球来说是9.81 м/c^2(月球低 6 倍 - 1.62 m/s^2)。

    此外,在到达地面时(y=0),球再次反弹,并且每次跳跃都会分别损失一定比例的速度/能量,公式如下

    y = N*k*vY*t - G*t^2/2
    x = N*k*vX*t
    

    哪里k是反弹因子(大约〜90%),N是反弹的数量。

    仍然需要将其编程到您的动画中,这显然不会成为问题。

    PS 这绝对比抛物线仿真更好cos()——顺便说一下,在计算速度方面更快,而且在物理上更合理

    • 7
  3. Alexandr_TT
    2021-11-12T22:40:57Z2021-11-12T22:40:57Z

    解决方案 svg 微笑

    球的轨迹是根据矢量编辑器 Inkscape 中问题中的图片创建的

    沿着我使用的轨迹动画运动 - animateMotion

    .container {
    width:60%;
    height:60%;
    }
    <div class="container">
    <svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" 
        xmlns:xlink="http://www.w3.org/1999/xlink"
           viewBox="0 0 488 232" preserveAspectRatio="xMinYMin meet" style="border:1px solid" >  
    <defs>
     <path id="trace" d="m 25.652812,16.016049 v 181.392771 0 0 l -0.596577,25.31062 c 0,0 12.411076,-62.72171 21.476772,-93.33069 5.109455,-17.25132 11.107049,-34.303277 18.493888,-50.709043 6.68532,-14.84773 11.981393,-31.214941 23.266504,-42.953546 5.128983,-5.335092 11.703068,-10.892125 19.090461,-11.334963 9.33174,-0.559391 18.66956,5.119788 25.65281,11.334963 12.5853,11.201058 18.46109,28.314233 25.65282,43.550123 7.68011,16.270538 13.21524,33.508736 18.49388,50.709046 9.35008,30.46698 17.6561,61.30229 23.26651,92.73411 0,0 7.63247,-46.2686 13.72127,-68.87103 4.15486,-15.42339 7.4192,-31.5679 15.511,-45.33985 5.42122,-9.226722 10.78091,-23.515729 21.47677,-23.863083 11.38465,-0.369722 18.27651,14.296709 24.45966,23.863083 8.5031,13.15573 11.7205,29.10909 16.10758,44.1467 6.69922,22.96293 9.48984,49.49348 15.511,70.06418 5.7106,-34.92901 6.57028,-45.00528 16.10758,-65.29157 5.26265,-11.19392 9.73289,-28.98491 22.07335,-29.82885 11.92521,-0.81554 20.99188,14.41196 25.05624,25.65281 4.04949,11.19974 6.57393,20.61892 9.54523,31.02201 3.6399,12.74398 5.25389,18.16556 10.14181,38.4456 2.98041,-18.27579 1.7071,-16.73913 4.17604,-24.72433 1.6821,-5.44034 3.72502,-10.96841 7.15892,-15.511 3.31674,-4.3876 7.05439,-11.27709 12.52812,-10.73839 7.04712,0.69355 9.92525,10.387 13.12469,16.70416 5.35774,10.57863 5.4736,18.42066 9.54524,34.26956 0.57788,-7.32318 1.59738,-10.47263 1.78973,-13.98594 0.5125,-9.36095 6.36879,-18.32474 10.84695,-17.16023 9.45261,2.45807 13.01612,16.09152 13.01612,16.09152" style="fill:none;stroke-opacity:0.9;stroke-width:2;stroke:#e8204f"/>
    </defs>
     
    <image xlink:href="https://isstatic.askoverflow.dev/hXyA5.png" x="0" y="0" width="25px" height="25px" >
       <animateMotion id="anT"
         
         dur="1.5s"
         begin="svg1.click+0.5s;anT.end+1s"
            repeatCount="1"
            fill="freeze"
            restart="whenNotActive" > 
            <mpath xlink:href="#trace" />
        </animateMotion>    
    </image>
       </svg>
     </div>

    • 5
  4. Alexandr_TT
    2021-11-15T17:48:26Z2021-11-15T17:48:26Z

    CSS 解决方案

    CSS 动画可以更好地接近这一点。你需要:

    1. 为同步功能找到合适的贝塞尔曲线https://cubic-bezier.com/#.17,.76,.58,1
    2. 将持续时间因子更新为所需
    3. 通过添加更多动画来添加任意数量的步骤

    然后你需要根据时长正确计算延迟(前一个动画延迟 + 2 * 前一个动画时长)。

    主要技巧是使用隔行扫描并运行每个动画两次会给你一个镜像效果和一个完美的抛物线曲线(其中一半由贝塞尔曲线定义)。

    .box {
      width: 200px;
      height: 190px;
      border: 1px solid;
      display: flex;
      justify-content: center;
      align-items: flex-end;
    }
    
    img {
       --d:0.8s; /*duration factor*/
    
       width:30px;
       animation-timing-function:cubic-bezier(.17,.76,.58,1); /* control this: https://cubic-bezier.com/#.17,.76,.58,1*/
       animation-iteration-count:2; /* don't change*/
       animation-direction: alternate; /* don't change */
       animation-name:t1,t2,t3,t4,t5; /* don't change unless you need more steps*/
    
       animation-duration:
         var(--d),
         calc(var(--d)/2),
         calc(var(--d)/3),
         calc(var(--d)/4),
         calc(var(--d)/5);
       animation-delay: 
         calc(var(--d)*-1), 
         calc(var(--d)), 
         calc(var(--d)   + 2*var(--d)/2), 
         calc(var(--d)*2 + 2*var(--d)/3), 
         calc(var(--d)*2 + 2*var(--d)/3 + 2*var(--d)/4); 
    }
    
    @keyframes t1{to {transform:translateY(-160px)}}
    @keyframes t2{to {transform:translateY(-110px)}}
    @keyframes t3{to {transform:translateY(-60px)}}
    @keyframes t4{to {transform:translateY(-30px)}}
    @keyframes t5{to {transform:translateY(-10px)}}
    <div class="box">
      <img src="https://isstatic.askoverflow.dev/hXyA5.png">
    <div>

    添加水平移动:

    .box {
       --d:0.8s; /*duration factor*/
       
      width: 200px;
      height: 190px;
      border: 1px solid;
      display: flex;
      align-items: flex-end;
      overflow:hidden;
    }
    
    img {
       width:30px;
       animation-timing-function:cubic-bezier(.17,.76,.58,1); /* control this: https://cubic-bezier.com/#.17,.76,.58,1*/
       animation-iteration-count:2; /* don't change*/
       animation-direction: alternate; /* don't change */
       animation-name:t1,t2,t3,t4,t5; /* don't change unless you need more steps*/
    
       animation-duration:
         var(--d),
         calc(var(--d)/2),
         calc(var(--d)/3),
         calc(var(--d)/4),
         calc(var(--d)/5);
       animation-delay: 
         calc(var(--d)*-1), 
         calc(var(--d)), 
         calc(var(--d)   + 2*var(--d)/2), 
         calc(var(--d)*2 + 2*var(--d)/3), 
         calc(var(--d)*2 + 2*var(--d)/3 + 2*var(--d)/4); 
    }
    
    @keyframes t1{to {transform:translateY(-160px)}}
    @keyframes t2{to {transform:translateY(-110px)}}
    @keyframes t3{to {transform:translateY(-60px)}}
    @keyframes t4{to {transform:translateY(-30px)}}
    @keyframes t5{to {transform:translateY(-10px)}}
    
    .box > span {
      animation:m calc(var(--d)*2 + 2*var(--d)/3 + 2*var(--d)/4 + 2*var(--d)/5) linear forwards;
    }
    
    @keyframes m{to {transform:translateX(150px)}}
    <div class="box">
      <span><img src="https://isstatic.askoverflow.dev/hXyA5.png"></span>
    <div>

    来自成员 @Temani Afif的答案的松散翻译 。

    • 2

相关问题

  • 第二个 Instagram 按钮的 CSS 属性

  • 由于模糊,内容不可见

  • 弹出队列。消息显示不正确

  • 是否可以在 for 循环中插入提示?

  • 如何将 JSON 请求中的信息输出到数据表 Vuetify vue.js?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何从列表中打印最大元素(str 类型)的长度?

    • 2 个回答
  • Marko Smith

    如何在 PyQT5 中清除 QFrame 的内容

    • 1 个回答
  • Marko Smith

    如何将具有特定字符的字符串拆分为两个不同的列表?

    • 2 个回答
  • Marko Smith

    导航栏活动元素

    • 1 个回答
  • Marko Smith

    是否可以将文本放入数组中?[关闭]

    • 1 个回答
  • Marko Smith

    如何一次用多个分隔符拆分字符串?

    • 1 个回答
  • Marko Smith

    如何通过 ClassPath 创建 InputStream?

    • 2 个回答
  • Marko Smith

    在一个查询中连接多个表

    • 1 个回答
  • Marko Smith

    对列表列表中的所有值求和

    • 3 个回答
  • Marko Smith

    如何对齐 string.Format 中的列?

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5