首页 > 解决方案 > 向滚动的 SVG 曲线添加名称

问题描述

我正在尝试创建一个在用户向下滚动时沿曲线滚动的名称列表。这使用 jquery 将文本沿 svg 路径的偏移位置与滚动高度链接起来。目前,每次添加名称时,我都必须调整 jquery 中的数字(当前为 70)以将所有名称滚动到视图中,然后在姓氏出现时停止,不再继续。因此,例如现在那里的名称数量,如果我将其调整为 60,它不会滚动足够远以显示所有这些,如果我将其调整得太高,名称会沿着我不想要的曲线滚动太远即将发生。我不知道这个数字与名称或字符的数量之间有什么相关性(如果有的话)。

无论如何,我可以使用 jquery 来检测名称或字符的数量并动态调整以始终将名称滚动到足够远的位置,因此每次添加名称时我都不必总是手动调整 jquery名单。

这是示例

const textPath = document.querySelector("#text-path");

const h = document.documentElement, 
      b = document.body,
      st = 'scrollTop',
      sh = 'scrollHeight';

document.addEventListener("scroll", e => {
  let percent = (h[st]||b[st]) / ((h[sh]||b[sh]) - h.clientHeight) * 70;
  textPath.setAttribute("startOffset", (-percent * 40) + 20)
});
@import url('https://fonts.googleapis.com/css?family=PT+Serif&display=swap');

body {
  margin: 5rem 0;
  min-height: 200vh;
  font-family: 'PT Serif', serif;
}
p {
  max-width: 500px;
  margin: 0 auto 1rem;
}
text {
  fill: red;
  font-size: 70px;
  letter-spacing: 5px;
}

svg {
  position: fixed;
  top: 200px;
  left: 0;
}
<svg width="100%" height="700px" viewBox="0 0 1920 1080">
  <path id="curve" fill="transparent" d="M65.9,222.1c115.6-21.7,281.1-3.9,352.5,102.4c35.7,53.1,44,119.8,25.1,180.3c-20,64.1-64.2,124.1-65,193.1
    c-0.8,65.9,50.5,123.8,111,150c65.9,28.5,150.5,32.9,220.7,20.1c71.3-12.9,141.3-60.9,157.7-131.5c17.4-75-25.1-142.5-65.5-201.5
    c-30.8-44.9-61.6-94.4-59.8-148.8c3-88.4,91.2-146.9,172-154.8c93.9-9.2,230.5,26.9,278.6,115.9c27.1,50.2,22.9,111,14.8,167.4
    c-14.7,102.2-21.8,206.5,66.2,278.8c77.7,63.9,198,63.5,268.3-12.1c53.1-57.1,64.2-145.9,33.5-216c-15.8-36.2-38.5-69-56.2-104.4
    c-10.2-20.3-18.9-42.1-19.1-64.9c-0.6-67.9,62.3-120.1,126.5-127.1c59.5-6.5,140.4,28.6,204,56.6"></path>
  <text dy="31" width="100%" height="100%" style="transform:translate3d(0,0,0);">
      <textPath style="transform:translate3d(0,0,0);" alignment-baseline="top" xlink:href="#curve" startOffset="20px" id="text-path">JAMES DYER AL MURPHY CHRISSIE ABBOTT CECILE DORMEAU GRACE HELMER OWEN POMERY SUPER FREAK JASON LYON DANIEL FROST ESSY MAY JACK HUDSON KATE ISOBEL SCOTT </textPath>
  </text>
</svg>

https://codepen.io/dan-hayman/pen/VweZKdp

非常感谢你的帮助

标签: jquerysvgscroll

解决方案


主要思想是这样的:

你需要路径的长度,你可以使用curve.getTotalLength();.

您还需要文本的长度。接下来,您将获得 2 个长度之间的差异(我的代码中的 delta),然后使用此值来重置属性的值startOffset

问题 1: 如果您尝试获取theText具有 textPath 的长度,则无法获得正确的值。您需要将文本放在不同的文本元素中(#txt在我的代码中)并获取该文本的长度。接下来我textPath.textContent用来设置文本路径元素的文本内容。

问题 2: 为了获得文本的长度,通常我会使用txt.getComputedTextLength()ortxt.textLength.baseVal.value;但因为在 css 中你letter-spacing: 5px;没有这些将返回正确的值。所以我正在使用const textLength = txt.getBBox().width;

const textPath = document.querySelector("#text-path");
const txt = document.querySelector("#txt");
const curve = document.querySelector("#curve");
//txt.getComputedTextLength()
//txt.textLength.baseVal.value;
const textLength = txt.getBBox().width;
const curveLength = curve.getTotalLength();


textPath.textContent = txt.textContent;

let delta = textLength - curveLength;

const h = document.documentElement, 
      b = document.body,
      st = 'scrollTop',
      sh = 'scrollHeight';

document.addEventListener("scroll", e => {  
  let percent = (h[st]||b[st]) / ((h[sh]||b[sh]) - h.clientHeight);
  let att = -(percent * (delta * 100/curveLength)) + "%";
  textPath.setAttribute("startOffset", att);
});
@import url('https://fonts.googleapis.com/css?family=PT+Serif&display=swap');

body {
  margin: 5rem 0;
  min-height: 200vh;
  font-family: 'PT Serif', serif;
}

text {
  fill: red;  
  letter-spacing: 5px;
}

svg {
  position: fixed;
  top: 200px;
  left: 0;
  outline:solid;
}
<svg viewBox="0 0 2000 1000">
<defs>
  <path id="curve" fill="transparent" stroke="black" stroke-width="5"  d="M65.9,222.1c115.6-21.7,281.1-3.9,352.5,102.4c35.7,53.1,44,119.8,25.1,180.3c-20,64.1-64.2,124.1-65,193.1
    c-0.8,65.9,50.5,123.8,111,150c65.9,28.5,150.5,32.9,220.7,20.1c71.3-12.9,141.3-60.9,157.7-131.5c17.4-75-25.1-142.5-65.5-201.5
    c-30.8-44.9-61.6-94.4-59.8-148.8c3-88.4,91.2-146.9,172-154.8c93.9-9.2,230.5,26.9,278.6,115.9c27.1,50.2,22.9,111,14.8,167.4
    c-14.7,102.2-21.8,206.5,66.2,278.8c77.7,63.9,198,63.5,268.3-12.1c53.1-57.1,64.2-145.9,33.5-216c-15.8-36.2-38.5-69-56.2-104.4
    c-10.2-20.3-18.9-42.1-19.1-64.9c-0.6-67.9,62.3-120.1,126.5-127.1c59.5-6.5,140.4,28.6,204,56.6"></path>
  <text dy="70" id="txt" font-size="70px">JAMES DYER AL MURPHY CHRISSIE ABBOTT CECILE DORMEAU GRACE HELMER OWEN POMERY SUPER FREAK JASON LYON DANIEL FROST ESSY MAY JACK HUDSON KATE ISOBEL SCOTT</text>
  </defs>
  
  <text dy="31" font-size="70" id="theText">
      <textPath xlink:href="#curve" id="text-path" startOffset="0"></textPath>
  </text>
</svg>


推荐阅读