iwmlib/lib/coordinates.html

116 lines
5.1 KiB
HTML
Raw Permalink Normal View History

<!DOCTYPE html>
2019-03-21 09:57:27 +01:00
<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)
2019-03-21 09:57:27 +01:00
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' })
}
2019-03-21 09:57:27 +01:00
}
function animate(callback) {
requestAnimationFrame((dt) => {
drawPolygons()
callback()
animate(callback)
})
}
</script>
</head>
2019-03-21 09:57:27 +01:00
<body onload="Doctest.run()">
<h1><a href="index.html">lib.</a>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 &amp; 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
2019-03-21 09:57:27 +01:00
must also be positioned absolutely. -->
<img id="women" draggable="false" style="position: absolute" src="examples/women.jpeg" />
2019-03-21 09:57:27 +01:00
<canvas
id="canvas"
height="280"
style="z-index: 100000; pointer-events: none; position: absolute; border: 1px solid red"
>
Canvas not supported.
</canvas>
</div>
2019-03-21 09:57:27 +01:00
<script class="doctest">
let dx = 44
2019-03-21 09:57:27 +01:00
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
}
2019-03-21 09:57:27 +01:00
app.run()
2019-03-21 09:57:27 +01:00
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)
2019-03-21 09:57:27 +01:00
context.strokeStyle = 'red'
context.beginPath()
context.arc(canvasPoint.x, canvasPoint.y, 12, 0, Math.PI * 2)
context.stroke()
}
animate(followPoint)
</script>
</body>
</html>