Brendan Weinstein
12/29/2024, 10:33 PMMichael Paus
12/30/2024, 8:55 AMBrendan Weinstein
12/30/2024, 3:41 PM<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Overlay Canvas on Div</title>
<style>
#container {
position: relative;
width: 500px;
height: 500px;
}
.overlay-div {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(255, 0, 0, 0.5); /* Semi-transparent red */
z-index: 0; /* Ensure the div is below the canvas */
}
.canvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1; /* Ensure the canvas is above the div */
}
</style>
</head>
<body>
<h1>Overlay Canvas on Div</h1>
<div id="container">
<div class="overlay-div"></div>
<canvas id="canvas2" class="canvas"></canvas>
</div>
<script>
// Canvas dimensions
const width = 500;
const height = 500;
// Get canvas element and set its size
const canvas2 = document.getElementById('canvas2');
canvas2.width = width;
canvas2.height = height;
// Get the 2D drawing context
const ctx2 = canvas2.getContext('2d');
// Draw a blue circle on the canvas
ctx2.fillStyle = 'blue';
ctx2.globalAlpha = 0.8; // Set transparency for better visual overlap
ctx2.beginPath();
ctx2.arc(250, 250, 100, 0, Math.PI * 2);
ctx2.fill();
</script>
</body>
</html>
Brendan Weinstein
12/30/2024, 3:42 PMBrendan Weinstein
12/30/2024, 3:43 PMBrendan Weinstein
12/30/2024, 3:44 PMBrendan Weinstein
12/30/2024, 3:46 PM<div id="composeViewport1" z-index=1></div>
<div id="htmlViewContents" z-index=2></div>
<div id="composeViewport3" z-index=3></div>
Would be very hacky, but in theory this could also work.Michael Paus
12/30/2024, 3:59 PMSargun Vohra
12/30/2024, 8:43 PMBrendan Weinstein
12/31/2024, 1:35 AMBrendan Weinstein
12/31/2024, 1:39 AMBrendan Weinstein
12/31/2024, 1:40 AMSargun Vohra
12/31/2024, 3:03 AMHtmlElement
compose library that does the same thing as that one: place the interop html element above the Compose canvas: https://github.com/sargunv/maplibre-compose/tree/main/lib/compose-html-interop
Filed https://github.com/sargunv/maplibre-compose/issues/210 to track the compositing issue with my project. I wonder if it’s possible to apply some alpha mask to composite things properly? I think that’s how Android views interop with SurfaceView, for example (SurfaceView is always behind Android views, but a hole in punched in the UI to see the Surface where it should be visible)Sargun Vohra
12/31/2024, 3:06 AMSargun Vohra
12/31/2024, 6:33 PMmodifier.drawBehind {
drawRect(
color = Color.Transparent,
size = size,
blendMode = BlendMode.Clear
)
}
Compose is still capturing touch/mouse input, so it’s not being passed through to the map underneath.
But otherwise, it works. See these screenshots; the first shows map controls from Compose rendered on the corners of the HtmlElement
map. The second shows a Compose AlertDialog on top of the HtmlElement
map.Michael Paus
01/01/2025, 12:09 AMdrawBehind
is very similar to drawWithContent
.Brendan Weinstein
01/01/2025, 1:28 AMSargun Vohra
01/01/2025, 2:15 AMzIndex = "-1"
to the composable to render behind.
if someone figures out a fix for the pointer input issue when rendering below, please PR or file an issue!Brendan Weinstein
01/01/2025, 3:30 AM<script>
window.startRelaying = function () {
// 1) Grab references to the canvas & the target div
const canvas = document.getElementById("canvasHolder");
const mapContainer = document.getElementsByClassName("mapboxgl-canvas")[0];
if (!canvas) {
console.error('canvas is undefined');
}
if (!mapContainer) {
console.error("mapContainer is undefined");
}
const eventTypes = [
"pointerdown",
"pointermove",
"pointerup",
"pointercancel",
"pointerover",
"pointerout",
"pointerenter",
"pointerleave",
"gotpointercapture",
"lostpointercapture",
"mousedown",
"mousemove",
"mouseup",
"mouseover",
"mouseout",
"mouseenter",
"mouseleave",
"click",
"dblclick",
"contextmenu",
"wheel",
// Touch Events
"touchstart",
"touchmove",
"touchend",
"touchcancel",
];
function relayEvent(originalEvent) {
console.log(
"Relaying pointer event:",
originalEvent.type,
"pointerId:", originalEvent.pointerId,
"clientX:", originalEvent.clientX,
"clientY:", originalEvent.clientY
);
const rectCanvas = canvas.getBoundingClientRect();
const rectMap = mapContainer.getBoundingClientRect();
const offsetX = originalEvent.clientX - rectCanvas.left;
const offsetY = originalEvent.clientY - <http://rectCanvas.top|rectCanvas.top>;
const mapX = rectMap.left + offsetX;
const mapY = <http://rectMap.top|rectMap.top> + offsetY;
const syntheticEvent = new PointerEvent(originalEvent.type, {
...originalEvent,
clientX: mapX,
clientY: mapY,
bubbles: true,
cancelable: true,
composed: true,
});
mapContainer.dispatchEvent(syntheticEvent);
}
eventTypes.forEach(type => {
canvas.addEventListener(type, relayEvent);
});
}
</script>
Sargun Vohra
01/01/2025, 3:46 AMtransformable
. The PoC only has panning, but zoom and rotate should be possible similarly