文本偏移

        几天之前写下了 IE Factor 这篇文章之后,我就想着我应该要举一个上礼拜让我抓头的例子。我也提供了我提出的解决方案,就像我周一所描述的:很烦实现不了效果,这促使我去做一些绝对没有意义的尝试。

        这种bug没有例外,这需要做许多看起来机会渺茫得可怜的尝试去找出方法来修复它。我也提出了IE的几种不同组合,这几乎能让写CSS的人疯掉,这些IE的bug不是IE5.0的,而是IE5.5的,IE5.5当然会比它的前辈IE5.0在CSS实现方面好得多,但是伴随着IE5.5的发布和提高,一些IE5.0中没有的新bug又出现了,这些同样的bug同时被带到了IE6中.

        问题:将一些200像素宽的内容盒子(这里我称之为”模块“)作垂直方向连续排列,这几乎是最原始的,一点也不复杂,每个模块都由一个大标题<h2>标签,标题后跟一个段落<p>标签组成。

        我提供的例子已经被精简了,几乎没有任何的设计成份,我只是让标题的文字变小了点,减小了<h2>中的距离顶部和底部的边距。因为我正创建的模块,边框只出现在两侧,我要让它变得更夸张以使bug变得更明显。为了看出它的异常,请在IE5.5或者IE6下看这个存在bug的例子,然后在其它正常的浏览器下看一下正常的结果。如果很不幸你没有IE5.5或者IE6,我这儿提供了第一个和最后一个模块的快照,这是在IE6下得到的结果


        注意观察每个模块下文字是怎么样离左侧越来越远的。这个bug从第二个模块中开始出现,在它以下的模块中bug变得越来越糟糕,直到最后一个模块,你会发现它已经被模块的容器覆盖切除了。随着越来越多的模块被添加,IE5.5和IE6下这个bug将会被无限放大,其它浏览器都不会发现这个问题,会返回正确的结果。

        很明显,这个问题是不能被接受的。我不知道客户会在这个侧边栏堆积多少个模块,我尝试了书中提到的每一个方法来阻止文字向左偏移。这个问题似乎很难理解,因为每个都相邻的而且独立的模块。代码是完全有效的,彼此也没有容器重叠,我尝试着用200像素的边框,也没有效果,我移掉了内边距改成外边距,移掉了标题,很不幸,都不行。

        我走开了,去吃午饭,回来之后就找到了问题的根源,我发现每个模块之间文字往左偏移的像素增量是4像素,这时,每个边框就只有2像素框,所以模块之间的文字偏移量到左和右边框之间的宽度都是相等的,我移掉边框,bug消失了看这个例子

        好的,这是边框问题,但是我要实现的效果不能没有边框,我尝试给顶部和底部加边框,太漂亮了!问题解决了。结果证明缺一个底部边框(可以是任何宽度值)来修复这个bug,为什么少一条底部边框会影响页面上的另外一个元素,这一点意义都没有,但在IE5.5和IE6上,它的确如此

        所以这个bug最终可以被如下描述:如果在一个元素中只有左右边框,没有底边框,第一个元素的侧边框将会影响紧挨着的下一个元素中文本的位置。

        为了修复这个例子中的bug,我给每个模块加了一个1像素的底边框,同时确保它的颜色和最明显的模块背景色一致(在这个例子中,背景色和底部边框都是白色),因为在其它浏览器中这个底部边框是不必要的,所以我也不想让它出现在这儿,我加了一条规则以避免其它浏览器中出现这条底边框:

       

.module {
  margin:0 0 15px;
  border:4px solid #666;
  border-width:0 4px;
  border-bottom:1px solid #fff;
  padding:2px 10px;
  }
html>body .module {
  border-bottom-width:0;
  }

        通过使用一个子选择器,最终将会隐藏所有浏览器的底边框(除IE5.5和IE6)。(请看最终效果)我也发现给所有模块添加一个宽度值也能解决这个文本偏移问题。但是IE5/win's破坏了盒模型,如果使用了左边距和右边距,这个问题需要被修复,这个时候每个独立模块的宽度就不必要被指定了,只需要给它们的父元素#sidebar添加宽度就可以了,所以我开始使劲的添加/删除底部边框以避免重新定义模块的宽度。

        这只是延迟我最近项目的一个无法解释的bug,如果任何一个人遇到同样的bug,希望这个例子可以帮你省省头发,让他们不必这么沮丧。


文章出处:http://stopdesign.com/archive/2004/01/30/ie_factor_example.html


英文不好,粗略的翻译了一下,欢迎拍砖!


以下是我的源码:

1.存在bug的源码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
	<head>
		<meta http-equiv="content-type" content="text/html; charset=utf-8" />
		<title>文本向左偏移</title>
		<style type="text/css">
			#sidebar {
				width: 200px;
			}
			.module {
				margin: 0 0 15px;
				border: 4px solid pink;
				border-width: 0 4px;
				padding: 2px 10px;
			}
			h2 {
				margin: 0.35em 0 0.35em;
				font-size: 120%;
				color: #c00;
			}
			p {
				margin:0 0 .75em;
			}
		</style>
	</head>

	<body>
	
		<p>这种简单的,几乎没有任何样式的实验在<strong>IE5.5和IE6</strong>发现了旧bug,详情请参考<a href="/log/2004/01/30/ie_factor_example.html">这篇日志入口</a>. (IE5.0下是正常的.) 这个bug在连续模块中被一直恶化,直到文本和覆盖它的模块宽度相等为止!</p>
		
		<div id="sidebar">
		
			<div class="module">
				<h2>模块标题</h2>
				<p>这是模块内容,在IE6下,你会发现除第一个模块正常外,其它每往下一个模块文字就住左偏移4个像素</p>
			</div>
		  
		  	<div class="module">
				<h2>模块标题</h2>
				<p>这是模块内容,在IE6下,你会发现除第一个模块正常外,其它每往下一个模块文字就住左偏移4个像素</p>
			</div>
		  
		
		  	<div class="module">
				<h2>模块标题</h2>
				<p>这是模块内容,在IE6下,你会发现除第一个模块正常外,其它每往下一个模块文字就住左偏移4个像素</p>
		  	</div>
		  
		  	<div class="module">
				<h2>模块标题</h2>
				<p>这是模块内容,在IE6下,你会发现除第一个模块正常外,其它每往下一个模块文字就住左偏移4个像素</p>
		  	</div>
		</div>
	</body>
</html>


2.去掉边框之后的源码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
	<head>
		<meta http-equiv="content-type" content="text/html; charset=utf-8" />
		<title>文本向左偏移</title>
		<style type="text/css">
			#sidebar {
				width: 200px;
			}
			.module {
				margin: 0 0 15px;
				border: 0;
				padding: 2px 10px;
			}
			h2 {
				margin: 0.35em 0 0.35em;
				font-size: 120%;
				color: #c00;
			}
			p {
				margin:0 0 .75em;
			}
		</style>
	</head>

	<body>
	
		<p>这种简单的,几乎没有任何样式的实验在<strong>IE5.5和IE6</strong>发现了旧bug,详情请参考<a href="/log/2004/01/30/ie_factor_example.html">这篇日志入口</a>. (IE5.0下是正常的.) 这个bug在连续模块中被一直恶化,直到文本和覆盖它的模块宽度相等为止!</p>
		
		<div id="sidebar">
		
			<div class="module">
				<h2>模块标题</h2>
				<p>这是模块内容,在IE6下,你会发现除第一个模块正常外,其它每往下一个模块文字就住左偏移4个像素</p>
			</div>
		  
		  	<div class="module">
				<h2>模块标题</h2>
				<p>这是模块内容,在IE6下,你会发现除第一个模块正常外,其它每往下一个模块文字就住左偏移4个像素</p>
			</div>
		  
		
		  	<div class="module">
				<h2>模块标题</h2>
				<p>这是模块内容,在IE6下,你会发现除第一个模块正常外,其它每往下一个模块文字就住左偏移4个像素</p>
		  	</div>
		  
		  	<div class="module">
				<h2>模块标题</h2>
				<p>这是模块内容,在IE6下,你会发现除第一个模块正常外,其它每往下一个模块文字就住左偏移4个像素</p>
		  	</div>
		</div>
	</body>
</html>

3.修复bug之后的源码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
	<head>
		<meta http-equiv="content-type" content="text/html; charset=utf-8" />
		<title>文本向左偏移</title>
		<style type="text/css">
			#sidebar {
				width: 200px;
			}
			.module {
				margin: 0 0 15px;
				border: 4px solid pink;
				border-width: 0 4px;
				padding: 2px 10px;
				border-bottom: 1px solid #fff;
			}
			html>body .module {
				border-bottom-width: 0;
			}
			h2 {
				margin: 0.35em 0 0.35em;
				font-size: 120%;
				color: #c00;
			}
			p {
				margin:0 0 .75em;
			}
		</style>
	</head>

	<body>
	
		<p>这种简单的,几乎没有任何样式的实验在<strong>IE5.5和IE6</strong>发现了旧bug,详情请参考<a href="/log/2004/01/30/ie_factor_example.html">这篇日志入口</a>. (IE5.0下是正常的.) 这个bug在连续模块中被一直恶化,直到文本和覆盖它的模块宽度相等为止!</p>
		
		<div id="sidebar">
		
			<div class="module">
				<h2>模块标题</h2>
				<p>这是模块内容,在IE6下,你会发现除第一个模块正常外,其它每往下一个模块文字就住左偏移4个像素</p>
			</div>
		  
		  	<div class="module">
				<h2>模块标题</h2>
				<p>这是模块内容,在IE6下,你会发现除第一个模块正常外,其它每往下一个模块文字就住左偏移4个像素</p>
			</div>
		  
		
		  	<div class="module">
				<h2>模块标题</h2>
				<p>这是模块内容,在IE6下,你会发现除第一个模块正常外,其它每往下一个模块文字就住左偏移4个像素</p>
		  	</div>
		  
		  	<div class="module">
				<h2>模块标题</h2>
				<p>这是模块内容,在IE6下,你会发现除第一个模块正常外,其它每往下一个模块文字就住左偏移4个像素</p>
		  	</div>
		</div>
	</body>
</html>

<think>我们正在处理一个关于SFML绘制文本位置偏移的问题。根据用户提供的引用,特别是引用[1]和引用[4],我们可以知道设置文本位置使用的是`setPosition`函数。文本位置偏移可能是由于文本的坐标原点(origin)和参考点(比如左上角、基准线等)导致的。 在SFML中,文本的绘制默认是以文本的左上角为参考点。但是,文本的基准线(baseline)和字符的上下结构可能会导致视觉上的偏移。此外,文本的位置设置可能没有考虑到文本本身的大小(比如文本的本地边界,local bounds)。 修复方法通常包括: 1. 调整文本的位置,考虑文本的本地边界(local bounds)来重新定位。 2. 设置文本的原点(origin)到合适的位置,比如中心点,然后根据这个原点来设置位置。 具体步骤: ### 步骤1:获取文本的本地边界 在设置文本位置之前,我们可以获取文本的本地边界(local bounds),然后根据边界信息调整位置。 ```cpp sf::FloatRect textRect = text.getLocalBounds(); ``` ### 步骤2:调整文本原点(可选) 如果你希望文本以某个特定点(比如中心)为参考,可以设置原点: ```cpp text.setOrigin(textRect.left + textRect.width/2.0f, textRect.top + textRect.height/2.0f); ``` ### 步骤3:设置文本位置 然后,使用`setPosition`设置文本的位置,此时位置将基于你设置的原点。 ```cpp text.setPosition(x, y); ``` ### 示例 假设我们想要将文本居中在窗口中心,我们可以这样做: ```cpp // 创建文本对象 sf::Text text; text.setFont(font); text.setString("Hello SFML"); text.setCharacterSize(50); text.setFillColor(sf::Color::White); // 获取文本的本地边界 sf::FloatRect textRect = text.getLocalBounds(); // 设置原点为中心 text.setOrigin(textRect.left + textRect.width/2.0f, textRect.top + textRect.height/2.0f); // 设置位置为窗口中心 text.setPosition(window.getSize().x/2.0f, window.getSize().y/2.0f); ``` ### 其他注意事项 1. **字体加载**:确保字体已经正确加载,否则文本将无法正确显示,边界信息也可能不准确。 2. **字符大小**:在设置边界前,确保已经设置了字符大小和字符串内容,因为改变这些属性会影响边界。 3. **边界类型**:`getLocalBounds()`返回的是文本在未应用任何变换情况下的本地边界。如果你对文本进行了缩放或旋转,可能需要使用`getGlobalBounds()`,但通常设置位置时使用本地边界即可。 ### 引用说明 在引用[4]中,我们看到在设置文本位置时,只使用了`setPosition`,而没有考虑文本的边界。这可能是导致偏移的原因之一。因此,通过引入边界计算来调整原点或位置,可以解决偏移问题[^4]。 §§相关问题§§ 1. SFML中如何正确计算文本的宽度和高度? 2. 除了设置原点,还有哪些方法可以解决文本位置偏移? 3. 如何将文本对齐到屏幕的不同位置(如左上角、右下角)?</think>### SFML 文本位置偏移的修复方法 在 SFML 中绘制文本出现位置偏移通常与坐标原点、文本边界框或定位方式有关。以下是系统性的解决方案: #### 1. **检查字体加载**(关键步骤) 确保字体文件正确加载,未加载字体会导致文本无法正确渲染: ```cpp sf::Font font; if (!font.loadFromFile("font.ttf")) { // 处理加载失败 std::cerr << "字体加载失败!" << std::endl; } text.setFont(font); // 必须设置有效字体[^1] ``` #### 2. **调整文本原点**(核心修复) 默认原点在文本左上角,通过设置原点修正偏移: ```cpp sf::Text text; text.setString("示例文本"); text.setCharacterSize(24); // 获取文本边界并设置原点居中 sf::FloatRect bounds = text.getLocalBounds(); text.setOrigin(bounds.width/2, bounds.height/2); // 水平垂直居中 text.setPosition(400, 300); // 此时坐标对应文本中心点 ``` #### 3. **精确计算位置** 当需要对齐时,使用边界框数据精确定位: ```cpp // 右对齐示例 float rightMargin = 800; text.setPosition( rightMargin - bounds.width, // X坐标 text.getPosition().y // Y坐标不变 ); ``` #### 4. **检查渲染顺序** 确保文本在窗口清除(`clear()`)后、显示(`display()`)前绘制: ```cpp window.clear(); window.draw(text); // 正确位置 window.draw(sprite); window.display(); ``` #### 5. **调试边界框** 可视化文本边界帮助诊断: ```cpp // 绘制文本边界框(调试用) sf::RectangleShape border(sf::Vector2f(bounds.width, bounds.height)); border.setPosition(text.getPosition()); border.setFillColor(sf::Color::Transparent); border.setOutlineColor(sf::Color::Red); border.setOutlineThickness(1); window.draw(border); ``` #### 常见问题场景 - **居中偏移**:未设置原点时,`setPosition(center)`会使文本左上角居中而非中心 - **换行错位**:SFML 不会自动换行,需手动处理多行文本位置 - **缩放失真**:避免对文本对象进行缩放,应使用`setCharacterSize()` > 提示:SFML 的文本坐标系统以左上角为原点 (0,0),Y 轴向下为正方向[^4]。对于 UI 元素,建议使用`sf::FloatRect`的`contains()`和`intersects()`方法进行点击检测[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值