有没有办法像跑步的传送带一样给这个东西添加动画?

huangapple go评论58阅读模式
英文:

Is there are anyway to animate this like a running conveyor belt?

问题

I need to animate this so that it'll look like a running conveyor belt, is there any way to achieve it?

这部分内容是关于如何使其看起来像一个运行的传送带,有没有办法实现?

英文:

I need to animate this so that it'll look like a running conveyor belt, is there are any way to achieve it?

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const cx = 50;
const cy = 50;
const width = 40;
const radius = 100; // CV size
const TwoPi = Math.PI * 0.5;

const circ = TwoPi * radius;
const height = circ / 4; // Roller counts
const parent = document.getElementById(&quot;bend&quot;);

for (let i = 0; i &lt; circ; i += height) {
    let seg = document.createElementNS(&quot;http://www.w3.org/2000/svg&quot;, &quot;path&quot;);
    
    let rs = (i / circ) * TwoPi;
    let re = ((i + height) / circ) * TwoPi;
    
    let ss = Math.sin(rs);
    let cs = Math.cos(rs);
    let se = Math.sin(re);
    let ce = Math.cos(re);
    
    seg.setAttribute(&quot;d&quot;,
        `M${(cs * radius) + cx},${(ss * radius) + cy}` +
        `A${radius},${radius} ${((re - rs) / Math.PI) * 180},0,1 ${(ce * radius) + cx},${(se * radius) + cy}` +
        `L${(ce * (radius - width)) + cx},${(se * (radius - width)) + cy}` +
        `A${radius - width},${radius - width} ${((re - rs) / Math.PI) * -180},0,0 ${(cs * (radius - width)) + cx},${(ss * (radius - width)) + cy}z`
    );
    
    seg.setAttribute(&quot;fill&quot;, &quot;url(#grad2)&quot;);
    seg.setAttribute(&quot;stroke&quot;, &quot;#008000&quot;);
    
    parent.appendChild(seg);
}

<!-- language: lang-html -->

&lt;svg width=&quot;200&quot; height=&quot;200&quot; viewBox=&quot;0 0 200 200&quot; style=&quot;transform: rotate(-90deg)&quot;&gt;
  &lt;defs&gt;
    &lt;linearGradient id=&quot;grad2&quot; x1=&quot;0%&quot; y1=&quot;0%&quot; x2=&quot;40%&quot; y2=&quot;100%&quot;&gt;
      &lt;stop offset=&quot;0%&quot; style=&quot;stop-color:#008000;stop-opacity:1&quot;/&gt;
      &lt;stop offset=&quot;100%&quot; style=&quot;stop-color:#c7fdc7;stop-opacity:1&quot;/&gt;
    &lt;/linearGradient&gt;
  &lt;/defs&gt;
    &lt;g id=&quot;bend&quot;&gt;&lt;/g&gt;
&lt;/svg&gt;

<!-- end snippet -->

Here's the preview of the above code, and this is the running animation example.

Thankyou.

答案1

得分: 3

这是一个使用重复的圆片段制作的版本。动画是使用 &lt;animateTransform&gt; 元素创建的。

减少了计算,增加了构建。

<svg width="200" viewBox="0 0 200 200">
  <defs>
    <linearGradient id="grad" x1="60%" y1="60%" x2="90%" y2="90%">
      <stop offset="0%" stop-color="#008000" stop-opacity="1"/>
      <stop offset="100%" stop-color="#c7fdc7" stop-opacity="1"/>
    </linearGradient>
    <mask id="m1">
      <rect x="50" y="50" width="100" height="100" fill="white"/>
    </mask>
    <circle id="c1" cx="0" cy="0" r="70" fill="none"
      stroke="url(#grad)" stroke-width="28" pathLength="360"
      stroke-dasharray="19 360" />
  </defs>
  <g mask="url(#m1)">
    <g transform="translate(50 150) rotate(-180)">
      <g>
        <circle id="c1" cx="0" cy="0" r="70" fill="none"
          stroke="darkgreen" stroke-width="30" />
        <use href="#c1"/>
        <use href="#c1" transform="rotate(20)"/>
        <use href="#c1" transform="rotate(40)"/>
        <use href="#c1" transform="rotate(60)"/>
        <use href="#c1" transform="rotate(80)"/>
        <use href="#c1" transform="rotate(100)"/>
        <use href="#c1" transform="rotate(120)"/>
        <use href="#c1" transform="rotate(140)"/>
        <use href="#c1" transform="rotate(160)"/>
        <animateTransform
          attributeName="transform"
          attributeType="XML"
          type="rotate"
          from="0"
          to="80"
          dur="5s"
          repeatCount="indefinite" />
      </g>
    </g>
  </g>
</svg>
英文:

Here is a version made with a slice of a circle that is repeated. The animation is made with the &lt;animateTransform&gt; element.

Less calculations and more construction.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

&lt;svg width=&quot;200&quot; viewBox=&quot;0 0 200 200&quot;&gt;
&lt;defs&gt;
&lt;linearGradient id=&quot;grad&quot; x1=&quot;60%&quot; y1=&quot;60%&quot; x2=&quot;90%&quot; y2=&quot;90%&quot;&gt;
&lt;stop offset=&quot;0%&quot; stop-color=&quot;#008000&quot; stop-opacity=&quot;1&quot;/&gt;
&lt;stop offset=&quot;100%&quot; stop-color=&quot;#c7fdc7&quot; stop-opacity=&quot;1&quot;/&gt;
&lt;/linearGradient&gt;
&lt;mask id=&quot;m1&quot;&gt;
&lt;rect x=&quot;50&quot; y=&quot;50&quot; width=&quot;100&quot; height=&quot;100&quot; fill=&quot;white&quot;/&gt;
&lt;/mask&gt;
&lt;circle id=&quot;c1&quot; cx=&quot;0&quot; cy=&quot;0&quot; r=&quot;70&quot; fill=&quot;none&quot;
stroke=&quot;url(#grad)&quot; stroke-width=&quot;28&quot; pathLength=&quot;360&quot;
stroke-dasharray=&quot;19 360&quot; /&gt;
&lt;/defs&gt;
&lt;g mask=&quot;url(#m1)&quot;&gt;
&lt;g transform=&quot;translate(50 150) rotate(-180)&quot; &gt;
&lt;g&gt;
&lt;circle id=&quot;c1&quot; cx=&quot;0&quot; cy=&quot;0&quot; r=&quot;70&quot; fill=&quot;none&quot;
stroke=&quot;darkgreen&quot; stroke-width=&quot;30&quot; /&gt;
&lt;use href=&quot;#c1&quot;/&gt;
&lt;use href=&quot;#c1&quot; transform=&quot;rotate(20)&quot;/&gt;
&lt;use href=&quot;#c1&quot; transform=&quot;rotate(40)&quot;/&gt;
&lt;use href=&quot;#c1&quot; transform=&quot;rotate(60)&quot;/&gt;
&lt;use href=&quot;#c1&quot; transform=&quot;rotate(80)&quot;/&gt;
&lt;use href=&quot;#c1&quot; transform=&quot;rotate(100)&quot;/&gt;
&lt;use href=&quot;#c1&quot; transform=&quot;rotate(120)&quot;/&gt;
&lt;use href=&quot;#c1&quot; transform=&quot;rotate(140)&quot;/&gt;
&lt;use href=&quot;#c1&quot; transform=&quot;rotate(160)&quot;/&gt;
&lt;animateTransform
attributeName=&quot;transform&quot;
attributeType=&quot;XML&quot;
type=&quot;rotate&quot;
from=&quot;0&quot;
to=&quot;80&quot;
dur=&quot;5s&quot;
repeatCount=&quot;indefinite&quot; /&gt;
&lt;/g&gt;
&lt;/g&gt;
&lt;/g&gt;
&lt;/svg&gt;

<!-- end snippet -->

答案2

得分: 1

以下是您要翻译的代码部分:

const drawSegment = (fromAngle, toAngle, innerRadius, outerRadius, centerX, centerY) => {
    const svg = d3.select('svg');
    const x1 = centerX + innerRadius * Math.sin(fromAngle);
    const y1 = centerY - innerRadius * Math.cos(fromAngle);
    const x2 = centerX + outerRadius * Math.sin(fromAngle);
    const y2 = centerY - outerRadius * Math.cos(fromAngle);
    const x3 = centerX + outerRadius * Math.sin(toAngle);
    const y3 = centerY - outerRadius * Math.cos(toAngle);
    const x4 = centerX + innerRadius * Math.sin(toAngle);
    const y4 = centerY - innerRadius * Math.cos(toAngle);
    const path = `M ${x1},${y1} L ${x2},${y2} A ${outerRadius},${outerRadius} 0 0 1 ${x3},${y3} L ${x4},${y4} A ${innerRadius}, ${innerRadius} 0 0 0 ${x1},${y1} Z`;

    svg.append('path')
        .attr('d', path)
        .attr('stroke', '#008000')
        .attr('fill', 'url(#grad)')
}

const a = Math.PI / 8;
let start = 0;

setInterval(() => {
    d3.select('svg').selectAll('path').remove();
    if (start < 1) {
        start += 0.02;
    } else
        start = 0;

    if (start > 0) {
        drawSegment(0, start * a, 50, 80, 20, 100);
    }
    for (let i = start; i < 4; i++) {
        drawSegment(a * i, Math.min((i + 1) * a, a * 4), 50, 80, 20, 100);
    }
}, 50);
svg {
    border: 1px solid #000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="200" height="120">
    <defs>
        <linearGradient id="grad" x1="0%" y1="0%" x2="40%" y2="100%">
            <stop offset="0%" style="stop-color:#008000;stop-opacity:1" />
            <stop offset="100%" style="stop-color:#c7fdc7;stop-opacity:1" />
        </linearGradient>
    </defs>
    <g id="bend"></g>
</svg>
英文:

Here is a possible solution (run the snippet below):

<!-- begin snippet: js hide: false console: false babel: false -->

<!-- language: lang-js -->

const drawSegment = (fromAngle, toAngle, innerRadius, outerRadius, centerX, centerY) => {
const svg = d3.select('svg');
const x1 = centerX + innerRadius * Math.sin(fromAngle);
const y1 = centerY - innerRadius * Math.cos(fromAngle);
const x2 = centerX + outerRadius * Math.sin(fromAngle);
const y2 = centerY - outerRadius * Math.cos(fromAngle);
const x3 = centerX + outerRadius * Math.sin(toAngle);
const y3 = centerY - outerRadius * Math.cos(toAngle);
const x4 = centerX + innerRadius * Math.sin(toAngle);
const y4 = centerY - innerRadius * Math.cos(toAngle);
const path = M ${x1},${y1} L ${x2},${y2} A ${outerRadius},${outerRadius} 0 0 1 ${x3},${y3} L ${x4},${y4} A ${innerRadius}, ${innerRadius} 0 0 0 ${x1},${y1} Z;

  svg.append(&#39;path&#39;)
.attr(&#39;d&#39;, path)
.attr(&#39;stroke&#39;, &#39;#008000&#39;)
.attr(&#39;fill&#39;, &#39;url(#grad)&#39;)
}
const a = Math.PI / 8;
let start = 0;
setInterval(() =&gt; {
d3.select(&#39;svg&#39;).selectAll(&#39;path&#39;).remove();
if (start &lt; 1) {
start += 0.02;
}
else
start = 0;
if (start &gt; 0) {
drawSegment(0, start * a, 50, 80, 20, 100);
}
for (let i = start; i &lt; 4; i++) {
drawSegment(a * i, Math.min((i + 1) * a, a * 4), 50, 80, 20, 100);
}
}, 50);

<!-- language: lang-css -->

svg {
border: 1px solid #000;
}

<!-- language: lang-html -->

&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js&quot;&gt;&lt;/script&gt;
&lt;svg width=&quot;200&quot; height=&quot;120&quot;&gt;
&lt;defs&gt;
&lt;linearGradient id=&quot;grad&quot; x1=&quot;0%&quot; y1=&quot;0%&quot; x2=&quot;40%&quot; y2=&quot;100%&quot;&gt;
&lt;stop offset=&quot;0%&quot; style=&quot;stop-color:#008000;stop-opacity:1&quot;/&gt;
&lt;stop offset=&quot;100%&quot; style=&quot;stop-color:#c7fdc7;stop-opacity:1&quot;/&gt;
&lt;/linearGradient&gt;
&lt;/defs&gt;
&lt;g id=&quot;bend&quot;&gt;&lt;/g&gt;
&lt;/svg&gt;

<!-- end snippet -->

答案3

得分: 0

这是一个反向动画:

const drawSegment = (fromAngle, toAngle, 
    	innerRadius, outerRadius, centerX, centerY) => {
    	const svg = d3.select('svg');
      const x1 = centerX + innerRadius * Math.sin(fromAngle);
      const y1 = centerY - innerRadius * Math.cos(fromAngle);
      const x2 = centerX + outerRadius * Math.sin(fromAngle);
      const y2 = centerY - outerRadius * Math.cos(fromAngle);
      const x3 = centerX + outerRadius * Math.sin(toAngle);
      const y3 = centerY - outerRadius * Math.cos(toAngle);
      const x4 = centerX + innerRadius * Math.sin(toAngle);
      const y4 = centerY - innerRadius * Math.cos(toAngle);
      const path = `M ${x1},${y1} L ${x2},${y2} A ${outerRadius},${outerRadius} 0 0 1 ${x3},${y3} L ${x4},${y4} A ${innerRadius}, ${innerRadius} 0 0 0 ${x1},${y1} Z`;
      
      svg.append('path')
      	.attr('d', path)
        .attr('stroke', '#0F0')
        .attr('fill', 'url(#grad)')
    }

    const seg = Math.PI / 8;
    let delta = 0, start, end;

    setInterval(() => {
    	d3.select('svg').selectAll('path').remove();
    	if (delta < 1) {
      	delta += 0.02;
      }
      else {
      	delta = 0;
      }
      if (delta > 0) {
      	start = seg * (4 - delta);
        end = seg * 4;
      	drawSegment(start, end, 50, 80, 20, 100);
      }
      else {
      	start = seg * 4;
      }
      while (start > 0) 	{
      	end = start;
      	start = Math.max (0, end - seg);
        drawSegment(start, end, 50, 80, 20, 100);
      }
    }, 100);
svg {
  border: 1px solid #000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="200" height="120">
  <defs>
    <linearGradient id="grad" x1="0%" y1="0%" x2="40%" y2="100%">
      <stop offset="0%" style="stop-color:#008000;stop-opacity:1"/>
      <stop offset="100%" style="stop-color:#c7fdc7;stop-opacity:1"/>
    </linearGradient>
  </defs>
    <g id="bend"></g>
</svg>
英文:

Here is a reverse animation:

<!-- begin snippet: js hide: false console: false babel: false -->

<!-- language: lang-js -->

const drawSegment = (fromAngle, toAngle, 
innerRadius, outerRadius, centerX, centerY) =&gt; {
const svg = d3.select(&#39;svg&#39;);
const x1 = centerX + innerRadius * Math.sin(fromAngle);
const y1 = centerY - innerRadius * Math.cos(fromAngle);
const x2 = centerX + outerRadius * Math.sin(fromAngle);
const y2 = centerY - outerRadius * Math.cos(fromAngle);
const x3 = centerX + outerRadius * Math.sin(toAngle);
const y3 = centerY - outerRadius * Math.cos(toAngle);
const x4 = centerX + innerRadius * Math.sin(toAngle);
const y4 = centerY - innerRadius * Math.cos(toAngle);
const path = `M ${x1},${y1} L ${x2},${y2} A ${outerRadius},${outerRadius} 0 0 1 ${x3},${y3} L ${x4},${y4} A ${innerRadius}, ${innerRadius} 0 0 0 ${x1},${y1} Z`;
svg.append(&#39;path&#39;)
.attr(&#39;d&#39;, path)
.attr(&#39;stroke&#39;, &#39;#0F0&#39;)
.attr(&#39;fill&#39;, &#39;url(#grad)&#39;)
}
const seg = Math.PI / 8;
let delta = 0, start, end;
setInterval(() =&gt; {
d3.select(&#39;svg&#39;).selectAll(&#39;path&#39;).remove();
if (delta &lt; 1) {
delta += 0.02;
}
else {
delta = 0;
}
if (delta &gt; 0) {
start = seg * (4 - delta);
end = seg * 4;
drawSegment(start, end, 50, 80, 20, 100);
}
else {
start = seg * 4;
}
while (start &gt; 0) 	{
end = start;
start = Math.max (0, end - seg);
drawSegment(start, end, 50, 80, 20, 100);
}
}, 100);

<!-- language: lang-css -->

svg {
border: 1px solid #000;
}

<!-- language: lang-html -->

&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js&quot;&gt;&lt;/script&gt;
&lt;svg width=&quot;200&quot; height=&quot;120&quot;&gt;
&lt;defs&gt;
&lt;linearGradient id=&quot;grad&quot; x1=&quot;0%&quot; y1=&quot;0%&quot; x2=&quot;40%&quot; y2=&quot;100%&quot;&gt;
&lt;stop offset=&quot;0%&quot; style=&quot;stop-color:#008000;stop-opacity:1&quot;/&gt;
&lt;stop offset=&quot;100%&quot; style=&quot;stop-color:#c7fdc7;stop-opacity:1&quot;/&gt;
&lt;/linearGradient&gt;
&lt;/defs&gt;
&lt;g id=&quot;bend&quot;&gt;&lt;/g&gt;
&lt;/svg&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年5月10日 15:38:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76215999.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定