0

I have a bunch of SVG path shapes on a Canvas.

But initially I transformed the canvas's coordinate system, so that it only just fits the unit circle, and y increases upwards. So e.g. (.9, .9) would be towards the top right of the Canvas:

$(document).ready(function() {  
    var canvas = document.getElementById("myCanvas");
    var ctx = canvas.getContext("2d");

    window.requestAnimationFrame(vsync);

    function vsync() {
        var canvas = document.getElementById("myCanvas");
        var W = window.innerWidth;
        var H = window.innerHeight;
        canvas.width  = W;
        canvas.height = H;

        var ctx = canvas.getContext("2d");

        // (0,0) at center of canvas
        // y increases up
        // unit circle fits on canvas with margin 0.1
        ctx.translate(W/2, H/2);

        var scale = Math.min(W/2,H/2) / 1.1;
        ctx.scale(scale,-scale);

I wish to hit-test mouse-clicks to check whether they are hitting my path objects.

I'm probably going to be doing my own maths rather than using isPointInPath. But whichever way I go about it, I need the mouse xy in the transformed coordinate system.

Of course it would only be a few lines to replicate the transform for the mouse point. But that's bad coding style. It creates the future opportunity for divergence. If I wanted to change the transform I would need to do it in two different places -- that's a step away from maintainability.

Is there any way to do this cleanly?

EDIT:
Get transformed coordinates with canvas
How do I get the coordinates of a mouse click on a canvas element?

Community
  • 1
  • 1
P i
  • 29,020
  • 36
  • 159
  • 267
  • Voted as duplicate. Not sure where you get the bad coding style from, but tracking mouse and transforms is currently the only way to solve this. In the future we will probably have access to the [SVGMatrix](https://developer.mozilla.org/en-US/docs/Web/API/SVGMatrix?redirectlocale=en-US&redirectslug=DOM%2FSVGMatrix) object for canvas as well, but until then.. –  Apr 13 '15 at 10:24
  • Feel free to check out [transformation-matrix](https://github.com/epistemex/transformation-matrix-js) which allows you to bind context to it (ie. having a single place to keep track of transformations). –  Apr 13 '15 at 10:27

1 Answers1

1

What you want to do is two different things, so it has to be changed in two different places. Changing coordination system of canvas is transforming point from your view into canvas coordination. Whereas transforming mouse coordination to your view coordination is a reverse operation.

Hence You cannot make the same function for both.

Good way of doing this would be defining two functions like:

convertCoordinationsFromFooToBar(x, y)

and

convertCoordinationsFromBarToFoo(x, y).

But notice that this way you can't use canvas translate and scale for transforms, you should explicitly call transform function on every coordinate you pass to canvas drawing functions.

Rafał Łużyński
  • 7,083
  • 5
  • 26
  • 38