首页 > 解决方案 > 如何将剪辑路径的文本相对于视口居中并显示所有剪辑路径的文本?

问题描述

这是我的 React 组件演示:https ://codesandbox.io/s/epic-brown-osiq1 ,我现在使用viewBox的值,getBBoxgetBoundingClientRect()实现一些计算以定位我的元素。目前,我已经根据控制台从getBoundingClientRect()日志中为我提供的返回值输入了原始值。您可以在我实现的元素上看到它getBoundingClientRect(),即<svg>' 根元素和clip-path' text' 元素。更好,但text更多的地方是屏幕的中心,真正对齐在text盒子的中心 - 你可以看到“So”的单词是在“Food”单词的开头而不是对齐的box中心。所以我目前处于这一点。

注意:您会在沙箱中看到一些评论,提供我以前的试验的信息或部分内容。 我的代码是做什么的?具体来说,我用一些动画面板显示 aclip-path的文本clip-path- 这是color_panel_group's element- 为构图提供一些动态。在后面还有一个阴影,text为构图提供一些深度。

我想知道我错过了什么。也许有人可以对我的代码行为进行一些解释?

这是我第二次演示的结果代码(大约是 React 组件产生的):

body {
  background: orange;
}

svg {
  background: green;
  display: block;
  margin: auto;
  position: relative;
  z-index: 2;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
}

.component {
  min-width: 100vw;
  min-height: 100vh;
  font-size: 100%;
}

.fade_in_background {
  opacity: 1;
  visibility: visible;
  transition: all 1.5s ease-out 0s;
}

.brandtype {
  margin: auto;
  text-align: center;
}

.brandtype_use {
  position: absolute;
  transform: translate(-112.65px, 0)
}

.clipPath_text {
  text-align: center;
}

.color_panel_group {
  padding: 25px;
}

.shape_animation {
  transform-origin: 0;
  transform: scale(0, 1) translate(0, 0);
  animation: moving-panel 3s 1.5s 1 alternate forwards;
}

.shadow {
  transform: translate(10px, 10px)
}

.shape_animation_shadow {
  fill: black;
  fill-opacity: .505;
  transition: all 1.3s ease-out 0.3s;
}

.brandtype {
  font-size: 6.8em;
}

@keyframes moving-panel {
  to {
    transform: scale(1, 1) translate(20px, 0);
  }
}
<div class="component">
  <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 965 657">
    <defs>
      <symbol id="panel_animation" y="0">
        <clipPath class="clipPath_text" id="clipPath_text"><text class="brandtype" word-spacing="-.45em">
            <tspan x="0%" y="50%" dy="1.6em">So</tspan>
            <tspan x="0%" y="50%" dy="3em">Food</tspan>
          </text></clipPath>
        <g class="shadow" clip-path="url(#clipPath_text)">
          <rect class="shape_animation shape_animation_shadow" width="100%" height="100%" x="-25px">
          </rect>
        </g>
        <g class="color_panel_group" clip-path="url(#clipPath_text)">
          <rect class="shape_animation" fill="#F2385A" width="100%" height="100%"></rect>
          <rect class="shape_animation" fill="#F5A503" width="80%" height="100%"></rect>
          <rect class="shape_animation" fill="#E9F1DF" width="60%" height="100%"></rect>
          <rect class="shape_animation" fill="#56D9CD" width="40%" height="100%"></rect>
          <rect id="shape_animation_ref" class="shape_animation" fill="#3AA1BF" width="20%" height="100%" x="-25px">
          </rect>
        </g>
      </symbol>
    </defs>
    <rect width="100%" height="100%" filter="url(#background_light)"></rect>
    <use width="500px" height="100%" x="50%" xlink:href="#panel_animation" class="brandtype_use"></use>
  </svg>
</div>

感谢您的任何提示。

标签: javascripthtmlcssreactjssvg

解决方案


SVG 中的文本对齐方式不像我们习惯的 HTML 和 CSS 那样工作,在 HTML 和 CSS 中,所有内容都是具有某些尺寸的框,我们可以应用例如text-align: center.

<svg:text>起始坐标中定义将文本行扩展的点。 text-anchor属性控制这种扩展将发生的方向:center值意味着它将双向扩展,因此初始锚点将位于边界框宽度的中间(对于水平书写系统)。请参阅出色的答案,说明这text-anchor是在 SVG 中居中文本的最佳方法:https ://stackoverflow.com/a/23272367/540955 。此外,SVG 内部没有 CSS 位置属性(左/上),只有 x/y 坐标,也没有您在 HTML 中所知道的框模型的边距和其余部分。

因此,在您的代码中添加text-anchor="middle"和向右移动x坐标会产生居中的文本。我建议使用裸<text>元素而不是<tspan>s,因为用dx/移动它们dy是相对于前面的最后一个字符,并且这个字符可能是来自父级的一些空格<text>(取决于代码格式),这会产生不平衡的居中。对于更简单的计算(或仅用于水平书写系统)也很有用,因为它将锚点从基线移动到“中心线”。所以使用属性(就像你已经做的那样)将第一行“一半”的行高向上移动,另一行向下移动应该可以解决问题:dominant-baseline="central"middledy

<svg viewBox="0 0 800 200" text-anchor="middle" dominant-baseline="central" font-size="100">
 <!-- Outline and diagonals with center point for illustration: -->
 <path d="M0,0h800v200h-800zl800,200m0 -200L0,200" fill="#FC9" stroke-width="1" stroke="rgba(0,0,0,0.3)"></path>
 <circle cx="50%" cy="50%" r="10" fill="red"></circle>
 <!-- Centered text: -->
 <text x="50%" y="50%" fill="rgba(0,0,0,0.3)">So</text>
 <!-- Shifted up and down: -->
 <text x="50%" y="50%" dy="-0.5em">So</text>
 <text x="50%" y="50%" dy="+0.5em">Food</text>
</svg>


(不完全相关:只能在 CSS 中background-clip: text使用. 这应该适用于任何支持背景剪辑的浏览器。)

div {
	display: flex;
	flex-direction: column;
	align-items: center;
	font-size: 30vh;
	line-height: 30vh;
	font-weight: bold;
	font-family: Impact;
}
span {
	color: #fff;
	background-color: #000;
	width: 100%;
	text-align: center;
}
@supports (-webkit-text-fill-color: transparent) and (-webkit-background-clip: text) {
	span {
		-webkit-text-fill-color: transparent;
		-webkit-background-clip: text;
		animation: 2s wohoo infinite alternate cubic-bezier(1,0,1,1);
		background-position: 0 0;
		background-size: 100% 100%;
		background-color: transparent;
		background-image: linear-gradient(
			to right,
			#f2385a 0,
			#f2385a 20%,
			#f5a503 0,
			#f5a503 40%,
			#e9f1df 0,
			#e9f1df 60%,
			#56d9cd 0,
			#56d9cd 80%,
			#3aa1bf 0,
			#3aa1bf 100%
		);
		background-repeat: no-repeat;
		transform-origin: center center;
	}
}

@keyframes wohoo {
	from {
		background-size: 0 100%;
		background-position: -5vh 0;
		transform: scale(0.7);
	}
	50% {
		transform: scale(0.7);
	}
	90% {
		transform: scale(0.9);
	}
	to {
		background-size: 500% 100%;
		background-position: 0vh 0;
		transform: scale(0.9) 
	}
}

html,body{margin:0;overflow:hidden;}
body {
	background-color: #1d1f20;
	color: snow;
	display: flex;
	flex-direction: row;
	justify-content: center;
	width: 100%;
}
<div>
	<span>Baz</span>
	<span>Gazonk</span>
	<span>Qux</span>
</div>


推荐阅读