d3.js眼睛跟随鼠标块

时间:2015-04-28 13:25:01

标签: javascript canvas svg d3.js

我试图用瞳孔跟随鼠标光标创建2只d3.js& svg眼睛,当鼠标越过它们时,它们会随机移动。然而,在随机数量的成功运动后,它们会冻结,我无法理解为什么。

这是代码:

var width = 1200,
    height = 600;

var ptdata = [];

var pray = 10, 
    eray = 50;

var cx0 = 0, cx1 = 100
    cy = 0;

var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g");

var eye0 = svg.append("circle")
.attr("id", "eye0")
.attr("class", "eye")
.attr("cx", cx0)
.attr("cy", cy)
.attr("r", eray)
.attr("stroke", "black")
.attr("fill", "white")
.data([ptdata]);

var eye1 = svg.append("circle")
.attr("id", "eye1")
.attr("class", "eye")
.attr("cx", cx1)
.attr("cy", cy)
.attr("r", eray)
.attr("stroke", "black")
.attr("fill", "white")
.data([ptdata]);

var pupil0 = svg.append("circle")
.attr("id", "pupil0")
.attr("class", "pupil")
.attr("cx", cx0)
.attr("cy", cy)
.attr("r", pray)
.attr("fill", "black")
.data([ptdata]);

var pupil1 = svg.append("circle")
.attr("id", "pupil1")
.attr("class", "pupil")
.attr("cx", cx1)
.attr("cy", cy)
.attr("r", pray)
.attr("fill", "black")
.data([ptdata]);

var eyes = svg.selectAll(".eye");
var pupils = svg.selectAll(".pupil");

function init() {
    var tx0 = 0, ty0 = 0;
    while (tx0<eray || (tx0+cx1)>(width-eray)) {
        var randx = Math.round(Math.random() * width, 2);
        tx0 = randx;
    }
    while (ty0<eray || (ty0+cy)>(height-eray)) {
        var randy = Math.round(Math.random() * height, 2);
        ty0 = randy;
    }

    cx0 += tx0; cx1 += tx0; cy += ty0;
    eye0.attr("cx", cx0);
    eye1.attr("cx", cx1);
    eyes.attr("cy", cy);
    pupil0.attr("cx", cx0);
    pupil1.attr("cx", cx1);
    pupils.attr("cy", cy);
}   
init();

var distanceThreshold = eray - pray;

var mouseX = cx0, mouseY = cy;

var svgagain = d3.select("body").select("svg")
.on("mousemove", function() { 
    var pt = d3.mouse(this); 
    follow(pt); 
});

function follow(pt) {
    ptdata.push(pt);

    var x = pt[0];
    var y = pt[1];

    var d0 = {
        dx: x - cx0,
        dy: y - cy
    };
    var distance0 = Math.sqrt(d0.dx * d0.dx + d0.dy * d0.dy);

    var d1 = {
        dx: x - cx1,
        dy: y - cy
    };
    var distance1 = Math.sqrt(d1.dx * d1.dx + d1.dy * d1.dy);

    mouseX0 = d0.dx / distance0 * distanceThreshold + cx0;
    mouseY0 = d0.dy / distance0 * distanceThreshold + cy;

    var xp0 = cx0, yp0 = cy;
    var xp1 = cx1, yp1 = cy;

    pupil0.attr("cx", 
        function(d) { 
            xp0 += (mouseX0 - xp0) / 1;
            return xp0; 
        })
    .attr("cy", 
        function(d) { 
            yp0 += (mouseY0 - yp0) / 1;
            return yp0; 
        });

    mouseX1 = d1.dx / distance1 * distanceThreshold + cx1;
    mouseY1 = d1.dy / distance1 * distanceThreshold + cy;


    pupil1.attr("cx", 
        function(d) { 
            xp1 += (mouseX1 - xp1) / 1;
            return xp1; 
        })
    .attr("cy", 
        function(d) { 
            yp1 += (mouseY1 - yp1) / 1;
            return yp1; 
        });
}

function move(pt) {
    ptdata.push(pt);

    var x = pt[0];
    var y = pt[1];

    var tx = 0, ty = 0;
    var newCX0 = cx0, newCX1 = cx1, newCY = cy;
    while (x<(newCX1+eray) && x>(newCX0-eray) && y<(newCY+eray) && y>(newCY-eray) ||
        (newCX0<eray || newCX1>(width-eray) || newCY<eray || newCY>(height-eray))){
        var randx = Math.round(Math.random() * width, 2);
        tx = Math.random() < 0.5 ? (-randx) : randx;
        newCX0 += tx; newCX1 += tx;
        var randy = Math.round(Math.random() * height, 2);
        ty = Math.random() < 0.5 ? (-randy) : randy;
        newCY += ty;
    }

    cx0 = newCX0; cx1 = newCX1; cy = newCY;
    eye0.attr("cx", cx0);
    eye1.attr("cx", cx1);
    eyes.attr("cy", cy);
    pupil0.attr("cx", cx0);
    pupil1.attr("cx", cx1);
    pupils.attr("cy", cy);
}

var eye0again = eye0.on("mouseover", function() { 
    var pt = d3.mouse(this); 
    move(pt); 
});

4 个答案:

答案 0 :(得分:0)

您的代码似乎卡在Exception in thread "main" java.lang.NoclassDefFoundError: au/com/bytecode/opencsv/CSVWriter 函数的while循环中。 move循环中的条件不会收敛,因为眼睛正在页面上移动。

试试这个:

while
var width = 600,
  height = 300;

var ptdata = [];

var pray = 10,
  eray = 50;

var cx0 = 0,
  cx1 = 100,
  cy = 0;

var svg = d3.select("#vis")
  .append("svg")
  .attr("width", width)
  .attr("height", height)
  .append("g");

var eye0 = svg.append("circle")
  .attr("id", "eye0")
  .attr("class", "eye")
  .attr("cx", cx0)
  .attr("cy", cy)
  .attr("r", eray)
  .attr("stroke", "black")
  .attr("fill", "white")
  .data([ptdata]);

var eye1 = svg.append("circle")
  .attr("id", "eye1")
  .attr("class", "eye")
  .attr("cx", cx1)
  .attr("cy", cy)
  .attr("r", eray)
  .attr("stroke", "black")
  .attr("fill", "white")
  .data([ptdata]);

var pupil0 = svg.append("circle")
  .attr("id", "pupil0")
  .attr("class", "pupil")
  .attr("cx", cx0)
  .attr("cy", cy)
  .attr("r", pray)
  .attr("fill", "black")
  .data([ptdata]);

var pupil1 = svg.append("circle")
  .attr("id", "pupil1")
  .attr("class", "pupil")
  .attr("cx", cx1)
  .attr("cy", cy)
  .attr("r", pray)
  .attr("fill", "black")
  .data([ptdata]);

var eyes = svg.selectAll(".eye");
var pupils = svg.selectAll(".pupil");

function init() {
  var tx0 = 0,
    ty0 = 0;
  while (tx0 < eray || (tx0 + cx1) > (width - eray)) {
    var randx = Math.round(Math.random() * width, 2);
    tx0 = randx;
  }
  while (ty0 < eray || (ty0 + cy) > (height - eray)) {
    var randy = Math.round(Math.random() * height, 2);
    ty0 = randy;
  }

  cx0 += tx0;
  cx1 += tx0;
  cy += ty0;
  eye0.attr("cx", cx0);
  eye1.attr("cx", cx1);
  eyes.attr("cy", cy);
  pupil0.attr("cx", cx0);
  pupil1.attr("cx", cx1);
  pupils.attr("cy", cy);
}
init();

var distanceThreshold = eray - pray;

var mouseX = cx0,
  mouseY = cy;

var svgagain = d3.select("body").select("svg")
  .on("mousemove", function() {
    var pt = d3.mouse(this);
    follow(pt);
  });

function follow(pt) {
  ptdata.push(pt);

  var x = pt[0];
  var y = pt[1];

  var d0 = {
    dx: x - cx0,
    dy: y - cy
  };
  var distance0 = Math.sqrt(d0.dx * d0.dx + d0.dy * d0.dy);

  var d1 = {
    dx: x - cx1,
    dy: y - cy
  };
  var distance1 = Math.sqrt(d1.dx * d1.dx + d1.dy * d1.dy);

  mouseX0 = d0.dx / distance0 * distanceThreshold + cx0;
  mouseY0 = d0.dy / distance0 * distanceThreshold + cy;

  var xp0 = cx0,
    yp0 = cy;
  var xp1 = cx1,
    yp1 = cy;

  pupil0.attr("cx",
      function(d) {
        xp0 += (mouseX0 - xp0) / 1;
        return xp0;
      })
    .attr("cy",
      function(d) {
        yp0 += (mouseY0 - yp0) / 1;
        return yp0;
      });

  mouseX1 = d1.dx / distance1 * distanceThreshold + cx1;
  mouseY1 = d1.dy / distance1 * distanceThreshold + cy;


  pupil1.attr("cx",
      function(d) {
        xp1 += (mouseX1 - xp1) / 1;
        return xp1;
      })
    .attr("cy",
      function(d) {
        yp1 += (mouseY1 - yp1) / 1;
        return yp1;
      });
}

function move(pt) {
  ptdata.push(pt);

  var x = pt[0];
  var y = pt[1];

  var tx = 0,
    ty = 0;
  var newCX0 = cx0,
    newCX1 = cx1,
    newCY = cy;
  while (x < (newCX1 + eray) && x > (newCX0 - eray) && y < (newCY + eray) && y > (newCY - eray) ||
    (newCX0 < eray || newCX1 > (width - eray) || newCY < eray || newCY > (height - eray))) {
    var randx = Math.round(Math.random() * width, 2);
    tx = Math.random() < 0.5 ? (-randx) : randx;
    newCX0 += tx;
    newCX1 += tx;
    var randy = Math.round(Math.random() * height, 2);
    ty = Math.random() < 0.5 ? (-randy) : randy;
    newCY += ty;
  }

  cx0 = newCX0;
  cx1 = newCX1;
  cy = newCY;
  //    eye0.attr("cx", cx0);
  //    eye1.attr("cx", cx1);
  //    eyes.attr("cy", cy);
  pupil0.attr("cx", cx0);
  pupil1.attr("cx", cx1);
  pupils.attr("cy", cy);
}

/*
var eye0again = eye0.on("mouseover", function() { 
    var pt = d3.mouse(this); 
    move(pt); 
});
*/

我已经评论了几个部分,这些部分将阻止您所看到的行为。我评论过的那些东西让眼睛跳到了svg周围。在某些时候,他们最终的位置导致你的<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> <div id="vis"></div>函数陷入while循环,如上所述。通过停止跳转,move循环似乎正确终止。

答案 1 :(得分:0)

我以这种方式解决了:

function move(pt) {

    var x = pt[0];
    var y = pt[1];

    var newCX0 = cx0, newCX1 = cx1, newCY = cy;
    while (newCX0>(cx0-eray) && newCX0<(cx1+eray) && newCY>(cy-eray) && newCY<(cy+eray)) {
        var randx = Math.random()*(width-(eray*4)) + eray;
        newCX0 = Math.round(randx, 2);
        newCX1 = newCX0+(eray*2);
        var randy = Math.random()*(height-(eray*2)) + eray;
        newCY = Math.round(randy, 2);
    }

    cx0 = newCX0; cx1 = newCX1; cy = newCY;
    eye0
    .attr("cx", cx0);
    eye1
    .attr("cx", cx1);
    eyes
    .attr("cy", cy);

    pupil0
    .attr("cx", cx0);
    pupil1
    .attr("cx", cx1);
    pupils
    .attr("cy", cy);
    });
}

答案 2 :(得分:0)

下面是我在2001年写的一个旧脚本,一年前更新过。不完全是你想要的,但你应该能够转换眼睛数学&#39;

&#13;
&#13;
(function () {

    /* Following Eyes 2003 - kurt.grigg@yahoo.co.uk (Updated) */

    var eye = 50; //Eye size in pixels

    if (eye % 2 == 0){
        eye++;
    }
    var eye5 = eye / 2 | 0;
    var pup = 42 * eye / 100; 
    if (pup % 2 == 0){
        pup++;
    }
    var pup5 = (pup - 3) / 2;
    if (pup5 % 2 == 1){
        pup5++;
    }
    var grng = (eye - pup) / 2; 
    if (grng % 2 == 1){
        grng++;
    }
    var rng = eye5 / grng; 
    var d = document;
    var my = 0;
    var mx = 0;
    var fy = 0;
    var fx = 0;
    var ros = eye + 2;
    var scy = 0;
    var scx = 0;
    var mls = 1000 / 60;
    var lastEx = performance.now();
    var h, w, dy, dx, chy, chx, d1, d2, a1, a2, le, re, yec, xec;

    var cstyle =
        'position:absolute;top:0px;left:0px;width:'+(ros*2)+'px;height:'+ros+'px;'
        +'margin:0px;border:none;padding:0px;display:inline-block;';

    var estyle =
        'position:absolute;top:0px;left:0px;height:'+eye+'px;'
        +'width:'+eye+'px;background-color:#ffffff;'
        +'border-radius: 50%;border: 1px solid #000000;'
        +'box-shadow: inset -'+eye/3+'px -'+eye/3+'px '+eye/2+
        'px -'+(eye/10|0)+'px rgba(0,0,0,0.16);';

    var pstyle =
        'position:absolute;top:45%;left:45%;height:'+pup+'px;'
        +'width:'+pup+'px;background-color:#000000;border-radius: 50%;';

    var wstyle =
        'position:absolute;top:16%;left:16%;width:20%;height:20%;'
        +'background:#ffffff;border-radius:50%;'
        +'transform: skewX(-15deg) skewY(-18deg);';

    var c = d.createElement('div');
    var e1 = d.createElement('div');
    var e2 = d.createElement('div');
    var p1 = d.createElement('div');
    var p2 = d.createElement('div');
    var w1 = d.createElement('div');
    var w2 = d.createElement('div');

    c.setAttribute('style', cstyle);
    e1.setAttribute('style', estyle);
    e2.setAttribute('style', estyle + 'left:'+ros+'px;');
    p1.setAttribute('style', pstyle);
    p2.setAttribute('style', pstyle);
    w1.setAttribute('style', wstyle);
    w2.setAttribute('style', wstyle);

     d.body.appendChild(c);
    c.appendChild(e1);
    c.appendChild(e2);
    d.body.appendChild(p1);
    d.body.appendChild(p2);
    p1.appendChild(w1);
    p2.appendChild(w2);

    function scrl(v) {
        var y, x;
        y = window.pageYOffset;
        x = window.pageXOffset;
        return (v == 0) ? y : x;
    }

    function initscroll() {
        scy = scrl(0);
        scx = scrl(1);
    }

    function windims() {
        var tmp = d.documentElement.clientWidth;
        var ch = (typeof tmp == 'number');
        var sc = (ch) ? window.innerWidth - tmp : 0;
        h = window.innerHeight;
        w = window.innerWidth - sc;
    }

    function mouse(e) {
        if (!e) {
            e = window.event;
        }
        my = e.pageY - window.pageYOffset;
        mx = e.pageX - window.pageXOffset;
    }

    function ani() {
        //Keep eyes on screen.
        chy = Math.floor(fy - (ros*1.2));
        if (chy <= 0) {
            chy = 0;
        }
        if (chy >= h - ros) {
            chy = h - ros;
        }

        chx = Math.floor(fx - ros);
        if (chx <= 0) {
            chx = 0;
        }
        if (chx >= w - (ros*2)) {
            chx = w - (ros*2);
        }

        //Eyeball centres.
        yec = chy + eye5;
        xec = chx + eye5;

        d1 = Math.sqrt((my - yec) * (my - yec) + (mx - xec) * (mx - xec));
        d2 = Math.sqrt((my - yec) * (my - yec) + (mx - (xec + ros)) * (mx - (xec + ros)));

        a1 = Math.atan2(my - yec, mx - xec) * 180 / Math.PI;
        a2 = Math.atan2(my - yec, mx - (xec + ros)) * 180 / Math.PI;

        le = (d1 < eye5) ? d1 / rng : grng;
        re = (d2 < eye5) ? d2 / rng : grng;

        c.style.top = chy + scy + 'px';
        c.style.left = chx + scx + 'px';

        p1.style.top = yec - pup5 + le * Math.sin(a1 * Math.PI / 180) + scy + 'px';
        p1.style.left = xec - pup5 + le * Math.cos(a1 * Math.PI / 180) + scx + 'px';

        p2.style.top = yec - pup5 + re * Math.sin(a2 * Math.PI / 180) + scy + 'px';
        p2.style.left = (xec + ros) - pup5 + re * Math.cos(a2 * Math.PI / 180) + scx + 'px';
    }

    function move() {
        dy = fy += (my - fy) * 0.05;
        dx = fx += (mx - fx) * 0.05;
        ani();
    }

    function init() {
        windims();
        draw();
    }

    function draw() {
        var now = performance.now();
        if ((now - lastEx) > (mls)) {
            move();
            lastEx = performance.now();
        }
        requestAnimationFrame(draw);
    }

    window.addEventListener("resize", windims, false);
    window.addEventListener("load", init, false);
    d.addEventListener("mousemove", mouse, false);
    window.addEventListener("scroll", initscroll, false);

})();
&#13;
&#13;
&#13;

答案 3 :(得分:0)

管理找到并用鼠标跟随我的另一个老看的眼睛脚本。它很容易调整大小和内嵌块,所以

Pod

可以整齐地放在HTML流程中。