问题
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>
回答1:
- 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>
回答2:
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.
来源:https://stackoverflow.com/questions/28574628/invert-x-and-y-coordinates-on-html5-canvas