Mouse positions


Tracking the pointer

The eyes track the position of the mouse pointer as it moves through the graphic below. This is a homage to xeyes.
image of a circle
Your browser did not display the SVG image. It is showing a standard image as a fallback.
Source of xeyes1.svg:Hide line numbers
01: <svg version="1.1" baseProfile="full"
02:      xmlns="http://www.w3.org/2000/svg"
03:      width="510px" height="210px" viewBox="0 0 510 210"
04:      stroke="black" stroke-width="0.5px" 
05:      onmousemove="moveEyes(evt)">
06: 
07: <script>
08: // <![CDATA[
09: 
10: var svgNS = "http://www.w3.org/2000/svg";
11: var xlinkNS = "http://www.w3.org/1999/xlink";
12: 
13: function moveEyes(evt){   
14: 
15:    // Get the mouse location:
16:    var mousex = evt.clientX;
17:    var mousey = evt.clientY;
18:    
19:    // Work out correct pupil position for left eye, and update:
20:    var dx=mousex-105;
21:    var dy=mousey-105;
22:    var dist = Math.sqrt(dx*dx + dy*dy); 
23:    if (dist > 70) {
24:       dx = dx*70/dist;
25:       dy = dy*70/dist;
26:    }
27:    var left=document.getElementById("LeftPupil");
28:    left.setAttributeNS(null, "cx", dx+105);
29:    left.setAttributeNS(null, "cy", dy+105);
30:    
31:    // Work out correct pupil position for right eye, and update:
32:    var dx=mousex-405;
33:    var dy=mousey-105;
34:    var dist = Math.sqrt(dx*dx + dy*dy); 
35:    if (dist > 70) {
36:       dx = dx*70/dist;
37:       dy = dy*70/dist;
38:    }
39:    var right=document.getElementById("RightPupil");
40:    right.setAttributeNS(null, "cx", dx+405);
41:    right.setAttributeNS(null, "cy", dy+105);
42: }
43: 
44: // ]]>
45: </script>
46: 
47: <circle r="100" cx="105" cy="105" stroke="black" stroke-width="10px" fill="white"/>
48: <circle r="100" cx="405" cy="105" stroke="black" stroke-width="10px" fill="white"/>
49: <circle id="LeftPupil" r="20" cx="105" cy="105" fill="black"/>
50: <circle id="RightPupil" r="20" cx="405" cy="105" fill="black"/>
51: 
52: </svg>

The important thing to take away from the above example is that in lines 16 and 17 we get the position of the mouse from the pointer. The values of evt.clientX evt.clientY are the number of x- and y-coordinates of the mouse's location measured in pixels from the edge of the graphic.

Pixel coordinates are bad:

We observe that the code above breaks when we mess with the graphic. In the graphic below, we have kept the code the same except for increasing the width and height by 50%. Note the errors when moving over the rightmost eye.
image of a circle
Your browser did not display the SVG image. It is showing a standard image as a fallback.

The reason for the error is that the standard coordinates of the SVG are now 50% larger than a pixel.

Source of xeyes2.svg:Hide line numbers
01: <svg version="1.1" baseProfile="full"
02:      xmlns="http://www.w3.org/2000/svg"
03:      width="765px" height="315px" viewBox="0 0 510 210"
04:      stroke="black" stroke-width="0.5px" 
05:      onmousemove="moveEyes(evt)">
06: 
07: <script>
08: // <![CDATA[
09: 
10: var svgNS = "http://www.w3.org/2000/svg";
11: var xlinkNS = "http://www.w3.org/1999/xlink";
12: 
13: function moveEyes(evt){   
14: 
15:    // Get the mouse location:
16:    var mousex = evt.clientX;
17:    var mousey = evt.clientY;
18:    
19:    // Work out correct pupil position for left eye, and update:
20:    var dx=mousex-105;
21:    var dy=mousey-105;
22:    var dist = Math.sqrt(dx*dx + dy*dy); 
23:    if (dist > 70) {
24:       dx = dx*70/dist;
25:       dy = dy*70/dist;
26:    }
27:    var left=document.getElementById("LeftPupil");
28:    left.setAttributeNS(null, "cx", dx+105);
29:    left.setAttributeNS(null, "cy", dy+105);
30:    
31:    // Work out correct pupil position for right eye, and update:
32:    var dx=mousex-405;
33:    var dy=mousey-105;
34:    var dist = Math.sqrt(dx*dx + dy*dy); 
35:    if (dist > 70) {
36:       dx = dx*70/dist;
37:       dy = dy*70/dist;
38:    }
39:    var right=document.getElementById("RightPupil");
40:    right.setAttributeNS(null, "cx", dx+405);
41:    right.setAttributeNS(null, "cy", dy+105);
42: }
43: 
44: // ]]>
45: </script>
46: 
47: <circle r="100" cx="105" cy="105" stroke="black" stroke-width="10px" fill="white"/>
48: <circle r="100" cx="405" cy="105" stroke="black" stroke-width="10px" fill="white"/>
49: <circle id="LeftPupil" r="20" cx="105" cy="105" fill="black"/>
50: <circle id="RightPupil" r="20" cx="405" cy="105" fill="black"/>
51: 
52: </svg>

Fixing the error and coordinate changes:

As we have discussed, each element (or tag) of the SVG document has a local coordinate system. From any element, we can extract a matrix which describes how to convert from local coordinates to screen coordinates (measured in pixels from the left and top). We can use this to update the coordinates.

image of a circle
Your browser did not display the SVG image. It is showing a standard image as a fallback.
Source of xeyes3.svg:Hide line numbers
01: <svg version="1.1" baseProfile="full"
02:      xmlns="http://www.w3.org/2000/svg"
03:      width="765px" height="315px" viewBox="0 0 510 210"
04:      stroke="black" stroke-width="0.5px" 
05:      onmousemove="moveEyes(evt)">
06: 
07: <script>
08: // <![CDATA[
09: 
10: var svgNS = "http://www.w3.org/2000/svg";
11: var xlinkNS = "http://www.w3.org/1999/xlink";
12: 
13: function moveEyes(evt){   
14: 
15:    // Get the mouse location:
16:    var position = document.rootElement.createSVGPoint();
17:    position.x = evt.clientX;
18:    position.y = evt.clientY;
19:    var matrix = document.rootElement.getScreenCTM();
20:    var correctPosition=position.matrixTransform(matrix.inverse());
21:    var mousex = correctPosition.x;
22:    var mousey = correctPosition.y;
23:    
24:    // Work out correct pupil position for left eye, and update:
25:    var dx=mousex-105;
26:    var dy=mousey-105;
27:    var dist = Math.sqrt(dx*dx + dy*dy); 
28:    if (dist > 70) {
29:       dx = dx*70/dist;
30:       dy = dy*70/dist;
31:    }
32:    var left=document.getElementById("LeftPupil");
33:    left.setAttributeNS(null, "cx", dx+105);
34:    left.setAttributeNS(null, "cy", dy+105);
35:    
36:    // Work out correct pupil position for right eye, and update:
37:    var dx=mousex-405;
38:    var dy=mousey-105;
39:    var dist = Math.sqrt(dx*dx + dy*dy); 
40:    if (dist > 70) {
41:       dx = dx*70/dist;
42:       dy = dy*70/dist;
43:    }
44:    var right=document.getElementById("RightPupil");
45:    right.setAttributeNS(null, "cx", dx+405);
46:    right.setAttributeNS(null, "cy", dy+105);
47: }
48: 
49: // ]]>
50: </script>
51: 
52: <circle r="100" cx="105" cy="105" stroke="black" stroke-width="10px" fill="white"/>
53: <circle r="100" cx="405" cy="105" stroke="black" stroke-width="10px" fill="white"/>
54: <circle id="LeftPupil" r="20" cx="105" cy="105" fill="black"/>
55: <circle id="RightPupil" r="20" cx="405" cy="105" fill="black"/>
56: 
57: </svg>

The significant code in in lines 15-21. The coordinate change is captured by the root (<svg>) element. There is a coordinate change going on to adjust for the fact that the image dimensions are 50% larger than the local coordinates.

We deal with this in a standard way. We create an object called a SVGPoint in line 16, and we set its x and y coordinates in lines 17-18. Then we find the matrix which changes coordinates from the SVG's coordinates to the screen coordinates (pixels from the left and top border of the image). We actually want to convert the other way, which we do in line 20 by taking an inverse to the matrix and applying it to the mouse position. Then we extract the new coordinate values in lines 21 and 22.

Embedding the graphic in a webpage:

As a remark, we note one problem with this example is that it only detects mouse movement within the image. If you embed the image in a webpage, and also include some ECMAScript code, you can get register movements within the whole webpage (but not the whole user's screen). See the xeyes demo.

References:

We do some string manipulating above. Here are some references related to strings.

This presentation is part of a SVG Tutorial for Mathematics Students.


© 2013 by W. Patrick Hooper. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. Creative Commons License Valid XHTML 1.0 Strict Valid CSS!