滚动开始时的图像跳跃

Image jumping at the beginning of scrolling

本文关键字:跳跃 图像 开始时 滚动      更新时间:2023-09-26

我写了一些代码来放大我的图像,但当我在一开始滚动时,这张图片会有点跳跃。如何解决问题?

完整页面视图。

编辑器视图。

HTML

<canvas id="canvas"></canvas>

JS

function draw(scroll) {
  scroll = (window.scrollY || window.pageYOffset) / (document.body.clientHeight - window.innerHeight) * 3000;
  canvas.setAttribute('width', window.innerWidth);
  canvas.setAttribute('height', window.innerHeight);
//The main formula that draws and zooms the picture
  drawImageProp(ctx, forest, 0, (-scroll * 3.9) / 4, canvas.width, canvas.height + (scroll * 3.9) / 2);
}

不是错误修复

我看了一下Codepen的例子,它确实跳到了顶部(有时)。我有一个修复程序,但我没有时间找到你的代码问题的来源。我确实注意到跳跃涉及到一个方面的变化,所以它一定是在缩放你的错误。(注意负面)

GPU是更好的裁剪器

此外,您的代码实际上正在做不必要的工作,因为您正在计算图像剪切区域。Canvas context可以为您进行剪裁,尤其擅长剪裁图像。即使提供了片段区域,图像仍将通过片段,因为片段是渲染管道的一部分。你唯一应该关心的是图像的剪辑显示是图像的任何部分是否可见,这样你就不会发送绘图调用,而且只有当你按下图像渲染计数(即游戏精灵计数500+)时,这才是真正重要的

代码示例

不管怎样,我离题了。下面是我的代码。您可以添加制衡。(论点审查、缩放最大最小值等)。

调用功能

  // get a normalised scale 0-1 from the scroll postion
  var scale = (window.scrollY || window.pageYOffset) / (document.body.clientHeight - window.innerHeight);
  // call the draw function 
  // scale 0-1 where 0 is min scale and 1 is max scale (min max determined in function
  // X and y offset are clamped but are ranged
  // 0 - image.width and 0 - image.height
  // where 0,0 shows top left and width,height show bottom right
  drawImage(ctx, forest, scale, xOffset, yOffset);

函数

评论应该涵盖您需要了解的内容。你会注意到,我所关心的只是图像应该有多大以及左上角的位置。GPU会为你进行剪辑,并且不会花费你的处理时间(即使是未加速的显示器)。我个人喜欢使用归一化值0-1,这是一项额外的工作,但我的大脑喜欢它的简单性,它也减少了对幻数的需求(幻数是代码不适应性的标志)。功能适用于任何尺寸的显示器和任何尺寸的图像。哦,我喜欢除法而不是乘法,(这是一个糟糕的编码习惯,源于良好的数学习惯)用* 0.5替换/ 2和所需的括号将使其更具可读性。

function drawImage(ctx, img, scale, x, y){
  const MAX_SCALE = 4;
  const MIN_SCALE = 1;
  var w = canvas.width; // set vars just for source clarity
  var h = canvas.height;
  var iw = img.width;
  var ih = img.height;
  var fit = Math.max(w / iw, h / ih); // get the scale to fill the avalible display area
  // Scale is a normalised value from 0-1 as input arg Convert to range
  scale = (MAX_SCALE - MIN_SCALE) * scale + MIN_SCALE; 
  var idw = iw * fit * scale; // get image total display size;
  var idh = ih * fit * scale;
  x /= iw; // normalise offsets
  y /= ih; //
  x = - (idw - w) * x;  // transform offsets to display coords
  y = - (idh - h) * y;
  x = Math.min( 0, Math.max( - (idw - w), x) ); // clamp image to display area
  y = Math.min( 0, Math.max( - (idh - h), y) ); 
  // use set transform to scale and translate
  ctx.setTransform(scale, 0, 0, scale, idw / 2 + x, idh / 2 + y);  
  // display the image to fit;
  ctx.drawImage(img, ( - iw / 2 ) * fit, (- ih / 2 ) * fit);
  // restore transform.
  ctx.setTransform(1, 0, 0, 1, 0, 0)
}

很抱歉我没有直接解决这个问题,但希望这能帮助你重新设计你的方法。

我最近添加了一个类似的答案,涉及用鼠标缩放和平移(以及旋转),你可能对如何平移画布感兴趣?它有点乱,仍然是"自我提醒(我把它清理干净)",并且没有边界夹紧。但展示了如何设置缩放原点,以及如何从屏幕空间转换为世界空间。(查找屏幕像素在平移/缩放/旋转显示器上的位置)。

祝你的项目好运。