<!doctype html> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Coordinates Doctest</title> <link rel="stylesheet" href="./3rdparty/highlight/styles/default.css"> <link rel="stylesheet" href="../css/doctest.css"> <script src="./3rdparty/highlight/highlight.pack.js"></script> <script src="../dist/iwmlib.3rdparty.js"></script> <script src="../dist/iwmlib.js"></script> <script> function drawPolygons() { canvas.width = main.getBoundingClientRect().width let context = canvas.getContext('2d') context.clearRect(0, 0, canvas.width, canvas.height) let stage = scatterContainer.polygon stage.draw(context, { stroke: '#FF0000' }) for (let scatter of scatterContainer.scatter.values()) { let polygon = scatter.polygon polygon.draw(context, { stroke: '#FF0000' }) } } function animate(callback) { requestAnimationFrame((dt) => { drawPolygons() callback() animate(callback) }) } </script> </head> <body onload="Doctest.run()"> <h1> Coordinates </h1> <p> To position objects in defined spatial relationships presupposes a clear understanding of the involved coordinate systems. Unfortunately, several systems with several conventions are involved: <a href="https://javascript.info/coordinates">DOM & CSS</a>, <a href="https://www.sarasoueidan.com/blog/svg-coordinate-systems/SVG">SVG</a>, <a href="https://www.w3schools.com/graphics/canvas_coordinates.asp">Canvas</a> </p> <p> We need a common reference system to switch between these coordinate systems. As the uttermost context, the browser page coordinate system is the most natural one. A simple API was long missing but has now been established in most modern browsers with <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/convertPointFromNoteToPage">window.convertPointFromNoteToPage</a> and the inverse <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/convertPointFromPageToNode">window.convertPointFromPageToNode</a>. Although MDN Web Docs warns about their Non-standard nature the methods work in browsers targeted by the IWM Browser project. This doctest assures that this assumption can be tested. </p> <p>Let's look at a scatter object with a rotatable local coordinate system. We try to follow a point in this local coordinate system by showing a marker outside the scatter that follows the point. </p> <div id="main" class="grayBorder interactive" style="position: relative; width: 100%; height: 280px;"> <!-- Note that we need to set draggable to false to avoid conflicts. The DOM elements must also be positioned absolutely. --> <img id="women" draggable="false" style="position: absolute;" src="examples/women.jpeg" /> <canvas id="canvas" height="280" style="z-index: 100000; pointer-events: none; position: absolute; border: 1px solid red;"> Canvas not supported. </canvas> </div> <script class="doctest"> let dx = 44 let app = new App() let scatterContainer = new DOMScatterContainer(main) let angle = 15 let image = document.getElementById('women') // The DOMScatter needs initial width and height. Therefore we // define the scatter when the image size is known, i.e. after loading... image.onload = (e) => { let scatter = new DOMScatter(image, scatterContainer, { x: dx, y: 44, width: e.target.naturalWidth, height: e.target.naturalHeight, rotationDegrees: angle, throwVisibility: 88, minScale: 0.5, maxScale: 1.5 }) dx += 300 angle = -angle } app.run() function followPoint() { let context = canvas.getContext('2d') let localPoint = { x: 100, y: 100 } let globalPoint = convertPointFromNodeToPage(image, localPoint.x, localPoint.y) let canvasPoint = convertPointFromPageToNode(canvas, globalPoint.x, globalPoint.y) context.strokeStyle = 'red' context.beginPath() context.arc(canvasPoint.x, canvasPoint.y, 12, 0, Math.PI * 2) context.stroke() } animate(followPoint) </script> </body>