如何有效地完成这种效果?

时间:2015-04-12 09:02:26

标签: javascript html performance

我正在测试像素跟随鼠标的效果。 http://dukevin.com/pixel

但我目前的实施资源非常繁重;创建填充页面的div并查询它们以更改颜色。

有没有一种方法可以产生类似的效果,而不会如此资源丰富? 我的想法是在鼠标移动时动态生成div,并在淡出时删除它们。

$(document).ready(function(){
    var body = $('body');
    for(var i = 0; i < Math.floor($(window).width()/30)*Math.floor($(window).height()/30) ; i++)
        body.append("<div class=box></div>");
});

var colors = ["#f00","#c00","#d00","#e00"];
$(document).on('mouseenter', '.box', function (event) {
    $(this).css({
        backgroundColor: colors[Math.floor(Math.random() * colors.length)],
        opacity: 1
    });
}).on('mouseleave', '.box', function (event) {
    $(this).css('opacity', 0);
});
body {
    width: 100%;
    margin: 0;
    padding: 0;
    line-height: 0px;
    background-color: #333;
}
.box {
    display: inline-block;
    vertical-align:top;
    z-index: -1;
    width: 30px;
    height: 30px;
    transition: all 2s ease;
}
.box:hover {
    transition: all 0s ease;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

2 个答案:

答案 0 :(得分:6)

<3

点击下面的运行代码段 ,然后在黑色区域中拖动鼠标。

总而言之,这是非常有效的。创建像素后,会将其添加到pixels数组中。在loop中,每个像素都会调用update(delta)函数,如果像素的alpha高于true,则会返回0。一旦像素的alpha值降至零以下,它就会被删除。

这只使用:

  • 1x HTML元素
  • 2x 事件监听器

&#13;
&#13;
var canvas    = document.querySelector("canvas");
var ctx       = canvas.getContext("2d");
var pixelSize = 20; // px, 20px squares
var speed     = 33; // ms, (1000ms / 33ms = ~30fps)
var ttl       = 2000.0; // ms, (pixel fade out time)

// Pixel constructor
function Pixel(x, y, size, rgba) {
  
  if (!(this instanceof Pixel)) {
    return new Pixel(x, y, size, rgba);
  }
  
  // pixel update function; called once per tick
  function update(delta) {
    // decrease the alpha of this pixel by delta/ttl;
    rgba.a = (rgba.a - (delta/ttl)).toFixed(2);
    // redraw this pixel
    ctx.clearRect(x, y, size, size);
    ctx.fillStyle = rgbaStr(rgba);
    ctx.fillRect(x, y, size, size);
    // return true if pixel alpha is still above 0
    // return false when this pixel is no longer visible (garbage collect)
    return rgba.a > 0;
  }
  
  // export the update function
  this.update = update;
}

// rgba helper
function rgba(r, g, b, a) {
    return {r:r, g:g, b:b, a:a};
}

// convert rgba to CSS string
function rgbaStr(rgba) {
    var args = [rgba.r, rgba.g, rgba.b, rgba.a];
    return "rgba(" + args.join(",") + ")";
}

// all "active" pixels
var pixels = [];

// Pixel factory function
function createPixel(x, y, size, rgba) {
  // create pixel
  var pixel = new Pixel(
    Math.round(x / size) * size, // snap to grid
    Math.round(y / size) * size, // snap to grid
    size,                        // pixel/grid size
    rgba                         // rgba color
  );
  // add pixel to array
  pixels.push(pixel);
  // return constructed pixel      
  return pixel;
}

// the loop
function loop(now) {
    // calculate delta
    var delta = Date.now() - now;
    // loop through each pixel
    pixels.forEach(function(pixel, idx) {
        // if pixel is faded out completely...
        if (!pixel.update(delta)) {
           // delete the pixel
           pixels.splice(idx, 1); 
        }
    });
    // loop again (based on speed)
    setTimeout(loop.bind(null, Date.now()), speed);
}

// size canvas to full size of window
function resizeCanvas(event) {
  ctx.canvas.width = window.innerWidth;
  ctx.canvas.height = window.innerHeight;
}

// setup
function init() {
  // set canvas size
  resizeCanvas();

  // resize canvas size whenever window is resized
  window.addEventListener("resize", resizeCanvas);
  
  // create pixels on mousemove
  canvas.addEventListener("mousemove", function(event) {
    createPixel(
      event.clientX,  // mouse x position
      event.clientY,  // mouse y position
      pixelSize,      // the pixelSize defined above
      rgba(255,0,0,1) // start at 100% red
    );
  });
  
  // start the loop
  loop(Date.now());
}

// start everything
init();
&#13;
html, body {
    width: 100%;
    height: 100%;
    margin: 0;
}

body {
    background-color: black;
    color: white;
}
&#13;
<canvas></canvas>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

我会创建位于所有内容之上的画布覆盖并将其呈现在那里,因为您不会一直创建和删除DOM对象,所以它应该快得多。