【问题标题】:Chain of div elements following a mouse跟随鼠标的 div 元素链
【发布时间】:2015-11-10 17:37:23
【问题描述】:

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

我对第一个有很好的结果,但现在我在弄清楚如何使第二个 div 跟随第一个时遇到了问题:

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

我想构建一个函数,将一个 div 和另一个 div 作为输入。

如果有人可以建议一种方法来做到这一点或改进现有代码(第一个 div 现在很好地跟随鼠标,但还不完美),将不胜感激。

【问题讨论】:

    标签: javascript jquery html animation graphics


    【解决方案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】:

    jsFiddle Demo

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

    有一个对orb() 的调用,在这种情况下可以很容易地修改为任何类型的 div。鼠标区域(文档)的侧面也涉及到少量的碰撞检测。

    (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);
     };
    })()
    .yellowOrb{ 
        position:absolute;
        width:100px;
        height:100px;
        background-color: yellow;
        opacity: 0.75;
        border-radius:100px;
        pointer-events:none;
        z-index:99999
    }
    &lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"&gt;&lt;/script&gt;

    【讨论】:

      【解决方案3】:

      感谢大家的建议; 我已经用圆数组重写了它(所以现在没有旋转处理);

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

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

      【讨论】:

        【解决方案4】:

        处理此任务的一种方法是将函数follow(snake, leader) 应用于每对连续的蛇段,使snakeleader 后面。

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

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

        现在您可以在angle 方向上调整snake.xsnake.y,使追随者靠近领导者。

        head 段可以跟随您定义为{ x: mouseX, y: mouseX } 的对象,并且您可以在鼠标位置发生变化时对其进行更新。

        下面的 sn-p 演示了这种方法。

        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>

        【讨论】:

        • 太棒了!这就是我想要做的......最后一件事:当你写这个精彩的例子时,我试图弄清楚如何限制蛇部分之间的最大距离(以避免它们彼此之间变得太远,而快速移动鼠标);因为你的例子比我的好,也许你也知道一个更好的解决方案......
        • 我添加了一个名为 maxDistance 的变量。您可以根据自己的喜好进行调整。目前它只适用于蛇元素之间,而不是鼠标和蛇头之间。如果您确实希望蛇紧紧跟随鼠标,请从第一次调用 follow 中删除 mouse: true
        • 完美!您为我完成了所有工作;)我只是将您的解决方案与我正在研究的解决方案进行比较,而您的解决方案要好得多,所以我会保留它;再次感谢
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-05
        • 1970-01-01
        • 1970-01-01
        • 2022-09-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多