我试图制作一种由特定区域内跟随鼠标的HTML div组成的蛇。
我对第一个有一个非常好的结果,但现在我在找出如何使第二个div跟随第一个有问题时出现了问题:
https://jsbin.com/xozawokore/edit?js,output
我想构建一个函数,将div作为输入,然后使用另一个div。
如果有人可以建议一种方法来完成这项工作或改进现有的代码(第一个div现在非常适合鼠标,但还不完美),我们将不胜感激。
答案 0 :(得分:3)
接近此任务的一种方法是将函数follow(snake, leader)
应用于每对连续的蛇段,使snake
落后于leader
。
如果每个蛇段具有存储段中心位置的属性x
和y
,则可以计算段之间的距离和位移角度:
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.y
和angle
,以便关注者更接近领导者。
头部可以跟随您定义为{ 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。鼠标区域(文档)侧面还涉及少量碰撞检测。
(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;
答案 3 :(得分:0)
感谢大家的建议; 我已经使用一系列圆圈重新编写了它(所以现在没有旋转来处理);
https://jsbin.com/zenowoduxu/edit?js,output
现在我尝试使用三角形和旋转......