js实现一个可调节参数的倒立摆动画效果代码
代码语言:html
所属分类:动画
代码描述:js实现一个可调节参数的倒立摆动画效果代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<style>
* {
margin: 0;
padding: 0;
font-family: 'Spartan', sans-serif;
user-select: none;
box-sizing: border-box;
touch-action: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
body {
display: grid;
}
#background {
display: grid;
background-color: AliceBlue;
width: 100vw;
height: 100vh;
overflow: hidden;
justify-self: center;
align-self: center;
justify-content: center;
align-content: center;
}
#container {
justify-self: center;
align-self: center;
width: 37rem;
height: min-content;
display: grid;
transform: scale(1);
}
#title {
grid-row: 1;
grid-column: 1;
justify-self: center;
font-size: 3.5rem;
white-space: nowrap;
color: #8CBCE5;
}
#buttons {
display: grid;
width: 100%;
justify-self: stretch;
grid-template-columns: auto auto auto;
grid-gap: 1rem;
white-space: nowrap;
}
button {
min-width: 6rem;
font-size: 1.2rem;
color: white;
background-color: #8CBCE5;
padding: 0.8rem;
border-radius: 0.7rem;
border: none;
cursor: pointer;
border: 0.25rem solid #8CBCE5;
}
button:hover {
border: 0.25rem solid #7ea9ce;
}
button:active {
background: #6387A7;
}
button:focus {
outline: none;
border: 0.25rem solid #6387A7;
}
#upper-sliders {
width: 100%;
display: grid;
grid-gap: 1rem;
grid-template-columns: 12rem auto 7rem;
align-items: center;
margin-bottom: 2rem;
}
#lower-sliders {
margin-top: 2rem;
width: 100%;
display: grid;
grid-gap: 1rem;
grid-template-columns: 1.8rem auto 7rem;
align-items: center;
}
#lower-sliders .left,
#upper-sliders .left {
grid-column: 1;
}
#lower-sliders .middle,
#upper-sliders .middle {
grid-column: 2;
min-width: 1rem;
}
#lower-sliders .right,
#upper-sliders .right {
grid-column: 3;
}
p {
font-size: 1.4rem;
font-weight: bold;
color: #8CBCE5;
text-align: justify;
line-height: 1.32;
}
input[type="number"] {
font-size: 1rem;
padding: 0.8rem 0.7rem 0.6rem 0.7rem;
border-radius: 0.5rem;
text-align: left;
background-color: #DDECFB;
border: 0.25rem solid #DDECFB;
color: #6387A7;
}
input[type="number"]:hover {
border: 0.25rem solid #C9DFF4;
}
input[type="number"]:focus {
outline: none;
border: 0.25rem solid #8AB1D6;
}
svg {
justify-self: center;
grid-column: 1;
grid-row: 1;
width: 30rem;
height: 23rem;
overflow: visible;
pointer-events: none;
}
svg * {
fill: #eee;
stroke-width: 1;
stroke: black;
}
.top-circle {
transform: translateX( 0px ) translateY( -65px );
}
#drag-target {
pointer-events: auto;
}
#bottom-text {
margin-top: 1.5rem;
justify-self: right;
font-size: 1.2rem;
}
a {
text-decoration: none;
opacity: 0.6;
}
input[type=range] {
-webkit-appearance: none; /* Hides the slider so that custom slider can be made */
width: 100%; /* Specific width is required for Firefox. */
background: transparent; /* Otherwise white in Chrome */
height: 1.5rem;
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
}
input[type=range]:focus {
outline: none; /* Removes the blue border. You should probably do some kind of focus styling for accessibility reasons though. */
}
input[type=range]::-ms-track {
width: 100%;
cursor: pointer;
/* Hides the slider so custom styles can be added */
background: transparent;
border-color: transparent;
color: transparent;
}
/* Special styling for WebKit/Blink */
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
height: 1.7rem;
width: 1.7rem;
border-radius: 0.5rem;
background-color: #8CBCE5;
cursor: pointer;
margin-top: -0.6rem; /* You need to specify a margin in Chrome, but in Firefox and IE it is automatic */
}
input[type=range]:hover::-webkit-slider-thumb {
border: 0.25rem solid rgba(0, 0, 0, 0.1);
}
input[type=range]:focus::-webkit-slider-thumb {
border: 0.25rem solid #6387A7;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 0.5rem;
cursor: pointer;
background-color: #DDECFB;
border-radius: 0.5rem;
}
/* All the same stuff for Firefox */
input[type=range]::-moz-range-thumb {
height: 1.2rem;
width: 1.2rem;
border-radius: 0.5rem;
background-color: #8CBCE5;
cursor: pointer;
border: 0.25rem solid #8CBCE5;
}
input[type=range]:hover::-moz-range-thumb {
border: 0.25rem solid rgba(0, 0, 0, 0.1);
}
input[type=range]:focus::-moz-range-thumb {
border: 0.25rem solid #6387A7;
}
input[type=range]::-moz-range-track {
width: 100%;
height: 0.5rem;
cursor: pointer;
background-color: #DDECFB;
border-radius: 0.5rem;
}
</style>
<link href="https://fonts.googleapis.com/css2?family=Spartan:wght@500&display=swap" rel="stylesheet">
</head>
<body >
<div id="background">
<div id="container">
<h1 id="title"> inverted pendulum </h1>
<div id="upper-sliders">
<p class="left"> gravitational acceleration </p>
<input id="g-slider" class="middle" type="range" min="-10" max="50" value="9.81" step="0.01"> </input>
<input id="g-input" type="number" class="right number" step="0.01" value="9.81"> </input>
<p class="left"> pendulum length </p>
<input id="pendulum-length-slider" class="middle" type="range" min="0.01" max="3" value="0.65" step="0.01"> </input>
<input id="pendulum-length-input" type="number" class="right number" step="0.01" value="0.65"> </input>
<p class="left"> pendulum mass </p>
<input id="pendulum-mass-slider" class="middle" type="range" min="0.01" max="100" value="1" step="0.01"> </input>
<input id="pendulum-mass-input" type="number" class="right number" step="0.01" value="1"> </input>
<p class="left"> slider mass </p>
<input id="slider-mass-slider" class="middle" type="range" min="0.01" max="100" value="1" step="0.01"> </input>
<input id="slider-mass-input" type="number" class="right number" step="0.01" value="1"> </input>
</div>
<div id="buttons">
<button id="reset"> reset </button>
<button id="toggle-controller"> turn on controller </button>
<button id="nudge"> nudge </button>
</div>
<div id="lower-sliders">
<p class="left"> P<sub>θ</sub> </p>
<input id="ptheta-slider" type="range" class="middle" min="-500" max="500" value="100" step="1"> </input>
<input id="ptheta-input" type="number" class="right number" step="1" value="100"> </input>
<p class="left"> D<sub>θ</sub> </p>
<input id="dtheta-slider" type="range" class="middle" min="-200" max="200" value="10" step="1"> </input>
<input id="dtheta-input" type="number" class="right number" step="1" value="10"> </input>
<p class="left"> P<sub>x</sub> </p>
<input id="px-slider" type="range" class="middle" min="-200" max="200" value="20" step="1"> </input>
<input id="px-input" type="number" class="right number" step="1" value="20"> </input>
<p class="left"> D<sub>x</sub> </p>
<input id="dx-slider" type="range" class="middle" min="-200" max="200" value="10" step="1"> </input>
<input id="dx-input" type="number" class="right number" step="1" value="10"> </input>
</div>
<p style="margin-top: 2rem; font-size: 1rem;"> this is a simulation of an inverted pendulum with a PD controller to bring the pendulum angle θ and silder displacement x to zero. it uses RK4 numerical integration and the controller function at the top of the JS code can be easily modified to test new controllers. </p>
<p id="bottom-text"> made by <a href="https://www.github.com/OscarSaharoy" target="_blank"> oscar saharoy </a> </p>
<svg width="100" height="100" viewbox="-50 -40 100 50" id="shadow" xmlns="http://www.w3.org/2000/svg" style="pointer-events: none">
<mask id="pendulum-shadow">
<rect class="pole" x="-12.5" y="-55" width="5" height="65" style="fill: white; stroke: none" transform-origin="-10 10" />
<circle class="top-circle" cx="-10" cy="10" r="10" style="fill: white; stroke: none" />
<rect class="slider" x="-23" y="4" width="26" height="12" rx="3" style="fill: white; stroke: none" />
<rect x="-110" y="7.5" width="200" height="5" style="fill: white; stroke: none" />
</mask>
<rect x="-300" y="-300" width="600&.........完整代码请登录后点击上方下载按钮下载查看
网友评论0