这个想法是你的元素与文本和canvas
元素是一个在另一个之上。您将文本保留在元素中(以便允许文本选择,这对于文本来说是不可能的canvas
),但使其完全透明(使用rgba(0,0,0,0)
, 以使文本在 IE8 和更早版本中可见 - 那是因为您没有RGBa
支持并且不canvas
支持 IE8 及更早版本)。
然后,您读取元素内的文本并使用相同的字体属性将其写在画布上,这样您在画布上写的每个字母都会覆盖元素中带有文本的相应字母。
该canvas
元素不支持多行文本,因此您必须将文本分解为单词,然后继续在测试行上添加单词,然后进行测量。如果测试线的宽度大于一条线的最大允许宽度(通过读取计算出的带有文本的元素的宽度来获得最大允许宽度),那么你将它写在画布上而不用添加最后一个单词,您将测试行重置为最后一个单词,并将写入下一行的 y 坐标增加一个行高(您也可以从元素与文本的计算样式中获得)。对于您编写的每一行,您还可以通过适当的步骤降低文本的不透明度(此步骤与每行的平均字符数成反比)。
在这种情况下,你不能轻易做的是证明文本的合理性。它可以完成,但它变得有点复杂,这意味着您必须计算每个步骤的宽度并逐字而不是逐行编写文本。
另外,请记住,如果您的文本容器在调整窗口大小时改变了宽度,那么您必须在每次调整大小时清除画布并在其上重新绘制文本。
好的,代码:
HTML:
<article>
<h1>Interacting Spiral Galaxies NGC 2207/ IC 2163</h1>
<em class='timestamp'>February 4, 2004 09:00 AM</em>
<section class='article-content' id='art-cntnt'>
<canvas id='c' class='c'></canvas>In the direction of <!--and so on-->
</section>
</article>
CSS:
html {
background: url(moving.jpg) 0 0;
background-size: 200%;
font: 100%/1.3 Verdana, sans-serif;
animation: ani 4s infinite linear;
}
article {
width: 50em; /* tweak this ;) */
padding: .5em;
margin: 0 auto;
}
.article-content {
position: relative;
color: rgba(0,0,0,0);
/* add slash at the end to check they superimpose *
color: rgba(255,0,0,.5);/**/
}
.c {
position: absolute;
z-index: -1;
top: 0; left: 0;
}
@keyframes ani { to { background-position: 100% 0; } }
JavaScript:
var wrapText = function(ctxt, s, x, y, maxWidth, lineHeight) {
var words = s.split(' '), line = '',
testLine, metrics, testWidth, alpha = 1,
step = .8*maxWidth/ctxt.measureText(s).width;
for(var n = 0; n < words.length; n++) {
testLine = line + words[n] + ' ';
metrics = ctxt.measureText(testLine);
testWidth = metrics.width;
if(testWidth > maxWidth) {
ctxt.fillStyle = 'rgba(0,0,0,'+alpha+')';
alpha -= step;
ctxt.fillText(line, x, y);
line = words[n] + ' ';
y += lineHeight;
}
else line = testLine;
}
ctxt.fillStyle = 'rgba(0,0,0,'+alpha+')';
alpha -= step;
ctxt.fillText(line, x, y);
return y + lineHeight;
}
window.onload = function() {
var c = document.getElementById('c'),
ac = document.getElementById('art-cntnt'),
/* use currentStyle for IE9 */
styles = window.getComputedStyle(ac),
ctxt = c.getContext('2d'),
w = parseInt(styles.width.split('px')[0], 10),
h = parseInt(styles.height.split('px')[0], 10),
maxWidth = w,
lineHeight = parseInt(styles.lineHeight.split('px')[0], 10),
x = 0,
y = parseInt(styles.fontSize.split('px')[0], 10),
text = ac.innerHTML.split('</canvas>')[1];
c.width = w;
c.height = h;
ctxt.font = '1em Verdana, sans-serif';
wrapText(ctxt, text, x, y, maxWidth, lineHeight);
};