沿水平响应路径制作 SVG 动画

问题描述 投票:0回答:1

我有一个水平响应的 SVG 路径,可以在不保持其比例的情况下进行拉伸,并且在标签上使用

preserveAspectRatio="none"
并在路径上使用
vector-effect="non-scaling-stroke"
时可以保持其完整,它可以正常工作。但我还需要沿着相同的路径为元素设置动画,而不丢失其纵横比。

这是一个示例,您可以看到,如果您水平调整包装器的大小,它就可以工作,但对于因全局

preserveAspectRatio="none"
属性而导致失去纵横比的星形则不起作用。我找不到解决方法,并且让路径水平响应并保持星形完整并遵循路径......

.wrapper {
    width: 100%;
    min-width: 200px;
    max-width: 100%;
    height: 200px;
    resize: horizontal;
    overflow: hidden;
    border: 1px solid blue;
}
svg {
    width: 100%;
    height: 100%;
}
.path {
    fill: none;
    stroke: black;
    stroke-width: 2px;
    stroke-dasharray: 6 6;
    stroke-linecap:round;
}
.star {
    fill: red;
}
<div class="wrapper">
        <svg viewBox="0 0 400 200" preserveAspectRatio="none">
            <defs>
                <path id="star" d="M0,24.675L2.679,32.921L11.349,32.921L4.335,38.017L7.014,46.262L0,41.166L-7.014,46.262L-4.335,38.017L-11.349,32.921L-2.679,32.921L0,24.675Z"/>
                <path id="path" d="M0,36.608C0,36.608 64.096,15.519 92.956,48.531C121.816,81.542 101.293,129.283 74.824,115.941C48.354,102.599 68.017,24.7 188.557,73.454C309.097,122.207 261.935,170.513 400,175.664" vector-effect="non-scaling-stroke"/>
            </defs>
            <use href="#path" class="path"/>
            <use href="#star" class="star" x="0" y="-36">
                <animateMotion dur="10s" repeatCount="indefinite" rotate="auto">
                    <mpath href="#path"/>
                </animateMotion>
            </use>
        </svg>
    </div>

html css svg svg-animate
1个回答
0
投票

我想我有一个好主意,用星锚元素替换原来的 svg 星。这样我就可以有第二个 SVG,其中包含保持其纵横比的实际星星,跟随星星锚。 随意看看。也许它给你任何想法。 但我认为这种方法的边缘无法以令人满意的方式消除。

明天我将回到我在评论中提到的想法。也就是尝试在JS中计算扭曲的路径。

const star = document.querySelector(".star-svg");

function moveStarToAnchor() { 
  const anchorRect = document.querySelector(".star_anchor").getBoundingClientRect();
  star.style.translate = anchorRect.x+ "px " + anchorRect.y + "px";
}

setInterval(moveStarToAnchor, 100);
.wrapper {
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  border: 1px solid blue;
  display: grid;
  position: relative;
}
.path-svg {
  width: 100%;
  height: 100%;
  grid-column: 1/2;
  grid-row: 1/2;
  position: absolute;
}

.star-svg {
  fill: red;
  grid-column: 1/2;
  grid-row: 1/2;
  position: absolute;
  top: 0;
  left: 0;
  width: 50px;
  height: 50px;
  transition: translate 100ms;
}

.path {
  fill: none;
  stroke: black;
  stroke-width: 2px;
  stroke-dasharray: 6 6;
  stroke-linecap: round;
}

body {
  margin: 0;
}

* {
  box-sizing: border-box;
}
<div class="wrapper">
  <svg class="path-svg" viewBox="0 0 400 200" preserveAspectRatio="none">
    <defs>
      <path id="star_anchor" d="M0,24.675L2.679" />
      <path id="path" d="M0,36.608C0,36.608 64.096,15.519 92.956,48.531C121.816,81.542 101.293,129.283 74.824,115.941C48.354,102.599 68.017,24.7 188.557,73.454C309.097,122.207 261.935,170.513 400,175.664" vector-effect="non-scaling-stroke" />
    </defs>
    <use href="#path" class="path" />
    <use href="#star_anchor" class="star_anchor" x="0" y="-36">
      <animateMotion dur="10s" repeatCount="indefinite" rotate="auto">
        <mpath href="#path" />
      </animateMotion>
    </use>
  </svg>
  <svg class="star-svg"  viewBox="0 0 10 10" width="10" height="10">
      <circle r="5" cx="5" cy="5" fill="red" />
  </svg>
</div>

© www.soinside.com 2019 - 2024. All rights reserved.