跟随鼠标的div元素链

时间:2015-08-17 23:28:44

标签: javascript jquery html animation graphics

我试图制作一种由特定区域内跟随鼠标的HTML div组成的蛇。

我对第一个有一个非常好的结果,但现在我在找出如何使第二个div跟随第一个有问题时出现了问题:

https://jsbin.com/xozawokore/edit?js,output

我想构建一个函数,将div作为输入,然后使用另一个div。

如果有人可以建议一种方法来完成这项工作或改进现有的代码(第一个div现在非常适合鼠标,但还不完美),我们将不胜感激。

4 个答案:

答案 0 :(得分:3)

接近此任务的一种方法是将函数follow(snake, leader)应用于每对连续的蛇段,使snake落后于leader

如果每个蛇段具有存储段中心位置的属性xy,则可以计算段之间的距离和位移角度:

var dx = leader.x - snake.x,
    dy = leader.y - snake.y,
    dd = Math.hypot(dx, dy),
    angle = snake.angle = Math.atan2(dy, dx);

现在,您可以在snake.x方向调整snake.yangle,以便关注者更接近领导者。

头部可以跟随您定义为{ x: mouseX, y: mouseX }的对象,并且只要它发生变化,您就可以使用鼠标位置进行更新。

以下代码段演示了这种方法。

function rotate(element, radians) {
  radians += Math.PI / 2;
  var s = 'rotate(' + radians + 'rad)';
  $(element).css('-moz-transform', s)
      .css('-webkit-transform', s)
      .css('-o-transform', s)
      .css('-ms-transform', s);
}

function initSnakes(container, numSnakes) {
  var snakeWidth = 22,
      snakeHeight = 22,
      snakeRadius = Math.max(snakeWidth, snakeHeight),
      maxDistance = 1.5 * snakeRadius,
      frameRate = 60,
      damping = 9 * frameRate / 30,
      width = container.width(),
      height = container.height(),
      border = parseInt(container.css('border-left-width'), 10),
      left = container.offset().left + border,
      top = container.offset().top + border,
      snakes = new Array(numSnakes),
      mouse = { x: width / 5, y: height / 5, mouse: true };

  function positionSnake(snake) {
    $(snake.element).css({ left: snake.x - snakeWidth / 2,
        top: snake.y - snakeHeight / 2 });
    rotate(snake.element, snake.angle);
  }

  for (var i = 0; i < numSnakes; ++i) {
    var snake = snakes[i] = {
      id: i,
      x: width * 4 / 5,
      y: height * 4 / 5,
      angle: Math.PI * 3 / 2,
      element: $.parseHTML('<div class="snakeSegment"></div>')
    };
    var color = 'rgb(90, 150, ' + Math.min(200, (120 + 35 * i)) + ')';
    $(snake.element).css('border-bottom-color', color);
    container.append(snake.element);
    positionSnake(snake);
    if (i == 0) {
      follow(snake, mouse);
    } else {
      follow(snake, snakes[i - 1]);
    }
  }

  function follow(snake, leader) {
    function update () {
      var dx = leader.x - snake.x,
          dy = leader.y - snake.y,
          dd = Math.hypot(dx, dy),
          angle = snake.angle = Math.atan2(dy, dx),
          direction = (dd < snakeRadius ? -1 : 1);
      if (dd > maxDistance && !leader.mouse) {
        snake.x += Math.cos(angle) * (dd - maxDistance);
        snake.y += Math.sin(angle) * (dd - maxDistance);
        dx = leader.x - snake.x;
        dy = leader.y - snake.y;
        dd = maxDistance;
      }
      if (dd - snakeRadius < 0.5) {
        return;
      }
      snake.x += direction * Math.cos(angle) * dd / damping;
      snake.y += direction * Math.sin(angle) * dd / damping;
      positionSnake(snake);
    }
    update();
    snake.moveInterval = window.setInterval(update, 1000 / frameRate);
  }

  function mouseUpdate(event) {
    event = event || window.event;
    mouse.x = event.pageX - left;
    mouse.y = event.pageY - top;
  }
  container.mousemove(mouseUpdate);
}

function launch() {
  initSnakes($('#snakeShadowDemo'), 5);
}

$(document).ready(launch);

$(window).resize(function () {
  $('.snakeSegment').remove();
  launch();
});
.snakeSegment {
  position: absolute;
  top: 100px;
  left: 50%;
  width: 0;
  height: 0;
  border-left: 11px solid transparent;
  border-right: 11px solid transparent;
  border-bottom: 22px solid #333;
}

#snakeShadowDemo {
  width: 400px;
  height: 450px;
  margin: auto;
  position: relative;
  background-color: #eee;
  border: solid 3px #333;
}
<script src="https://code.jquery.com/jquery-2.1.4.js"></script>

<div id="snakeShadowDemo"></div>

答案 1 :(得分:1)

每个div应具有以0(或1)开头的唯一ID。然后

numDivs;
var firstDiv = document.getElementById("0");
firstDiv.setCoordinates(mouse.x, mouse.y); // this isnt correct but you get the idea
previousDiv = firstDiv;
for(var i = 1; i < numDivs; i ++){
    var div = document.getElementById(i);
    div.setCoordinates(previousDiv.x + offset, previousDiv.y + offset); // sequentially set the coordinates based upon the previous div
    previousDiv = div;
}

答案 2 :(得分:1)

<强> jsFiddle Demo

我建议创建一个数组来保存这些div。在这个简单的演示中,我将它们命名为orbs(因为它们是黄色圆圈)。每次鼠标移动时,都会创建一个圆球。如果有超过5个球体,则删除数组中的第一个(shift()从数组中删除第一个项目。)

在这种情况下,可以轻松地将orb()调用到任何类型的div。鼠标区域(文档)侧面还涉及少量碰撞检测。

&#13;
&#13;
(function(){
 var orbs = [];
 function orb(){
  return $('<div class="yellowOrb">')[0]; 
 }
 window.onmousemove = function(e){
  var docH = $(document).height(),
      docW = $(document).width();
  if( e.pageY < 5 || e.pageY > (docH-40)
     || e.pageX < 5 || e.pageX > (docW-40) ) {
      $(orbs).each(function(){
          $(orbs.shift()).remove();  
      });
      return;
  }
  var ylow = orb();
  ylow.style.top = e.pageY-50 + "px";
  ylow.style.left = e.pageX-50 + "px";
  orbs.push(ylow);
  if(orbs.length > 5){
      $(orbs.shift()).remove();
  }
  $('body').append(ylow);
 };
})()
&#13;
.yellowOrb{ 
    position:absolute;
    width:100px;
    height:100px;
    background-color: yellow;
    opacity: 0.75;
    border-radius:100px;
    pointer-events:none;
    z-index:99999
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
&#13;
&#13;
&#13;

答案 3 :(得分:0)

感谢大家的建议; 我已经使用一系列圆圈重新编写了它(所以现在没有旋转来处理);

https://jsbin.com/zenowoduxu/edit?js,output

现在我尝试使用三角形和旋转......