Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moving and rotating an object according to mouse clickt?

I am trying to move an object in a way that it rotates as the same direction of the mouse click and also move to the location of the mouse click. So far I arranged movement but I think there is something wrong with the angle because it does not rotate the way I do. Where am I making a mistake? How can I fix it?

var theThing = document.querySelector("#thing");
var container = document.querySelector("#contentContainer");
var triangle = document.querySelector("#triangle");
container.addEventListener("click", getClickPosition, false);

function getClickPosition(e) {
  var xPosition = e.clientX;
  var yPosition = e.clientY;
  var translate3dValue = "translate3d(" + xPosition + "px," + yPosition +
    "px,0)";
  var spx = document.querySelector("#triangle").clientWidth / 2;
  var spy = document.querySelector("#triangle").clientHeight / 2;
  var angle = Math.atan2(yPosition - spy, xPosition - spx) * 180 /
    Math.PI;
  if (angle < 0) {
    angle = 360 - (-angle);
  }

  theThing.style.transform = translate3dValue;
  theThing.style.transform += "rotate(" + angle + "deg)"
}
body {
  background-color: #FFF;
  padding: 0;
  margin: 0;
}

#contentContainer {
  width: 500px;
  height: 500px;
  border: 15px #EDEDED solid;
  overflow: hidden;
  background-color: #F2F2F2;
  cursor: pointer;
}

#thing {
  width: 75px;
  height: 75px;
  background-color: rgb(255, 207, 0);
  border-radius: 0%;
  transform: translate3d(200px, 100px, 0);
  transition: transform.2s ease-in;
}

#triangle {
  width: 0;
  height: 0;
  border-left: 30px solid transparent;
  border-right: 45px solid transparent;
  border-bottom: 75px solid black;
}
<div id="contentContainer">
  <div id="thing">
    <div id="triangle">
    </div>
  </div>
</div>
like image 248
TheOrion Avatar asked Jan 31 '19 06:01

TheOrion


2 Answers

You'll have to tweak it a little and replace hard coded values. Also, this is not meant to be efficient or elegant in any way.

<html>

<head>
    <title>Move to click position</title>
    <style>
        body {
            background-color: #FFF;
            padding: 0;
            margin: 0;
        }

        #contentContainer {
            width: 500px;
            height: 500px;
            /* border: 15px #EDEDED solid; */
            overflow: hidden;
            background-color: #F2F2F2;
            cursor: pointer;
            display: block;

        }

        #thing {
            width: 75px;
            height: 75px;
            background-color: rgb(255, 207, 0);
            border-radius: 0%;
            /* transform: translate3d(200px, 100px, 0); */
            transition: transform.2s ease-in;
            /* transform-origin: 0% 0% */
        }

        #triangle {
            width: 0;
            height: 0;
            border-left: 30px solid transparent;
            border-right: 45px solid transparent;
            border-bottom: 75px solid black;
        }
    </style>
</head>

<body>
    <div id="contentContainer">
        <div id="thing">
            <div id="triangle">
            </div>
        </div>
    </div>
    <script>
        var theThing = document.querySelector("#thing");
        var container = document.querySelector("#contentContainer");
        var triangle = document.querySelector("#triangle");
        container.addEventListener("click", getClickPosition, false);
        // container.addEventListener("mousemove", getClickPosition, false);

        // we'll keep tarck of a vector going from center to head 
        var center = {
            'x': 75 / 2.0,
            'y': 75 / 2.0
        }
        var head = {
            'x': 75 / 2.0,
            'y': 0.0
        }

        function norm(vx, vy) {
            return Math.sqrt(vx * vx + vy * vy);
        }

        function normalize(vx, vy) {
            d = norm(vx, vy);
            return { 'x': vx / d, 'y': vy / d };
        }

        function dot(vx, vy, wx, wy) {
            return vx * wx + vy * wy;
        }

        function det(vx, vy, wx, wy) {
            return vx * wy - vy * wx;
        }

        // compute clockwise angle between two vectors
        function vwAngle(vx, vy, wx, wy) {
            return Math.atan2(det(vx, vy, wx, wy), dot(vx, vy, wx, wy));
        }

        function getClickPosition(e) {
            var xPosition = e.clientX;
            var yPosition = e.clientY;
            console.log(xPosition, yPosition);
            var spx = document.querySelector("#triangle").clientWidth / 2.0;
            var spy = document.querySelector("#triangle").clientHeight / 2.0;
            console.log(spx, spy);
            console.log();

            // vector from center to mouse
            var m = normalize(
                xPosition - center.x,
                yPosition - center.y
            );

            // v is a vector fron center to head
            var vNormalized = normalize(head.x - center.x, head.y - center.y);

            // clockwise angle between vectors m and v
            var between = -vwAngle(m.x, m.y, vNormalized.x, vNormalized.y);


            // Update vector v by updated head:

            // rotate v around point 
            var cosb = Math.cos(between);
            var sinb = Math.sin(between);
            var vRotated = {
                'x': cosb * vNormalized.x - sinb * vNormalized.y,
                'y': sinb * vNormalized.x + cosb * vNormalized.y
            };
            var d = norm(head.x - center.x, head.y - center.y);
            head.x = center.x + vRotated.x * d;
            head.y = center.y + vRotated.y * d;


            // translation:
            var dx = xPosition - center.x
            var dy = yPosition - center.y
            center.x = xPosition - 75 / 2.0;
            center.y = yPosition - 75 / 2.0;
            head.x += dx;
            head.y += dy;
            var translate3dValue = "translate3d(" + center.x + "px," + center.y + "px,0)";
            theThing.style.transform = translate3dValue;
            theThing.style.transform += "rotate(" + (between * 180 / Math.PI) + "deg)";

        }

    </script>
</body>
</body>

</html>
like image 180
sam46 Avatar answered Oct 08 '22 02:10

sam46


I seem to find a way to work it out. Even though it is not perfect, I think it is working now. I used offset method in order to get the center of the image and find the angle between the center and the mouse using Math.atan2 method.

var theThing = document.querySelector("#thing");
var container = document.querySelector("#contentContainer");
var triangle = document.querySelector("#triangle");
container.addEventListener("click", getClickPosition, false);

function getClickPosition(e) {
  var xPosition = e.clientX;
  var yPosition = e.clientY;
  var translate3dValue = "translate3d(" + xPosition + "px," + yPosition + "px,0)";
  var spx = document.querySelector("#thing").clientWidth / 2;
  var spy = document.querySelector("#thing").clientHeight / 2;
  var box = $("#thing");
  var boxCenter = [box.offset().left + box.width() / 2, box.offset().top + box.height() / 2];
  var angle = Math.atan2(xPosition - boxCenter[0], -(yPosition - boxCenter[1])) * (180 / Math.PI);
  theThing.style.transform = translate3dValue;
  theThing.style.transform += "rotate(" + angle + "deg)"

}
body {
  background-color: #FFF;
  padding: 0;
  margin: 0;
}

#contentContainer {
  width: 550px;
  height: 350px;
  border: 15px #EDEDED solid;
  overflow: hidden;
  background-color: #F2F2F2;
  cursor: pointer;
}

#thing {
  width: 75px;
  height: 75px;
  background-color: rgb(255, 207, 0);
  border-radius: 0%;
  transform: translate3d(200px, 100px, 0);
  transition: transform.8s ease-in;
}

#triangle {
  width: 0;
  height: 0;
  border-left: 30px solid transparent;
  border-right: 45px solid transparent;
  border-bottom: 75px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="contentContainer">
  <div id="thing">
    <div id="triangle">
    </div>
  </div>
</div>
like image 1
TheOrion Avatar answered Oct 08 '22 01:10

TheOrion