admin 管理员组

文章数量: 1086019

I'm curious how Mike Bostock was able to create a vertical line that follows your mouse cursor in such a smooth way. If you look here / , you can see what I'm talking about.

Take a look at a quick example I just made here: /

There are many times where the line in my example actually disappears. Is there some sort of position interpolation he is doing to create a smooth translation between two points that are not being recorded? If so, anyone know how to do something like that?

I'm curious how Mike Bostock was able to create a vertical line that follows your mouse cursor in such a smooth way. If you look here http://square.github./cubism/ , you can see what I'm talking about.

Take a look at a quick example I just made here: http://jsfiddle/zbfUq/

There are many times where the line in my example actually disappears. Is there some sort of position interpolation he is doing to create a smooth translation between two points that are not being recorded? If so, anyone know how to do something like that?

Share Improve this question edited Oct 12, 2012 at 6:52 Bill 25.6k8 gold badges99 silver badges129 bronze badges asked Oct 11, 2012 at 16:55 frshcafrshca 1,3392 gold badges15 silver badges24 bronze badges 1
  • Did you try transition-duration in CSS? I found it works very well and it’s so much simpler! fiddle – BarryCap Commented Apr 6, 2022 at 12:33
Add a ment  | 

3 Answers 3

Reset to default 3

I've made you a working example: http://jsfiddle/zbfUq/37/

Essentially you have record the mouse position in the onmousemove event handler, but not actually move the line there straight away.

You then run a timer which checks every so often (every 10 milliseconds in my example), and moves the line closer to the mouse position.

In the onmouseover event, I set the line position to the mouse position, and set the timer going.

In the onmouseout event I clear the timer, and set the line position back to 0 (you could also hide the line).

The updatepos function first checks how far away the line is from the mouse position. If it is less than 1px away, it simply moves the line to the mouse position. If it is more than 1px away, it moves is closer at a speed proportional to the distance away it is (if the line is further from the mouse, it moves towards it quicker).

Javascript code

(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';
    });
})();​

I'm guessing he's using a d3.js transition, see https://github./mbostock/d3/wiki/Transitions, to basically animate the line (and values) from the current line position to where the mouse cursor currently is. You can tell he isn't trying to just follow the mouse curse because if you move the cursor quickly you can see the line lag behind a bit, this is the animation time of the transition.

I put together a quick example of how this is done in d3.js at http://jsfiddle/2N2rt/4/. I didn't play around with it much so I'm sure you can get it even smoother, but this seemed pretty good.

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);

Also keep in mind that svg elements tend to animate a lot more smoothly than DOM elements. Here's a pure svg example ( http://jsfiddle/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();

Again, this is just a quick example but hopefully it gives you some ideas.

I believe that line is generated by using the cubism.rule, Check out view-source:http://bost.ocks/mike/cubism/intro/demo-stocks.html. What you need is the following:

d3.select("body").append("div") .attr("class", "rule") .call(context.rule());

This uses context.rule() to acplish that, a d3/cubism function.

There's only one issue that the rule only covers the current screen. Once you scroll the screen up the rule (line) disappears.

本文标签: jquerySmooth Javascript mousemove similar to CubismjsStack Overflow