javascript - Canvas 图像旋转性能

标签 javascript performance canvas

有助于可视化代码的图像

enter image description here

问题

有什么方法可以使下面的代码性能更高吗?当只渲染图像的可见部分而不是整个图像时,我觉得我错过了一些东西。

代码

// ------------
// Setup canvas
// ------------

let rotation = 0;
const ratio = window.devicePixelRatio || 1;
const canvas = document.createElement('canvas');
document.body.appendChild(canvas);
canvas.width = canvas.clientWidth * ratio;
canvas.height = canvas.clientHeight * ratio;
const context = canvas.getContext('2d');
context.scale(ratio, ratio);

// ----------
// Load image
// ----------

let imageReady = false;
const image = new Image();
      image.onload = () => {
        imageReady = true;
      }
      image.src = 'https://i.imgur.com/ltOYsck.png';

// --------------
// Animation Loop
// --------------

window.requestAnimationFrame(loop)

function loop() {
  context.clearRect(0,0,canvas.width, canvas.height);

  if (imageReady === true) {
    context.save();
    context.translate(canvas.clientWidth/2, canvas.clientHeight/2 + 1000)
    context.rotate(rotation * Math.PI / 180);
    context.drawImage(
      image,
      0,
      0,
      image.width,
      image.height,
      -image.width/4,
      -image.height/4,
      image.width * 0.5,
      image.height * 0.5
    );
    context.restore();
  }

  rotation += 0.1;
  if(rotation >= 360) rotation = 0;

  window.requestAnimationFrame(loop)
}
canvas {
  width: 1200px;
  height: 200px;
  background: lightgreen;
}

最佳答案

这个“答案”没有回答你关于你的代码的问题,因为我认为这首先是错误的方法......

I'm trying to achieve an effect with 4-5 canvases over each other all spinning at different speeds However after 5 layers the CPU usage in Chrome goes through the roof (from 9% to 70%).

...但它包含一个示例,可以毫无问题地旋转 50 图层。 ~10%CPU 和~15%GPU;在笔记本电脑上

The reason for the large images is because I want it to look crisp on Retina devices, so everything is twice as big as it needs to be (4400 x 4400)

尤其是当您想要清晰的图像时,请避免使用像素图形。您使用的图像非常适合将其转换为矢量。

4400x4400 像素意味着 4400x4400x4 字节(~73MB)的原始图像数据,每次渲染该图像(的一部分)时,JS 都必须处理这些数据。

/*
  // set random rotation speeds for each layer; and a bit more.
  // code is commented out, because at the moment this is defined in the CSS
  let i=1;
  for(let elm of document.querySelectorAll('#example>g')){
    // give this particular elm an initial rotation and add a little scale to it
    const sx = (Math.random() * .2 + .8).toFixed(4);
    const sy = (Math.random() * .2 + .8).toFixed(4);
    const rotate = Math.floor(Math.random() * 360);

    const transform = `scale(${sx},${sy})rotate(${rotate}deg)`;
    const duration = Math.floor(Math.random() * 25000 + 5000) + "ms";

    elm.style.setProperty("transform", transform);
    elm.style.setProperty("animation-duration", duration);

    console.log(`#example>g:nth-child(${i++}){animation-duration:${duration};transform:${transform}}`);
  }
*/
@keyframes rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

#example>g>use {
  animation-name: rotate;
  animation-duration: inherit;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  fill: rgba(64, 64, 64, .25);
}

/* the following CSS has been generated by the JS */
#example>g:nth-child(1){animation-duration:6235ms;transform:scale(0.9831,0.9672)rotate(317deg)}
#example>g:nth-child(2){animation-duration:27794ms;transform:scale(0.9849,0.8447)rotate(290deg)}
#example>g:nth-child(3){animation-duration:9000ms;transform:scale(0.8721,0.8287)rotate(149deg)}
#example>g:nth-child(4){animation-duration:13234ms;transform:scale(0.8428,0.8676)rotate(198deg)}
#example>g:nth-child(5){animation-duration:26854ms;transform:scale(0.9927,0.9902)rotate(136deg)}
#example>g:nth-child(6){animation-duration:20110ms;transform:scale(0.9047,0.8027)rotate(158deg)}
#example>g:nth-child(7){animation-duration:23603ms;transform:scale(0.9949,0.8478)rotate(32deg)}
#example>g:nth-child(8){animation-duration:27045ms;transform:scale(0.8898,0.8352)rotate(166deg)}
#example>g:nth-child(9){animation-duration:24821ms;transform:scale(0.8344,0.9232)rotate(127deg)}
#example>g:nth-child(10){animation-duration:11986ms;transform:scale(0.8612,0.8307)rotate(232deg)}
#example>g:nth-child(11){animation-duration:7464ms;transform:scale(0.8422,0.9567)rotate(175deg)}
#example>g:nth-child(12){animation-duration:6435ms;transform:scale(0.9263,0.8725)rotate(330deg)}
#example>g:nth-child(13){animation-duration:29691ms;transform:scale(0.9359,0.9489)rotate(260deg)}
#example>g:nth-child(14){animation-duration:12935ms;transform:scale(0.8948,0.9912)rotate(107deg)}
#example>g:nth-child(15){animation-duration:21544ms;transform:scale(0.8496,0.9085)rotate(120deg)}
#example>g:nth-child(16){animation-duration:16241ms;transform:scale(0.9520,0.8554)rotate(111deg)}
#example>g:nth-child(17){animation-duration:23578ms;transform:scale(0.8677,0.9682)rotate(234deg)}
#example>g:nth-child(18){animation-duration:15650ms;transform:scale(0.8582,0.8700)rotate(54deg)}
#example>g:nth-child(19){animation-duration:11847ms;transform:scale(0.9447,0.9884)rotate(139deg)}
#example>g:nth-child(20){animation-duration:9324ms;transform:scale(0.9153,0.9116)rotate(316deg)}
#example>g:nth-child(21){animation-duration:17702ms;transform:scale(0.9779,0.8993)rotate(37deg)}
#example>g:nth-child(22){animation-duration:13465ms;transform:scale(0.9961,0.8083)rotate(194deg)}
#example>g:nth-child(23){animation-duration:15226ms;transform:scale(0.9492,0.8862)rotate(183deg)}
#example>g:nth-child(24){animation-duration:12913ms;transform:scale(0.8593,0.9157)rotate(28deg)}
#example>g:nth-child(25){animation-duration:23357ms;transform:scale(0.9777,0.8756)rotate(118deg)}
#example>g:nth-child(26){animation-duration:6081ms;transform:scale(0.8035,0.8200)rotate(342deg)}
#example>g:nth-child(27){animation-duration:15580ms;transform:scale(0.8807,0.8166)rotate(242deg)}
#example>g:nth-child(28){animation-duration:18051ms;transform:scale(0.9160,0.8838)rotate(102deg)}
#example>g:nth-child(29){animation-duration:6058ms;transform:scale(0.8111,0.9906)rotate(3deg)}
#example>g:nth-child(30){animation-duration:8070ms;transform:scale(0.9133,0.8374)rotate(60deg)}
#example>g:nth-child(31){animation-duration:16621ms;transform:scale(0.8352,0.9580)rotate(339deg)}
#example>g:nth-child(32){animation-duration:27493ms;transform:scale(0.9611,0.8951)rotate(146deg)}
#example>g:nth-child(33){animation-duration:18659ms;transform:scale(0.8012,0.9420)rotate(234deg)}
#example>g:nth-child(34){animation-duration:26061ms;transform:scale(0.9279,0.8988)rotate(16deg)}
#example>g:nth-child(35){animation-duration:29827ms;transform:scale(0.9939,0.8191)rotate(289deg)}
#example>g:nth-child(36){animation-duration:20111ms;transform:scale(0.9248,0.8385)rotate(107deg)}
#example>g:nth-child(37){animation-duration:17507ms;transform:scale(0.8673,0.9479)rotate(330deg)}
#example>g:nth-child(38){animation-duration:12485ms;transform:scale(0.9069,0.9609)rotate(163deg)}
#example>g:nth-child(39){animation-duration:13963ms;transform:scale(0.8223,0.8398)rotate(195deg)}
#example>g:nth-child(40){animation-duration:9466ms;transform:scale(0.8756,0.9944)rotate(81deg)}
#example>g:nth-child(41){animation-duration:5128ms;transform:scale(0.8159,0.9781)rotate(118deg)}
#example>g:nth-child(42){animation-duration:19802ms;transform:scale(0.8892,0.9996)rotate(55deg)}
#example>g:nth-child(43){animation-duration:15241ms;transform:scale(0.8090,0.9250)rotate(169deg)}
#example>g:nth-child(44){animation-duration:17820ms;transform:scale(0.8080,0.8366)rotate(301deg)}
#example>g:nth-child(45){animation-duration:12900ms;transform:scale(0.8853,0.9383)rotate(298deg)}
#example>g:nth-child(46){animation-duration:27931ms;transform:scale(0.8182,0.9923)rotate(155deg)}
#example>g:nth-child(47){animation-duration:5307ms;transform:scale(0.9641,0.9780)rotate(299deg)}
#example>g:nth-child(48){animation-duration:12744ms;transform:scale(0.8974,0.9224)rotate(121deg)}
#example>g:nth-child(49){animation-duration:28452ms;transform:scale(0.8455,0.8270)rotate(125deg)}
#example>g:nth-child(50){animation-duration:7462ms;transform:scale(0.9797,0.9203)rotate(351deg)}
<svg id="example" version="1" xmlns="http://www.w3.org/2000/svg" viewBox="-2200 -2200 4400 1000">
  <defs><path id="asteroid" d="M-101 2154c-47-5-101-21-161-48-37-16-80-38-115-59l-19-11-19-5c-34-9-119-34-161-46-299-90-509-170-611-235-32-21-49-36-65-59-29-43-69-89-138-158-65-65-125-121-264-245-115-104-126-114-135-128-17-26-36-76-56-143-16-56-28-106-58-234-37-159-51-214-69-266-19-58-35-86-52-94-8-4-15-10-22-21-43-64-86-256-98-436-7-99-3-183 11-239 8-33 15-48 35-74 79-104 183-309 255-502 23-60 36-100 54-166 6-23 14-41 27-67 91-184 347-474 570-642 112-85 208-135 282-146 132-21 195-36 408-96 192-54 296-81 432-110 90-20 116-24 172-29 28-2.5 116-2.5 148 0 116 9 228 32 352 72 118 38 254 96 353 151l16 9 24 23c204 191 424 408 580 571 144 150 252 273 311 351 40 52 77 109 108 164 15 26 46 89 58 115 47 106 79 215 89 308 2.3 20 2 24-3.5 53-33 172-57 334-63 433-3 44-2.5 64 1.4 129 9 147 9 223 2 304-13 141-52 252-117 333-18 22-22 27-41 39-47 31-88 66-133 111-40 41-69 75-107 127-47 64-87 130-148 243-43 78-52 93-73 120-47 58-129 139-211 209-132 111-255 188-347 217-31 10-50 13-76 13-17 0-21-.3-30-2.3-35-8-52-10-94-10-37 0-54 1.1-89 6-89 12-189 40-292 81-47 18-147 49-219 67-53 13-92 21-134 27-20 3-56 3.5-73 1.5z"/></defs>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
  <g><use xlink:href="#asteroid" /></g>
</svg>

关于javascript - Canvas 图像旋转性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54737984/

相关文章:

jquery - 使用 canvas 或 svg 绘制自定义矩形形状,支持 IE7

javascript - 随着质量增加,速度下降

javascript - 如何防止从选定的单选按钮触发更改事件?

javascript - 使用 JavaScript 更改选择标签值

java - python vs java 用于存储字典的内存

linux - 在c++ 11 std::thread中执行的时间开销是否取决于所执行的有效负载?

javascript - 如何将图像添加到 Canvas 并按尺寸缩放?

javascript - 在另一个函数中创建 Mongoose 连接时不调用查询回调

javascript - 重复的 CSS 类?

python - 简化python中的循环