首页 > 解决方案 > Tooltip moves further from mouseover location as I scroll HTML page

问题描述

I'm using JQuery mouseover and CSS with "position: absolute;" to position the tooltip next to a particular matrix (x, y) location where the mouse is pointing to.

But as I scroll down, the tooltip moves further from the mouse pointer! :(

Here are the two images:

My fiddle: http://jsfiddle.net/kjx9z1uy/22/

My code snippet:

var colours = ['#F5F5F5', '#F5F5F5', '#F5F5F5', '#f4cd42', '#F5F5F5'];
var n = colours.length;
var w = 15;
var h = w * 4;

// create an offsreen canvas containing the desired coloured circles
var off = document.createElement('canvas');
off.width = n * w;
off.height = h;
var ctx = off.getContext('2d');  

// request mousemove events
var tipCanvas = document.getElementById("tip");
var tipCtx = tipCanvas.getContext("2d");
$("#canvas").mousemove(function (e) {
    handleMouseMove(e);
});

for (var i = 0; i < n; ++i) {
    ctx.beginPath();
        ctx.rect(i*w, 0, w, h)
        // Fill
    ctx.globalAlpha = "0.8"; // Opacity
    ctx.fillStyle = colours[i];
        ctx.fill();
        // Stroke
    ctx.globalAlpha = "1.0"; // Opacity reset
    //ctx.lineWidth = "1";
        ctx.strokeStyle = "black";
    ctx.stroke();
}

// get handles to the on-screen canvas
var canvas = document.getElementById('canvas');
var ctx2 = canvas.getContext('2d');

// create 3000 random points
var points = [];
var num_boxes = Math.floor(canvas.width/w)
                              * Math.floor(canvas.height/h)
console.log("# boxes: " + num_boxes)
for (var i = 0; i < Math.floor(canvas.width/w); ++i) {
    for (var j = 0; j < Math.floor(canvas.height/h); ++j) {
    var point_left = Math.floor(i*w);
    var point_top = Math.floor(j*h);
    var point_right = point_left + w;
    var point_bottom = point_top + h;
    points.push({
        c: i % n,
        x: point_left,
        y: point_top,
        w: w,
        h: h,
        r: point_right,
        b: point_bottom,
        text: "Data: (" + i + ", " + j + ") at (" + point_left + ", " + point_top + ", " + point_right + ", " + point_bottom + ")"
    });
  }
}

// copy points from the offscreen canvas into the on-page canvas
var t0 = Date.now();
ctx2.font = "bold 15px sans-serif";
ctx2.fillStyle = "black";
for (var i = 0; i < points.length; ++i) {
    var p = points[i];
    ctx2.drawImage(off, p.c * p.w, 0, p.w, p.h, p.x, p.y, p.w, p.h);
    ctx2.fillText(p.c, p.x, p.y+p.h);
        //console.log("RECT:", p.x, p.y, p.w, p.h)
}
var t1 = Date.now();
console.log("Elapsed time: " + (t1 - t0) + "ms");

// show tooltip when mouse hovers over dot
function handleMouseMove(e) {
    mouseX = parseInt(e.clientX);
    mouseY = parseInt(e.clientY);
    var hit = false;
        var adjustY = 15 + tipCanvas.height
    for (var i = 0; i < points.length; ++i) {
        var p = points[i];
        var withinX = (mouseX >= p.x) && (mouseX < p.r);
        var withinY = (mouseY >= p.y) && (mouseY < p.b);
        if (withinX && withinY) {
                if ((mouseX + tipCanvas.width) < canvas.width) {
                tipCanvas.style.left = mouseX + "px";
            }
            else {
                if (tipCanvas.width < canvas.width) {
                    tipCanvas.style.left = (mouseX - tipCanvas.width) + "px";
              }
              else {
                    tipCanvas.style.left = mouseX + "px";
              }
            }
                if (mouseY > adjustY) {
                tipCanvas.style.top = (mouseY - adjustY) + "px";
            }
            else {
                tipCanvas.style.top = (mouseY + adjustY) + "px";
            }
            tipCtx.clearRect(0, 0, tipCanvas.width, tipCanvas.height);
            tipCtx.fillText(p.text, 5, 15);
            tipCtx.fillText('Mouse: (' + mouseX + ', ' + mouseY + ")", 5, 30);
            hit = true;
        }
    }
    if (!hit) {
        tipCanvas.style.left = 0 - tipCanvas.width - 40 + "px";
    }
}
#tip {
    background-color: white;
    border: 1px solid blue;
    position: absolute;
    left: -200px;
    top: -100px;
}
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<canvas id="tip" width=200 height=40></canvas>
<canvas id="canvas" width="1000" height="15000"> </canvas>

标签: javascripthtmljquerycss

解决方案


因为您没有添加滚动高度。

在 handleMouseMove() 函数中,我将 window.scrollY 添加到 Y 轴值。

var colours = ['#F5F5F5', '#F5F5F5', '#F5F5F5', '#f4cd42', '#F5F5F5'];
var n = colours.length;
var w = 15;
var h = w * 4;

// create an offsreen canvas containing the desired coloured circles
var off = document.createElement('canvas');
off.width = n * w;
off.height = h;
var ctx = off.getContext('2d');  

// request mousemove events
var tipCanvas = document.getElementById("tip");
var tipCtx = tipCanvas.getContext("2d");
$("#canvas").mousemove(function (e) {
    handleMouseMove(e);
});

for (var i = 0; i < n; ++i) {
    ctx.beginPath();
        ctx.rect(i*w, 0, w, h)
        // Fill
    ctx.globalAlpha = "0.8"; // Opacity
    ctx.fillStyle = colours[i];
        ctx.fill();
        // Stroke
    ctx.globalAlpha = "1.0"; // Opacity reset
    //ctx.lineWidth = "1";
        ctx.strokeStyle = "black";
    ctx.stroke();
}

// get handles to the on-screen canvas
var canvas = document.getElementById('canvas');
var ctx2 = canvas.getContext('2d');

// create 3000 random points
var points = [];
var num_boxes = Math.floor(canvas.width/w)
                              * Math.floor(canvas.height/h)
console.log("# boxes: " + num_boxes)
for (var i = 0; i < Math.floor(canvas.width/w); ++i) {
    for (var j = 0; j < Math.floor(canvas.height/h); ++j) {
    var point_left = Math.floor(i*w);
    var point_top = Math.floor(j*h);
    var point_right = point_left + w;
    var point_bottom = point_top + h;
    points.push({
        c: i % n,
        x: point_left,
        y: point_top,
        w: w,
        h: h,
        r: point_right,
        b: point_bottom,
        text: "Data: (" + i + ", " + j + ") at (" + point_left + ", " + point_top + ", " + point_right + ", " + point_bottom + ")"
    });
  }
}

// copy points from the offscreen canvas into the on-page canvas
var t0 = Date.now();
ctx2.font = "bold 15px sans-serif";
ctx2.fillStyle = "black";
for (var i = 0; i < points.length; ++i) {
    var p = points[i];
    ctx2.drawImage(off, p.c * p.w, 0, p.w, p.h, p.x, p.y, p.w, p.h);
    ctx2.fillText(p.c, p.x, p.y+p.h);
        //console.log("RECT:", p.x, p.y, p.w, p.h)
}
var t1 = Date.now();
console.log("Elapsed time: " + (t1 - t0) + "ms");

// show tooltip when mouse hovers over dot
function handleMouseMove(e) {
    mouseX = parseInt(e.clientX);
    mouseY = parseInt(e.clientY);
    var hit = false;
    var adjustY = 15 + tipCanvas.height;
    var scrollY = window.scrollY;
    for (var i = 0; i < points.length; ++i) {
        var p = points[i];
        var withinX = (mouseX >= p.x) && (mouseX < p.r);
        var withinY = (mouseY >= p.y) && (mouseY < p.b);
        if (withinX && withinY) {
                if ((mouseX + tipCanvas.width) < canvas.width) {
                tipCanvas.style.left = mouseX + "px";
            }
            else {
                if (tipCanvas.width < canvas.width) {
                    tipCanvas.style.left = (mouseX - tipCanvas.width) + "px";
              }
              else {
                    tipCanvas.style.left = mouseX + "px";
              }
            }
                if (mouseY > adjustY) {
                tipCanvas.style.top = (mouseY - adjustY + scrollY) + "px";
            }
            else {
                tipCanvas.style.top = (mouseY + adjustY + scrollY) + "px";
            }
            tipCtx.clearRect(0, 0, tipCanvas.width, tipCanvas.height);
            tipCtx.fillText(p.text, 5, 15);
            tipCtx.fillText('Mouse: (' + mouseX + ', ' + mouseY + ")", 5, 30);
            hit = true;
        }
    }
    if (!hit) {
        tipCanvas.style.left = 0 - tipCanvas.width - 40 + "px";
    }
}
#tip {
    background-color: white;
    border: 1px solid blue;
    position: absolute;
    left: -200px;
    top: -100px;
}
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<canvas id="tip" width=200 height=40></canvas>
<canvas id="canvas" width="1000" height="15000"> </canvas>


推荐阅读