nanobar
nanobar

Reputation: 66355

Move a coordinate along an angled line using mouse movement

Please run the code snippet below - you will see an angled line derived from the corners of a box. Given mouse movement, I would like to move the marker along this line - where either:

So far I haven't got anywhere but I'll update if I do and many thanks for any help.

PS doesn't really matter if it doesn't move exactly along the line - it's the algorithm to move along an angle I'm interested in.

Fiddle: http://jsfiddle.net/ngr3dbhx/3/

var boxEl = document.getElementById('box');
var lineEl = document.getElementById('line');
var markerEl = document.getElementById('marker');
var rad, deg;

// Draw an angled line for demonstration purposes.
function getElementOffset (el) {
    var rect = el.getBoundingClientRect();
    var docEl = document.documentElement;

    var rectTop = rect.top + window.pageYOffset - docEl.clientTop;
    var rectLeft = rect.left + window.pageXOffset - docEl.clientLeft;

    return {
        top: rectTop,
        left: rectLeft
    };
}

function calcAndDrawAngle () {
    var boxOffset = getElementOffset(boxEl);

    var x1 = boxOffset.left;
    var y1 = boxOffset.top;

    var x2 = boxOffset.left + boxEl.offsetWidth;
    var y2 = boxOffset.top + boxEl.offsetHeight;

    var deltaX = x2 - x1;
    var deltaY = y2 - y1;

    rad = Math.atan2(deltaY, deltaX);
    deg = rad * (180 / Math.PI);

    lineEl.style.transform = 'rotate(' + deg + 'deg) translate(-50%, 0)';  
}

// On mouse move I want to move the marker along the anged line..
// Do something with rad or deg?
document.addEventListener('mousemove', function (e) {
    markerEl.style.top = e.clientY + 'px';
    markerEl.style.left = e.clientX + 'px';
});

calcAndDrawAngle();
window.addEventListener('resize', calcAndDrawAngle);
html,
body {
    margin: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
}

#box {
    position: absolute;
    top: 20%;
    left: 30%;
    width: 35%;
    height: 30%;
    border: 1px solid #999;
}

#line {
    position: absolute;
    top: 0;
    left: 0;
    transform-origin: top left;
    height: 1px;
    width: 9999em;
    background-color: black;
}

#marker {
    position: absolute;
    width: 8px;
    height: 8px;
    background-color: red;
}
<div id="box">
    <div id="line"></div>
</div>
<div id="marker"></div>

Upvotes: 1

Views: 159

Answers (2)

Mario A
Mario A

Reputation: 3363

you mean this?

https://jsfiddle.net/2q1nLh3q/1/

The formula is basic mathematics:

y = k * x + d

Where k is deltaY / deltaX and d is the point where the line crosses the y axis.

So your function could look like this:

document.addEventListener('mousemove', function (e) {
    window.requestAnimationFrame(function() {

        var boxOffset = getElementOffset(boxEl);

        var k =  boxEl.offsetHeight / boxEl.offsetWidth;
        var d = boxOffset.top - boxOffset.left * k; 

        var mouseY = k * e.clientX  + d;

        markerEl.style.top = mouseY + 'px';
        markerEl.style.left = e.clientX + 'px';
    });
});

Upvotes: 1

Amit
Amit

Reputation: 46323

Using fairly simple math, calculate y for any x within limited range (subtracted 4 to place rectangle at center):

//var canvas = document.getElementById('canvas');
var boxEl = document.getElementById('box');
var lineEl = document.getElementById('line');
var markerEl = document.getElementById('marker');
var rad, deg;
var coords;

// Draw an angled line for demonstration purposes.
function getElementOffset (el) {
    var rect = el.getBoundingClientRect();
    var docEl = document.documentElement;

    var rectTop = rect.top + window.pageYOffset - docEl.clientTop;
    var rectLeft = rect.left + window.pageXOffset - docEl.clientLeft;

    return {
        top: rectTop,
        left: rectLeft
    };
}

function calcAndDrawAngle () {
    var boxOffset = getElementOffset(boxEl);

    var x1 = boxOffset.left;
    var y1 = boxOffset.top;

    var x2 = boxOffset.left + boxEl.offsetWidth;
    var y2 = boxOffset.top + boxEl.offsetHeight;

    coords = [{x:x1,y:y2},{x:x2,y:y1}];
    var deltaX = x2 - x1;
    var deltaY = y2 - y1;

    rad = Math.atan2(deltaY, deltaX);
    deg = rad * (180 / Math.PI);

    lineEl.style.transform = 'rotate(' + deg + 'deg) translate(-50%, 0)';  
}

// On mouse move I want to move the marker along the anged line..
// Do something with rad or deg?
document.addEventListener('mousemove', function (e) {
    var x = Math.min(Math.max(e.clientX, coords[0].x), coords[1].x) - 4;
    var y = coords[0].y + ((coords[1].y - coords[0].y) * (coords[1].x - x) / (coords[1].x - coords[0].x));
    markerEl.style.top = y + 'px';
    markerEl.style.left = x + 'px';
});

calcAndDrawAngle();
window.addEventListener('resize', calcAndDrawAngle);
html,
body {
    margin: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
}

#box {
    position: absolute;
    top: 20%;
    left: 30%;
    width: 35%;
    height: 30%;
    border: 1px solid #999;
}

#line {
    position: absolute;
    top: 0;
    left: 0;
    transform-origin: top left;
    height: 1px;
    width: 9999em;
    background-color: black;
}

#marker {
    position: absolute;
    width: 8px;
    height: 8px;
    background-color: red;
}
<div id="box">
    <div id="line"></div>
</div>
<div id="marker"></div>

Upvotes: 1

Related Questions