提问人:Don McCurdy 提问时间:10/23/2023 最后编辑:Don McCurdy 更新时间:10/26/2023 访问量:47
绘制到“位置:固定”叠加层,与滚动的内联内容对齐
Drawing into a "position: fixed" overlay, aligned with scrolling inline content
问:
我有一个很长的网页,其中包含一些需要 2D 或 3D HTMLCanvasElement 才能显示的内联元素。出于此处不在范围内的性能原因,将 HTMLCanvasElement 放入每个 中是不切实际的,而是我使用单个 HTMLCanvasElement 作为覆盖层。<figure/>
<figure/>
position: fixed
在每一帧(使用)上,我用来查找每个图形相对于窗口的位置和大小,然后绘制到画布叠加层中与其后面重叠的区域。为简单起见,每个数字都只是一个圆圈。requestAnimationFrame
figure.getBoundingClientRect()
<figure/>
当页面是静态的时,这工作正常,但是我在滚动时在不同的浏览器中看到的结果非常不一致。在Firefox中,绘制到画布上的内容与其后面的内联页面完美对齐。在 Chrome 和(有时?Safari 中,绘制到画布上的内容略微滞后于内联页面 - 请参阅演示中,其中圆圈在滚动时不会停留在边框内。
目标:
- 一 (1) 个 HTMLCanvasElement
- 滚动时,叠加内容相对于内嵌图形边框是稳定的
- 在滚动较大的图形时,叠加内容相对于窗口是稳定的(即看不到任何移动)
position: sticky
问题:为什么这在 Chrome 或 Safari 中不起作用,可以使用不同的 CSS 或 JavaScript 实现来修复吗?
滚动过程中的屏幕截图:
const figures = Array.from(document.querySelectorAll('figure'));
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
animate();
function animate() {
requestAnimationFrame(animate);
if (canvas.width !== innerWidth || canvas.height !== innerHeight) {
canvas.width = innerWidth;
canvas.height = innerHeight;
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "crimson";
for (const figure of figures) {
drawFigure(figure);
}
}
function drawFigure(figure) {
const {
left,
top,
width,
height
} = figure.getBoundingClientRect();
if (top > innerHeight) return;
const size = Math.min(width, height) / 2 - 5;
const x = left + width / 2;
const y = top + height / 2;
ctx.beginPath();
ctx.arc(x, y, size, 0, 2 * Math.PI);
ctx.fill();
}
html,
body {
margin: 0;
padding: 0;
background: #eee;
font-family: Courier;
line-height: 1.4em;
}
main {
margin: 2em auto;
max-width: 1024px;
background: #fff;
border-radius: 8px;
padding: 2em;
}
p {
text-indent: 2.5em;
}
figure {
background: mintcream;
border: 5px dashed aquamarine;
margin: 2em;
box-sizing: border-box;
}
figure.inline {
height: 200px;
width: 200px;
margin: 0.5em 2em;
}
figure.inline:nth-of-type(odd) {
float: right;
margin-right: 0;
}
figure.inline:nth-of-type(even) {
float: left;
margin-left: 0;
}
.full {
height: 500vh;
width: 100%;
margin: 0;
position: relative;
}
.full>figure.sticky {
position: sticky;
top: 0;
left: 0;
box-sizing: border-box;
width: 100%;
height: 100vh;
border: 5px dashed crimson;
margin: 0;
}
footer {
font-style: italic;
}
canvas {
position: fixed;
top: 0;
left: 0;
pointer-events: none;
opacity: 0.5;
}
<main>
<h1>Scrolling Inline Content + Fixed Overlay</h1>
<p>
Tart sweet roll jujubes wafer halvah chocolate bar muffin. Pie sweet roll brownie chocolate liquorice oat cake gingerbread. Powder topping shortbread jujubes oat cake shortbread jelly. Macaroon chupa chups sweet roll danish powder carrot cake tart bonbon.
Sweet gummies chocolate bar sugar plum chocolate lollipop sweet. Caramels marshmallow sugar plum apple pie tart soufflé biscuit halvah tart. Topping danish toffee chocolate pastry. Shortbread donut oat cake chocolate bar biscuit marshmallow macaroon
wafer. Danish chocolate bar cupcake marzipan jelly beans wafer. Bear claw jelly toffee topping cotton candy pudding oat cake bonbon. Caramels powder brownie donut carrot cake cake ice cream. Jelly chocolate bar dragée gingerbread cotton candy fruitcake
shortbread. Soufflé cake danish fruitcake fruitcake cake marzipan.
</p>
<p>
Cheesecake sweet sweet cookie soufflé jelly beans. Caramels chupa chups chocolate cake shortbread cupcake donut muffin macaroon croissant. Brownie sweet chupa chups sweet roll toffee. Tiramisu marzipan liquorice candy powder pudding toffee wafer sesame
snaps. Powder lollipop cake toffee chupa chups. Halvah dragée shortbread cookie ice cream. Lemon drops bear claw muffin powder gummies tootsie roll powder gummi bears. Toffee sweet cake gingerbread tootsie roll marzipan lollipop jelly-o pudding. Cake
cake sugar plum pie tiramisu chocolate cake jelly beans candy canes oat cake. Cupcake chocolate wafer powder powder. Tiramisu topping sweet ice cream sugar plum candy canes danish pudding. Fruitcake candy canes chocolate cake oat cake croissant cookie.
Cake pie lemon drops ice cream apple pie cookie marzipan tiramisu caramels.
</p>
<figure class="inline"></figure>
<p>
Fruitcake topping cookie soufflé toffee candy bonbon. Powder sweet gummi bears ice cream pudding halvah tootsie roll tart dragée. Danish tootsie roll jelly beans bear claw chocolate cake cheesecake gingerbread tiramisu oat cake. Chocolate bar candy canes
shortbread donut jujubes bear claw. Tootsie roll toffee soufflé liquorice marshmallow. Powder cotton candy marzipan soufflé macaroon dragée lollipop chocolate bar gingerbread. Oat cake chocolate cake jelly beans cotton candy pudding. Tiramisu candy
canes jelly-o croissant brownie. Chocolate bar icing fruitcake sesame snaps powder.
</p>
<p>
Halvah cookie cheesecake donut lollipop pudding candy tart. Gummies biscuit dragée cotton candy chocolate cake toffee lemon drops. Chocolate bar oat cake gummi bears tart toffee gingerbread sugar plum donut jelly-o. Apple pie pastry sugar plum jujubes
lollipop candy sesame snaps lemon drops caramels. Carrot cake pie oat cake powder dragée chocolate cake sweet roll marzipan. Lollipop lollipop tiramisu bonbon pudding tootsie roll. Dessert caramels sweet sugar plum cheesecake cake. Dragée cookie cake
pastry candy.
</p>
<figure class="inline"></figure>
<p>
Oat cake chocolate bar donut cotton candy soufflé halvah. Biscuit jujubes ice cream brownie cheesecake brownie dragée lollipop dragée. Dragée sweet powder shortbread croissant croissant sweet roll cheesecake. Wafer marshmallow cheesecake jujubes tootsie
roll bonbon croissant carrot cake. Chocolate shortbread shortbread cheesecake pie chocolate sweet. Sweet roll chupa chups candy muffin macaroon topping cake. Candy icing donut shortbread macaroon fruitcake tart muffin. Caramels candy canes sweet pie
cheesecake. Topping powder soufflé chocolate cake liquorice powder danish.
</p>
<p>
Macaroon dessert gummies cake tiramisu candy chocolate. Cookie powder donut jelly beans ice cream dragée pie. Marshmallow fruitcake macaroon icing jujubes croissant. Candy canes topping dessert candy canes apple pie pie cake. Tiramisu caramels tiramisu
brownie croissant. Chocolate cake marshmallow apple pie candy danish shortbread jujubes chupa chups caramels. Wafer chupa chups candy canes fruitcake biscuit fruitcake gingerbread pudding.
</p>
<p>
Jelly beans danish danish chupa chups cookie cheesecake powder. Danish lemon drops gingerbread chupa chups cheesecake macaroon danish tart sweet roll. Biscuit jelly beans gummi bears sesame snaps liquorice halvah wafer. Gingerbread halvah cotton candy
apple pie carrot cake sweet roll gingerbread pastry. Jelly beans sesame snaps tootsie roll cupcake chocolate bar chocolate cake sesame snaps. Carrot cake powder cake ice cream ice cream chocolate cake. Carrot cake gummies biscuit powder cake shortbread.
Tiramisu liquorice bonbon jelly-o danish tootsie roll lollipop brownie brownie. Carrot cake jelly-o danish bear claw tootsie roll sesame snaps caramels pie gummies.
</p>
<div class="full">
<figure class="sticky"></figure>
</div>
<p>
Chocolate bar shortbread jelly-o cake pastry cake chocolate cake. Pudding pastry caramels sweet bear claw marshmallow bear claw. Sesame snaps gummies topping brownie macaroon pastry. Dragée macaroon danish apple pie chocolate bar shortbread muffin. Dessert
jelly apple pie biscuit dessert. Tart chocolate sugar plum cheesecake topping. Pastry toffee donut candy canes marshmallow cake lemon drops. Cotton candy cake tart carrot cake topping tart cake gummi bears cake. Brownie sweet croissant jujubes sweet
roll jelly beans jelly fruitcake cupcake. Tart danish danish jujubes pastry tiramisu tart dragée dessert.
</p>
<figure class="inline"></figure>
<p>
Croissant powder danish muffin sugar plum gingerbread cake chocolate cake. Chocolate cake biscuit wafer tootsie roll marshmallow sesame snaps soufflé pudding. Bonbon pie oat cake shortbread cheesecake ice cream. Chupa chups oat cake caramels cupcake chocolate.
Carrot cake candy canes wafer soufflé chocolate bar cake jelly beans. Caramels lollipop jelly beans marzipan gingerbread brownie marshmallow. Candy canes ice cream gummi bears candy ice cream chocolate bar ice cream. Sugar plum danish fruitcake biscuit
cheesecake chocolate bar.
</p>
<p>
Carrot cake powder brownie gummi bears marzipan carrot cake. Tootsie roll cake gummies dragée chupa chups oat cake tart. Dragée lemon drops cake icing jelly beans cookie chocolate cake. Biscuit sweet roll sesame snaps tart pudding jelly ice cream. Fruitcake
danish tootsie roll marshmallow fruitcake halvah. Cake lemon drops carrot cake chocolate cake bonbon sweet carrot cake caramels.
</p>
<p>
Biscuit pudding macaroon cookie muffin jelly. Candy canes lollipop dragée sweet carrot cake candy cotton candy. Sweet roll dragée dragée cheesecake sweet gingerbread oat cake danish. Shortbread jelly-o cake bear claw gummi bears sesame snaps. Shortbread
pastry liquorice tiramisu bonbon. Lollipop gingerbread gummi bears sweet liquorice gummies shortbread biscuit sweet. Fruitcake donut chocolate cake wafer danish. Chocolate fruitcake powder bonbon tiramisu lollipop.
</p>
<p>
Chocolate cake chocolate candy liquorice liquorice jelly beans carrot cake candy canes cheesecake. Lollipop chocolate bar gummi bears candy canes chocolate cake oat cake halvah bonbon. Cupcake biscuit biscuit halvah brownie candy oat cake lollipop. Gummi
bears sweet pastry marshmallow jujubes donut lollipop candy dragée. Oat cake carrot cake donut halvah dragée biscuit brownie gummies. Liquorice chupa chups sweet candy canes chocolate cake. Croissant cupcake bonbon gingerbread sweet lemon drops tootsie
roll. Macaroon cake chupa chups sweet jelly beans sesame snaps bonbon cotton candy ice cream. Dessert marzipan lemon drops muffin chocolate liquorice. Chupa chups biscuit bear claw bear claw liquorice sugar plum fruitcake. Gummi bears donut chocolate
shortbread chocolate bar halvah gingerbread. Cotton candy cheesecake croissant donut jelly jelly. Chocolate sweet roll fruitcake ice cream muffin chupa chups croissant. Sugar plum jujubes cupcake cotton candy marshmallow sesame snaps dragée candy.
</p>
<hr>
<footer>
Filler text by <a href="https://cupcakeipsum.com/">Cupcake Ipsum</a>.
</footer>
</main>
<canvas></canvas>
答:
注意:我正在发布我自己的问题的解决方案,但会暂时保持开放和“未回答”,希望其他人能想出更好的解决方案,或者解释为什么会发生这种情况!谢谢。
我已经解决了这个问题,将其分为两种情况并使用 JavaScript 在它们之间切换。
- 没有人物占据全屏高度。使用 ,更新每一帧,使画布相对于文档正文及其内联内容保持固定。现在,在滚动过程中,视口会稍微远离画布,因此我们将画布扩展 100px 作为缓冲区。
position: absolute
top: XXpx
- 至少有一个图形占据整个屏幕高度。用于防止图形在滚动过程中相对于视口移动。
position: sticky; top: 0;
就我而言,这两种情况是相互排斥的。当我们在两者之间过渡时,画布上仍然有一个小的转变,但它比原来的问题要明显得多。
对画布的更新工作如下:
if (figures.some(isFullWindow)) {
canvas.style.position = 'fixed';
canvas.style.top = (-PAD) + 'px';
canvas.style.left = (-PAD) + 'px';
} else {
canvas.style.position = 'absolute';
canvas.style.top = (window.scrollY - PAD) + 'px';
canvas.style.left = (-PAD) + 'px';
}
function isFullWindow(figure) {
const {top, bottom} = figure.getBoundingClientRect();
const _isFullView = top <= 0 && bottom >= innerHeight;
return _isFullView;
}
画布周围需要一个额外的容器来支持模式。position: sticky
上一个:HTML/CSS 对齐问题
评论
requestAnimationFrame
scroll-behavior
scroll-behavior: smooth;