【问题标题】:Resizing window on CodePen is causing scrollbar to appear on full screen canvas在 CodePen 上调整窗口大小导致滚动条出现在全屏画布上
【发布时间】:2020-08-07 07:57:33
【问题描述】:

我有一个奇怪的问题,它以前工作过,问题出在 CodePen 上。我有全尺寸的画布:

function width() {
  // why -1 ?
  // without this there is horizontal scrollbar
  // I have no idea what is causing this
  return window.innerWidth - 1;
}

// ---------------------------------------------------------------
function height() {
  return window.innerHeight;
}

var canvas = document.getElementsByTagName('canvas')[0];
canvas.width = width();
canvas.height = height();

我不确定是什么原因造成的,但如您所见,我已将 -1 添加到宽度,否则会出现水平滚动条。我认为它以前可以工作,它发生在 GNU/Linux Chrome 上。

画布上有display: block,你可以在Matrix Rain Demo看到代码,它在调试模式下工作正常。

这是 CodePen 的问题吗,任何人都知道为什么这个 1px。

这在 StackSnippets 中运行良好:

function width() {
  return window.innerWidth;
}

// ---------------------------------------------------------------
function height() {
  return window.innerHeight;
}

var canvas = document.getElementsByTagName('canvas')[0];
canvas.width = width();
canvas.height = height();
canvas {
  display: block;
}
body {
  margin: 0;
}
<canvas></canvas>

编辑:

问题只出现在某些窗口上。要看到你需要慢慢调整大小。对于我的(我有全高清笔记本电脑),它出现在例如:1594 但在 1595 工作。如果我使用 -1,滚动条在没有它的情况下永远不会出现,它会闪烁它以某些宽度显示。

确切地说浏览器和操作系统我有 Fedora 32 和谷歌 Chrome 稳定版(刚刚更新到 84.0.4147.105 (Official version) (64-bit)

EDIT2:

我的演示可以在 Stack Snippet 中运行,无需修复我的演示:

var katagana = gen_unicode(0x30A1, 0x30F6);
var hiragana = gen_unicode(0x3041, 0x3096);

// ---------------------------------------------------------------
class Matrix {
  constructor(canvas, { font_size = 14, width, height } = {}) {
    this._canvas = canvas;
    this._ctx = canvas.getContext('2d');
    this._font_size = font_size;
    this._drops = [];
    this._columns = Math.floor(width / font_size);
    this._chars = katagana.concat(hiragana);
    this.resize(width, height);
  }
  random_char() {
    return rnd(this._chars);
  }
  render_char(char, x, y) {
    this._ctx.fillText(char, x, y);
  }
  start() {
    let frames = 0;
    this._run = true;
    const self = this;
    (function loop() {
      if (frames++ % 2 === 0) {
        self.render(); // slower render
      }
      if (self._run) {
        requestAnimationFrame(loop);
      }
    })()
  }
  stop() {
    this._run = false;
  }
  reset() {
    for (let x = 0; x < this._columns; x++) {
      this._drops[x] = 255;
    }
  }
  resize(width, height) {
    this._width = width;
    this._height = height;
    this._canvas.height = height;
    this._canvas.width = width;
    this.reset();
  }
  clear() {
    this._ctx.fillStyle = 'rgba(0, 0,0,0.05)';
    this._ctx.fillRect(0, 0, this._width, this._height);
    this._ctx.fillStyle = '#0F0';
    this._ctx.font = this._font_size + "px monospace";
  }
  render() {
    this.clear();
    for (let col = 0; col < this._drops.length; col++) {
      const char = this.random_char();
      const x = col * this._font_size;
      const y = this._drops[col] * this._font_size;
      this.render_char(char, x, y);
      if (y > this._height && Math.random() > .975) {
        this._drops[col] = 0;
      }
      this._drops[col]++;
    }
  }
}

// ---------------------------------------------------------------
// :: Init code
// ---------------------------------------------------------------
var canvas = document.getElementsByTagName('canvas')[0];

const matrix = new Matrix(canvas, {
  font_size: 14,
  width: width(),
  height: height()
});

matrix.start();

window.addEventListener('resize', e => {
  matrix.resize(width(), height());
});

// ---------------------------------------------------------------
// :: Utils
// ---------------------------------------------------------------
function gen_unicode(start, end) {
  var chars = [];
  for (var i = start; i <= end; ++i) {
    chars.push(String.fromCharCode(i));
  }
  return chars;
}

// ---------------------------------------------------------------
function rnd(array) {
  return array[Math.floor(Math.random() * array.length)]
}

// ---------------------------------------------------------------
function width() {
  // why -1 ?
  // without this there is horizontal scrollbar
  // I have no idea what is causing this
  return window.innerWidth;
}

// ---------------------------------------------------------------
function height() {
  return window.innerHeight;
}
body {
  background: black;
  margin: 0;
  min-width: 100vw;
  min-height: 100vh;
}
canvas {
  display: block;
  margin: 0;
}
&lt;canvas&gt;&lt;/canvas&gt;

编辑: 1px 不是不管有没有它都会发生的修复。

【问题讨论】:

  • 在codepen上也很好(至少对我来说)
  • @TemaniAfif 可能与我的浏览器有关。我有待更新。重启后如果正常会重启并删除。
  • @TemaniAfif 对我来说重启后还是一样。
  • 然后提供有关您的浏览器版本的更多详细信息
  • @TemaniAfif 我已经更新了这个问题,可能是浏览器错误,因为它只出现在某些窗口宽度上。

标签: html css canvas iframe codepen


【解决方案1】:

这可能无法解决您的问题,但这里有一个不同的想法,以避免在调整大小时刷新画布。您只需使用大宽度/高度属性并考虑object-fit 以避免失真(相关:How does object-fit work with canvas element?

var katagana = gen_unicode(0x30A1, 0x30F6);
var hiragana = gen_unicode(0x3041, 0x3096);

// ---------------------------------------------------------------
class Matrix {
  constructor(canvas, { font_size = 14} = {}) {
    this._canvas = canvas;
    this._ctx = canvas.getContext('2d');
    this._font_size = font_size;
    this._drops = [];
    this._columns = Math.floor(2000 / font_size);
    this._chars = katagana.concat(hiragana);
    this._width = 2000;
    this._height = 2000;
    this.reset();
  }
  random_char() {
    return rnd(this._chars);
  }
  render_char(char, x, y) {
    this._ctx.fillText(char, x, y);
  }
  start() {
    let frames = 0;
    this._run = true;
    const self = this;
    (function loop() {
      if (frames++ % 2 === 0) {
        self.render(); // slower render
      }
      if (self._run) {
        requestAnimationFrame(loop);
      }
    })()
  }
  stop() {
    this._run = false;
  }
  reset() {
    for (let x = 0; x < this._columns; x++) {
      this._drops[x] = 255;
    }
  }
  clear() {
    this._ctx.fillStyle = 'rgba(0, 0,0,0.05)';
    this._ctx.fillRect(0, 0, this._width, this._height);
    this._ctx.fillStyle = '#0F0';
    this._ctx.font = this._font_size + "px monospace";
  }
  render() {
    this.clear();
    for (let col = 0; col < this._drops.length; col++) {
      const char = this.random_char();
      const x = col * this._font_size;
      const y = this._drops[col] * this._font_size;
      this.render_char(char, x, y);
      if (y > this._height && Math.random() > .975) {
        this._drops[col] = 0;
      }
      this._drops[col]++;
    }
  }
}

// ---------------------------------------------------------------
// :: Init code
// ---------------------------------------------------------------
var canvas = document.getElementsByTagName('canvas')[0];

const matrix = new Matrix(canvas, {
  font_size: 14
});

matrix.start();

// ---------------------------------------------------------------
// :: Utils
// ---------------------------------------------------------------
function gen_unicode(start, end) {
  var chars = [];
  for (var i = start; i <= end; ++i) {
    chars.push(String.fromCharCode(i));
  }
  return chars;
}

// ---------------------------------------------------------------
function rnd(array) {
  return array[Math.floor(Math.random() * array.length)]
}
body {
  background: black;
  margin: 0;
  height:100vh;
}
canvas {
  width:100%;
  height:100%;
  display:block;
  object-fit:none;
  object-position:top left;
}
&lt;canvas width="2000" height="2000"&gt;&lt;/canvas&gt;

【讨论】:

  • 如果屏幕大于 2000 像素会怎样。另外,在手机上渲染 2000px 会有点过分吗?顺便说一句:我问的是 1px 错误而不是调整大小,我正在为错误报告创建可重现的示例。
  • @jcubic 1px 错误肯定是由于调整大小功能和您动态设置的宽度/高度。我提供了一种替代方法来避免所有这些并使用静态宽度/高度(它对其他人可能会有所帮助)
  • 正如您从堆栈 sn-p 中看到的那样,这仅在 CodePen 上发生,它在堆栈 sn-p 上工作正常,因此您的示例无法解决任何问题,因为我的 Matrix Rain 在堆栈 sn-p 中工作正常。
  • 不,我不想在移动设备上运行固定的 2000x2000 画布。很好的例子,但对我没有用。
【解决方案2】:

在 CodePen 博客 Full Screen Canvas 上找到 Chris Coyier 的这篇旧文章

解决方案是:

function resizeCanvas() {
  can.style.width = window.innerWidth + "px";
  setTimeout(function() {
    can.style.height = window.innerHeight + "px";
  }, 0);
}

这与:

function resizeCanvas() {
  canvas.width = window.innerWidth;
  setTimeout(function() {
    canvas.height = window.innerHeight;
  }, 0);
}

解决方案是也使用以下方法隐藏滚动条:

body {
  margin: 0;
  overflow: hidden;
}

【讨论】:

    猜你喜欢
    • 2020-06-09
    • 1970-01-01
    • 2021-04-06
    • 2014-05-05
    • 1970-01-01
    • 1970-01-01
    • 2013-09-17
    • 2021-04-27
    • 1970-01-01
    相关资源
    最近更新 更多