RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1330825
Accepted
Alexandr_TT
Alexandr_TT
Asked:2022-09-22 06:31:30 +0000 UTC2022-09-22 06:31:30 +0000 UTC 2022-09-22 06:31:30 +0000 UTC

曲柄机构动画

  • 772

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
  <svg version="1.1"
    baseProfile="full"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    xmlns:ev="http://www.w3.org/2001/xml-events"
    width="1100"
    height="600">

  <title>  Slider-Crank </title>

  <defs>
    <rect
                id="Slidebar"
      stroke-width="1"
            stroke="black"
              fill="silver"
      fill-opacity="1"
                 x="0"
                 y="-12"
             width="300"
            height="24"
    />
    <g id="Crosshead" stroke-width="1" stroke="black" fill-opacity="1">
      <rect
           fill="gold"
              x="-50"
              y="-25"
          width="100"
         height="50"
      />
      <circle cx="0" cy="0" r="15" fill="white"/>
    </g>
    <g id="Crank" stroke-width="1" stroke="black" fill-opacity="1">
      <path fill="silver"
             d="M -99.959 40.000
                A  40  40 0 0 1 -99.959, -40.000
                A 450 450 0 0 0  -9.950, -49.000
                A  50  50 0 1 1  -9.950,  49.000
                A 450 450 0 0 0 -99.959,  40.000
                z"/>
      <circle cx="-100" cy="0" r="25" fill="white"/>
      <circle cx="0"    cy="0" r="30" fill="lightgrey"/>
    </g>
    <g id="ConRod" stroke-width="1" stroke="black" fill-opacity="0.7">
      <path fill="silver"
             d="M  12.387  21.715
                A 30 30 0 0 1  27.551  17.776
                L 453.475  22.035
                A 30 30 0 0 1 473.243  29.733
                A 40 40 0 0 1 473.243 -29.733
                A 30 30 0 0 1 453.475 -22.035
                L  27.551 -17.776
                A 30 30 0 0 1 12.387  -21.715
                A 25 25 0 0 1 12.387   21.715
                z"/>
      <circle cx="0"   cy="0" r="25" fill="silver"/>
      <circle cx="0"   cy="0" r="15" fill="white"/>
      <circle cx="500" cy="0" r="40" fill="silver"/>
      <circle cx="500" cy="0" r="25" fill="white"/>
    </g>

  </defs>

  <use xlink:href="#Slidebar"  x="150" y="263"/>
  <use xlink:href="#Slidebar"  x="150" y="337"/>
  <use xlink:href="#Crosshead" x="200" y="300">
    <animate
      attributeName="x"
            dur="3s"
            values="  200.000;
                      207.202;
                      227.545;
                      257.557;
                      292.430;
                      327.159;
                      357.557;
                      380.753;
                      395.140;
                      400.000;
                      395.140;
                      380.753;
                      357.557;
                      327.159;
                      292.430;
                      257.557;
                      227.545;
                      207.202;
                      200.000"
        repeatCount="indefinite"/>
  </use>

  <use xlink:href="#Crank" x="800" y="300">
    <animateTransform
      attributeName="transform" type="rotate" from="0,800,300"
         by="360" dur="3s" repeatCount="indefinite"/>
  </use>
  <use xlink:href="#ConRod" x="200" y="300">
    <animate
      attributeName="x"
            dur="3s"
            values="  200.000;
                      207.202;
                      227.545;
                      257.557;
                      292.430;
                      327.159;
                      357.557;
                      380.753;
                      395.140;
                      400.000;
                      395.140;
                      380.753;
                      357.557;
                      327.159;
                      292.430;
                      257.557;
                      227.545;
                      207.202;
                      200.000"

        repeatCount="indefinite"/>
    <animateTransform
      attributeName="transform" type="rotate" from="0,200,300"
         repeatCount="indefinite" dur="3s"
         values="  0.000, 200.000, 300;
                  -3.922, 207.202, 300;
                  -7.386, 227.545, 300;
                  -9.974, 257.557, 300;
                 -11.359, 292.430, 300;
                 -11.359, 327.159, 300;
                  -9.974, 357.557, 300;
                  -7.386, 380.753, 300;
                  -3.922, 395.140, 300;
                   0.000, 400.000, 300;
                   3.922, 395.140, 300;
                   7.386, 380.753, 300;
                   9.974, 357.557, 300;
                  11.359, 327.159, 300;
                  11.359, 292.430, 300;
                   9.974, 257.557, 300;
                   7.386, 227.545, 300;
                   3.922, 207.202, 300;
                   0.000, 200.000, 300"/>
  </use>

</svg>

我正在尝试使用 svg 和 javascript 重现曲柄机构的运动动画。

滑块需要移动动画,曲柄需要旋转动画,但如何获得曲柄动画?animatesvg 有和的值animateTransform,但是有没有一个方程可以让我们重现这个?

译者注:

也就是说,我们需要一个通用的解决方案,允许使用不同的输入数据:曲柄、连杆的尺寸和滑块的行程长度,来实现整个曲柄机构的动画。

@sonia maklouf用 svg问题对曲柄运动进行松散的翻译。

javascript
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    Leonid
    2022-09-23T02:55:29Z2022-09-23T02:55:29Z

    如果没有详细的图纸,那么它是可能的。我们改变曲柄膝部的旋转角度(蓝线),从而获得与连杆(绿色)的连接点。根据连杆的长度,我们找到与滑块(绿色圆圈)的连接点,滑块沿恒定路径(黄色线)移动。

    const canvas = document.querySelector('canvas');
    const ctx = canvas.getContext('2d');
    
    const w = canvas.width = 600;
    const h = canvas.height = 180;
    
    {
        const center = [w*2/3,h/2];
        const joint_radius = 10;
        const crank_len = 80;
        const rotation_speed = Math.PI/180;
        const conrod_len = 200;
        
        let angle = 0;
        ctx.lineWidth = 5;
        
        draw();
    
        function draw(){
            ctx.clearRect(0,0,w,h);
            
            ctx.strokeStyle = 'yellow';
            ctx.stroke(new Path2D(`M ${center[0]+crank_len-conrod_len} ${center[1]} h ${-crank_len*2}`));
            
            ctx.fillStyle = 'red';
            ctx.beginPath();
            ctx.arc(...center,joint_radius,0,2*Math.PI);
            ctx.fill();
            
            let crank_x = center[0] + Math.cos(angle)*crank_len;
            let crank_y = center[1] + Math.sin(angle)*crank_len;
            
            ctx.fillStyle = 'blue';
            ctx.beginPath();
            ctx.arc(crank_x,crank_y,joint_radius,0,2*Math.PI);
            ctx.fill();
            
            ctx.strokeStyle = 'blue';
            ctx.stroke(new Path2D(`M ${center[0]} ${center[1]} L ${crank_x} ${crank_y}`));
            
            let crosshead_x = crank_x - Math.sqrt(conrod_len**2 - (crank_y-center[1])**2);
            let crosshead_y = center[1];
            
            ctx.fillStyle = 'green';
            ctx.beginPath();
            ctx.arc(crosshead_x,crosshead_y,joint_radius,0,2*Math.PI);
            ctx.fill();
            
            ctx.strokeStyle = 'green';
            ctx.stroke(new Path2D(`M ${crank_x} ${crank_y} L ${crosshead_x} ${crosshead_y}`));
                      
            angle = angle%(2*Math.PI) + rotation_speed;
            
            requestAnimationFrame(draw);        
        }
    }
    <canvas></canvas>

    UPD您可以以相同的方式操作 SVG 中的属性。某些设置可以在合理的范围内更改(标有注释)。

    {
        const svg = document.querySelector('svg');
        const crank = svg.querySelector('#crank');
        const crosshead = svg.querySelector('#crosshead');
        const conrod = svg.querySelector('#conrod');
        const bar_rect = svg.querySelector('#slidebar');
        
        const bar1 = svg.querySelector('#bar1');
        const bar2 = svg.querySelector('#bar2');
        
        // Эти параметры можно изменять (в разумных пределах)
        const center = [800,150];
        const crank_len = 100;
        const conrod_len = 500;
        const crosshead_len = 100;
        const rotation_speed = 1;
        // Дальше ничего менять не надо))
        
        
        bar_rect.setAttribute('width', crank_len*2 + crosshead_len);
        bar1.setAttribute('y', center[1] - 37.5);
        bar1.setAttribute('x', center[0] - crank_len - conrod_len - crosshead_len/2);
        bar2.setAttribute('y', center[1] + 37.5);
        bar2.setAttribute('x', center[0] - crank_len - conrod_len - crosshead_len/2);
        
        crosshead.querySelector('rect').setAttribute('x', -crosshead_len/2);
        crosshead.querySelector('rect').setAttribute('width', crosshead_len);
        
        let angle = 0;
        
        draw();
    
        function draw(){     
            crank.setAttribute('transform', `translate(${center[0]},${center[1]}) rotate(${angle+180}, 0, 0) scale(${crank_len/100})`);
            
            let crank_x = center[0] + Math.cos(angle*(Math.PI/180))*crank_len;
            let crank_y = center[1] + Math.sin(angle*(Math.PI/180))*crank_len;
            
            let crosshead_x = crank_x - Math.sqrt(conrod_len**2 - (crank_y-center[1])**2);
            let crosshead_y = center[1];
            
            crosshead.setAttribute('transform', `translate(${crosshead_x},${crosshead_y})`);
            
            let conrod_angle = Math.acos((crank_x-crosshead_x)/conrod_len)*(180/Math.PI);
            
            conrod_angle = (crank_y > center[1])? conrod_angle : -conrod_angle;
            
            conrod.setAttribute('transform', `translate(${crosshead_x},${crosshead_y}) rotate(${conrod_angle},0,0) scale(${conrod_len/500})`);
    
                    
            angle = angle%(360) + rotation_speed;
            
            requestAnimationFrame(draw);        
        }
    
    }
    <svg viewBox="0 0 1100 600">
        <defs>
            <rect
                id="slidebar"
                stroke-width="1"
                stroke="black"
                fill="silver"
                fill-opacity="1"
                x="0"
                y="-12"
                width="300"
                height="24"
            />
    
        </defs>
    
        <use id="bar1" xlink:href="#slidebar"/>
        <use id="bar2" xlink:href="#slidebar"/>
    
        <g id="crosshead" stroke-width="1" stroke="black" fill-opacity="1">
            <rect
                fill="gold"
                x="-50"
                y="-25"
                width="100"
                height="50"
            />
            <circle cx="0" cy="0" r="15" fill="white"/>
        </g>
    
        <g id="crank" stroke-width="1" stroke="black" fill-opacity="1">
            <path fill="silver"
                d="M -99.959 40.000
                    A  40  40 0 0 1 -99.959, -40.000
                    A 450 450 0 0 0  -9.950, -49.000
                    A  50  50 0 1 1  -9.950,  49.000
                    A 450 450 0 0 0 -99.959,  40.000
                    z"/>
            <circle cx="-100" cy="0" r="25" fill="white"/>
            <circle cx="0"    cy="0" r="30" fill="lightgrey"/>
        </g>
        <g id="conrod" stroke-width="1" stroke="black" fill-opacity="0.7">
            <path fill="silver"
                    d="M  12.387  21.715
                        A 30 30 0 0 1  27.551  17.776
                        L 453.475  22.035
                        A 30 30 0 0 1 473.243  29.733
                        A 40 40 0 0 1 473.243 -29.733
                        A 30 30 0 0 1 453.475 -22.035
                        L  27.551 -17.776
                        A 30 30 0 0 1 12.387  -21.715
                        A 25 25 0 0 1 12.387   21.715
                        z"/>
            <circle cx="0"   cy="0" r="25" fill="silver"/>
            <circle cx="0"   cy="0" r="15" fill="white"/>
            <circle cx="500" cy="0" r="40" fill="silver"/>
            <circle cx="500" cy="0" r="25" fill="white"/>
        </g>
    </svg>

    • 8
  2. barsik34566
    2022-09-23T00:14:39Z2022-09-23T00:14:39Z

    在此处输入图像描述

    B坐标可以通过三角函数得到圆的参数方程

    x= cos(ang_rad)*半径

    y=sin(ang_rad)*半径

    坐标 C 可以用谷歌搜索“圆线交点”,即半径为 BC 的圆与线 CA 的交点。交叉点将是 2 选择较小的 X 所在的位置。

    • 5

相关问题

  • 第二个 Instagram 按钮的 CSS 属性

  • 由于模糊,内容不可见

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

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

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

Sidebar

Stats

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

    表格填充不起作用

    • 2 个回答
  • Marko Smith

    提示 50/50,有两个,其中一个是正确的

    • 1 个回答
  • Marko Smith

    在 PyQt5 中停止进程

    • 1 个回答
  • Marko Smith

    我的脚本不工作

    • 1 个回答
  • Marko Smith

    在文本文件中写入和读取列表

    • 2 个回答
  • Marko Smith

    如何像屏幕截图中那样并排排列这些块?

    • 1 个回答
  • Marko Smith

    确定文本文件中每一行的字符数

    • 2 个回答
  • Marko Smith

    将接口对象传递给 JAVA 构造函数

    • 1 个回答
  • Marko Smith

    正确更新数据库中的数据

    • 1 个回答
  • Marko Smith

    Python解析不是css

    • 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