简体   繁体   中英

Invert X and Y coordinates on HTML5 canvas

I am working on an interface that has a HTML5 canvas on it, and I need to invert the X and Y coordinates when you select a position. I thought that subtracting the width of the canvas from the selected X position, and subtracting the height of the canvas from the selected Y position would invert the coordinates, but it is doing some very weird things.

The X and Y coords that log when you click in the top left corner of the canvas are X:324,Y:483 but theoretically, they should be X:650,Y:587 , and when you click in the bottom right corner, the logged coordinates are X:-325,Y:-103 when they theoretically should be X:0,Y:0 . As a side note, I do know that the dot that appears when you click is using the inverted coordinates, and that is fine.

Any help is appreciated especially if I am doing something horribly wrong. Thanks!

JS:

window.fires.directive('fieldDirective', ['ScoutService', '$interval', function(ScoutService, $interval) {
    var $scope = this;
    $scope.sServ = ScoutService;
    $interval(function(){
        $scope.col = ScoutService.getAllianceColor();
    },1);
    return {
        restrict: "A",
        link: function(scope, element) {
            element.bind('mousedown', function(event) {
                var canvas = document.getElementById('field');
                var context = canvas.getContext('2d');
                if(event.offsetX !== undefined) {
                    $scope.xPos = 650 - event.offsetX;
                    $scope.yPos = 587 - event.offsetY;
                    $scope.sServ.sendLobCoords(xPos, yPos);
                } else {
                    $scope.xPos = 650 - event.layerX - event.currentTarget.offsetLeft;
                    $scope.yPos = 587 - event.layerY - event.currentTarget.offsetTop;
                    $scope.sServ.sendLobCoords(xPos, yPos);
                }
                console.log('red'+$scope.xPos + ' ' + $scope.yPos);
                canvas.width = canvas.width;
                context.arc($scope.xPos, $scope.yPos, 12, 0, Math.PI*2);
                context.fillStyle = '#FFFF00';
                context.fill();
                context.lineWidth = 3;
                context.strokeStyle = '#B2B200';
                context.stroke();
                context.closePath();
            });
        }
    };
}]);

HTML:

<canvas field-directive id="field" ng-class="{'field-red': sCtrl.fieldColor === 'red', 'field-blue': sCtrl.fieldColor === 'blue'}" width="650" height="587">Your browser does not support the HTML5 Canvas Element.  Please use a supported browser such as Google Chrome 4.0+ or FireFox 2.0+.</canvas>
  • First make the x and y relative to the canvas element itself by subtracting the position of the element from the client coordinates
  • Then subtract the adjusted x from width, y from height
  • If you need an absolute position, add back the offsets

Example modification:

element.bind('mousedown', function(event) {
    var canvas = document.getElementById('field');
    var context = canvas.getContext('2d');

    // get element position
    var rect = canvas.getBoundingClientRect();

    // get inversed coordinates: enable code after comment if abs. pos.
    var ix = canvas.width - (event.clientX - rect.left); // + rect.left
    var iy = canvas.height - (event.clientY - rect.top); // + rect.top

    ...update $scope here etc...
});

Live demo:

 var canvas = document.getElementById('field'); canvas.addEventListener('mousemove', function(event) { var canvas = document.getElementById('field'); var context = canvas.getContext('2d'); // get element position var rect = canvas.getBoundingClientRect(); // get inversed coordinates: enable code after comment if abs. pos. var ix = canvas.width - (event.clientX - rect.left); // + rect.left var iy = canvas.height - (event.clientY - rect.top); // + rect.top // draw something context.clearRect(0, 0, 500, 180); context.fillRect(ix - 2, iy - 2, 4, 4); }); 
 canvas {border: 1px solid #007} 
 <canvas id="field" width=500 height=180></canvas> 

I think the problem is arising because offsetX and offsetY are tied to the item that was clicked. In this case whatever "element" is. If the click event were tied directly to the canvas I think your code would work.

Try binding the event to the canvas itself or use the position of the element with the click behavior and the position of the canvas to do corrective math.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM