0

I have a webpage with a box that can be moved around on the page (via JavaScript) that contains many large SVG diagrams and thus needs a scrollbar to allow viewing all content in it. I need to know the coordinate the user clicks inside the box; the distance between the top-left corner and the click position inside the inner content area. I only know MouseEvent.pageX, clientX and screenX but these do not provide the correct result. Reduced to the minimum to show the situation:

        <div class="content">
                The&nbsp;content&nbsp;is&nbsp;to&nbsp;wide&nbsp;to&nbsp;show&nbsp;in&nbsp;this&nbsp;box.<br>
                The&nbsp;content&nbsp;is&nbsp;to&nbsp;wide&nbsp;to&nbsp;show&nbsp;in&nbsp;this&nbsp;box.<br>
                The&nbsp;content&nbsp;is&nbsp;to&nbsp;wide&nbsp;to&nbsp;show&nbsp;in&nbsp;this&nbsp;box.<br>
                The&nbsp;content&nbsp;is&nbsp;to&nbsp;wide&nbsp;to&nbsp;show&nbsp;in&nbsp;this&nbsp;box.<br>
                The&nbsp;content&nbsp;is&nbsp;to&nbsp;wide&nbsp;to&nbsp;show&nbsp;in&nbsp;this&nbsp;box.<br>
                The&nbsp;content&nbsp;is&nbsp;to&nbsp;wide&nbsp;to&nbsp;show&nbsp;in&nbsp;this&nbsp;box.<br>
                The&nbsp;content&nbsp;is&nbsp;to&nbsp;wide&nbsp;to&nbsp;show&nbsp;in&nbsp;this&nbsp;box.<br>
                The&nbsp;content&nbsp;is&nbsp;to&nbsp;wide&nbsp;to&nbsp;show&nbsp;in&nbsp;this&nbsp;box.
        </div>

And the corresponding CSS:

.content {
        border: solid 1px;
        height: 100px;
        width: 100px;
        overflow: auto;
        top: 50px;
        left: 200px;
        position: absolute;
}

Answer: Thanks Yogi and flowton!

The combination of event.offsetX/Y + event.target.scrollLeft/Top did the trick!

Teddy
  • 993
  • 10
  • 20
  • What did you try? Where are you stuck? – cloned May 03 '22 at 13:56
  • 1
    Here is a [jsFiddle Demo](https://jsfiddle.net/ydt3eLxm/2/) with a draggable and scrollable dialog box that displays click position information. Should be enough to get you started. – Yogi May 03 '22 at 15:49
  • Does this answer your question? [Find mouse position relative to element](https://stackoverflow.com/questions/3234256/find-mouse-position-relative-to-element) – Daniel Beck May 04 '22 at 16:56

1 Answers1

3

I've reworked my answer, it now takes scrollTop of the demoBox into account :-) The snippet here can cause wrong values to be displayed if the snippet container was scrolled .. if you have this situation in your project too you'd have to fetch all scrollTop values of all containers in the hierarchy!

function reposition(x,y){
    let demoBox = document.querySelector('#demo-box');
    demoBox.style.left = x;
    demoBox.style.top = y;
}

// this function was leeched from ppk (http://quirksmode.org)
function findPos(obj) {
    var curleft = curtop = 0;
    if (obj.offsetParent) {
        do {
            curleft += obj.offsetLeft;
            curtop += obj.offsetTop;
        } while (obj = obj.offsetParent); // = != == - I know! :)
    }
    return [curleft,curtop];
}

function showRelativePosition(evt){
    let box = document.querySelector('#demo-box');// evt.target may be a DOM element inside the container so is unreliable
    let pos = findPos(box);
    let cx = evt.clientX; // evt.pageX
    let cy = evt.clientY; // evt.pageY
    let ox = cx - pos[0];
    let oy = cy - pos[1];
    let st = box.scrollTop;
    let out = document.querySelector('#output');
    out.innerHTML = `<div>You clicked at ${cx}, ${cy} inside box at ${pos[0]}, ${pos[1]}.</div><div>That is ${ox}, ${oy} inside the box and ${ox}, ${oy+st} inside the content.</div>`;
}

document.addEventListener( 'DOMContentLoaded', function(){
    let demoBox = document.querySelector('#demo-box');
    demoBox.addEventListener( 'click', showRelativePosition );
    for(let i = 0; i < 23; i++){
        demoBox.innerHTML += '<p>Lorem ipsum dolor sit amet…</p>';
    }
} );
body{ position: relative; }
nav{ display: flex; flex-direction: row; flex-wrap: nowrap; justify-content: space-between; }
nav>button{ 
    flex: 0 0 auto;
    padding: 4px;
    margin: 0 2px 4px;
}
#demo-box{ 
    position: absolute;
    left: 1em;
    top: 3em;
    margin: 1em; 
    border-radius: 8px; 
    border: 1px solid #888; 
    width: 18em; 
    height: 14em; 
    overflow: scroll;
}
#output{ text-align: center; }
<nav>
    <button onclick="reposition('1em','3em')">Pos A</button>
    <button onclick="reposition('6em','6em')">Pos B</button>
    <button onclick="reposition('14em','14em')">Pos C</button>
    <button onclick="reposition('8em','5em')">Pos D</button>
    <button onclick="reposition('1em','5em')">Pos E</button>
</nav>
<div id="output"></div>
<div id="demo-box">Demo Box</div>
flowtron
  • 854
  • 7
  • 20