平滑的Javascript mousemove类似于Cubism.js

时间:2012-10-11 16:55:46

标签: javascript jquery d3.js cubism.js

我很好奇迈克博斯托克如何能够以如此顺畅的方式创建一条跟随鼠标光标的垂直线。如果你看这里http://square.github.com/cubism/,你可以看到我在说什么。

看看我刚刚在这里做的一个简单示例:http://jsfiddle.net/zbfUq/

很多时候,我的示​​例中的行实际上消失了。他是否正在进行某种位置插值,以便在两个未被记录的点之间创建平滑的平移?如果是这样,任何人都知道如何做这样的事情?

3 个答案:

答案 0 :(得分:3)

我为你做了一个有用的例子: http://jsfiddle.net/zbfUq/37/

基本上你已经在onmousemove事件处理程序中记录了鼠标位置,但实际上并没有立即将线移动到那里。

然后运行一个计时器,每隔一段时间检查一次(在我的例子中每10毫秒),并将线移近鼠标位置。

onmouseover事件中,我将行位置设置为鼠标位置,并设置计时器。

onmouseout事件中,我清除了计时器,并将行位置设置回0(您也可以隐藏该行)。

updatepos函数首先检查线与鼠标位置的距离。如果它小于1px,它只是将线移动到鼠标位置。如果它距离超过1px,它移动的距离就会与它离开的距离成比例(如果线离鼠标更远,它会更快地向它移动)。

Javascript代码

(function() {
    var selectline = document.getElementById('selection_line');
    var container = document.getElementById('page_content');
    var mouseX = 0;
    var lineX = 0;

    var linetimer;

    var updatepos = function () {
        var speed, distance;
        distance = Math.abs(mouseX - lineX);
        if (distance < 1) {
            lineX = mouseX;
        }
        else {
            speed = Math.round( distance / 10, 0 );
            speed = speed >= 1 ? speed : 1;
            lineX = (lineX < mouseX) ? lineX + speed : lineX - speed;
        }

        selectline.style.left = lineX + 'px';

    }

    $(container).on("mouseover", function(e) {
        lineX = mouseX;
        selectline.style.left = lineX + 'px';
        linetimer = setInterval(updatepos, 10);
    });

    $(container).on('mousemove', function(e) {
        mouseX = e.pageX;
        console.log(mouseX);
    });

    $(container).on("mouseout", function(e) {
        clearTimeout(linetimer);
        lineX = 0;
        selectline.style.left = LineX + 'px';
    });
})();​

答案 1 :(得分:2)

我猜他正在使用d3.js transition,参见https://github.com/mbostock/d3/wiki/Transitions,基本上为从当前行位置到鼠标光标当前所在行的线(和值)设置动画。你可以告诉他不是只是按照鼠标诅咒,因为如果你快速移动光标,你可以看到线条滞后一点,这是过渡的动画时间。

我在http://jsfiddle.net/2N2rt/4/的d3.js中汇总了一个如何完成此操作的快速示例。我没有玩很多,所以我相信你可以让它更顺畅,但这似乎很不错。

var line = d3.select('#selection_line'),
    page = d3.select('#page_content'),
    x = 0;

page.on('mousemove', function() { x = d3.mouse(this)[0]; });

var update = function() { 
    line.transition()
        .duration(5)
        .ease('cubic-in-out')
          .style('left', x + 'px');
};

setInterval(update, 35);

另请注意,svg元素比DOM元素更容易制作动画。这是一个纯svg示例(http://jsfiddle.net/2N2rt/10/)。

var graph = d3.select('#graph')
              .append('svg')
                  .attr('width', '100%')
                  .attr('height', 600);

var box = graph.append('rect')
               .attr('transform', 'translate(0, 100)')              
               .attr('width', '100%')
               .attr('height', 200)
               .attr('class', 'page_content');

var line = graph.append('line')
                .attr('transform', 'translate(0, 50)') 
                .attr({'x1': 0, 'y1' : 0, 'x2': 0, 'y2': 300})
                .attr('class', 'selection_line');

var x = 0;

graph.on('mousemove', function () {
   x = d3.mouse(this)[0];         
});

var draw = function () {           
      line
        .transition()
        .duration(18)
        .attrTween('transform', d3.tween('translate(' + x + ', 50)', d3.interpolateString))
        .each('end', draw);        
};

draw();

同样,这只是一个简单的例子,但希望它能给你一些想法。

答案 2 :(得分:0)

我相信该行是使用cubism.rule生成的,请查看view-source:http://bost.ocks.org/mike/cubism/intro/demo-stocks.html。您需要的是以下内容:

d3.select(“body”)。append(“div”)。attr(“class”,“rule”)。call(context.rule());

这使用context.rule()来实现它,一个d3 /立体主义函数。

该规则仅涵盖当前屏幕的问题只有一个。一旦向上滚动屏幕,规则(行)就会消失。