Почему эта пиксельная анимация весела - PullRequest
1 голос
/ 05 июня 2019

У меня есть следующая многоступенчатая анимация пикселизации.Он очень медленно анимируется от низкой к высокой пикселизации, чтобы показать вам, что он встряхивает между некоторыми шагами, как будто изображение слегка перемещается между визуализациями.Я не могу понять, почему это происходит или как заставить его выглядеть так, как будто изображение находится в одном месте.

var c = document.createElement('canvas')
c.style.display = 'flex'
c.style.width = '100vw'
c.style.height = '100vh'
c.style['image-rendering'] = 'pixelated'
document.body.appendChild(c)

var x = c.getContext('2d')

x.webkitImageSmoothingEnabled = false
x.mozImageSmoothingEnabled = false
x.msImageSmoothingEnabled = false
x.imageSmoothingEnabled = false

var src = c.getAttribute('data-draw')
var small = `https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/M101_hires_STScI-PRC2006-10a.jpg/307px-M101_hires_STScI-PRC2006-10a.jpg`
var large = `https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/M101_hires_STScI-PRC2006-10a.jpg/1280px-M101_hires_STScI-PRC2006-10a.jpg`

// c.width = c.clientWidth
// c.height = c.clientHeight

var stack = []
var start = false
var place = 0

function queue(image, ratio, width, height) {
  stack.push({ image, ratio, width, height })

  if (start) return
  start = true

  setTimeout(proceed, 0)
}

function proceed() {
  let point = stack.shift()
  let w
  let h

  if (point.ratio) {
    w = c.width = c.clientWidth * point.ratio
    h = c.height = c.clientHeight * point.ratio
  } else {
    w = point.width
    h = point.height
  }

  if (!stack.length) {
    x.webkitImageSmoothingEnabled = true
    x.mozImageSmoothingEnabled = true
    x.msImageSmoothingEnabled = true
    x.imageSmoothingEnabled = true
    c.classList.remove('px')
  }

  drawImageProp(x, point.image, 0, 0, w, h)

  if (stack.length) {
    setTimeout(proceed, 1000)
  }
}

var s = new Image()
s.onload = function(){
  queue(s, 0.01)
  queue(s, 0.03)

  var i = new Image()
  i.onload = function(){
    queue(i, 0.03)
    queue(i, 0.11)
    queue(i, 1)
  }
  i.src = large
}
s.src = small

function drawImageProp(ctx, img, x, y, w, h, offsetX, offsetY) {
  if (arguments.length === 2) {
      x = y = 0;
      w = ctx.canvas.width;
      h = ctx.canvas.height;
  }

  // default offset is center
  offsetX = typeof offsetX === "number" ? offsetX : 0.5;
  offsetY = typeof offsetY === "number" ? offsetY : 0.5;

  // keep bounds [0.0, 1.0]
  if (offsetX < 0) offsetX = 0;
  if (offsetY < 0) offsetY = 0;
  if (offsetX > 1) offsetX = 1;
  if (offsetY > 1) offsetY = 1;

  var iw = img.width,
      ih = img.height,
      r = Math.min(w / iw, h / ih),
      nw = iw * r,   // new prop. width
      nh = ih * r,   // new prop. height
      cx, cy, cw, ch, ar = 1;

  // decide which gap to fill
  if (nw < w) ar = w / nw;
  if (Math.abs(ar - 1) < 1e-14 && nh < h) ar = h / nh;  // updated
  nw *= ar;
  nh *= ar;

  // calc source rectangle
  cw = iw / (nw / w);
  ch = ih / (nh / h);

  cx = (iw - cw) * offsetX;
  cy = (ih - ch) * offsetY;

  // make sure source rectangle is valid
  if (cx < 0) cx = 0;
  if (cy < 0) cy = 0;
  if (cw > iw) cw = iw;
  if (ch > ih) ch = ih;

  // fill image in dest. rectangle
  ctx.drawImage(img, cx, cy, cw, ch,  x, y, w, h);
}

Даже между двумя последними шагами он немного сдвигается.Хотите знать, что идет не так и как это исправить.

К вашему сведению, есть два изображения, маленькое и большое, и то же самое.Сначала загружается маленькое изображение с низким разрешением, а затем загружается большое.Пока загружается большой, он выполняет несколько шагов анимации, используя маленькое изображение для запуска анимации.Затем, когда закончится большой, он выбирает, где остановился маленький, и делает еще несколько шагов анимации, используя большое изображение.

...