Skip to content

Instantly share code, notes, and snippets.

@klevcsoo
Last active March 21, 2024 10:06
Show Gist options
  • Save klevcsoo/86ff50ffa7d8d157166fe18a9c4b1c0f to your computer and use it in GitHub Desktop.
Save klevcsoo/86ff50ffa7d8d157166fe18a9c4b1c0f to your computer and use it in GitHub Desktop.
A simple map renderer in Typescript using the Canvas API. I found it in an old project of mine.
function attachMapRenderer(canvas: HTMLCanvasElement, mapUrl: string) {
const img = new Image(); img.src = mapUrl;
img.onload = () => {
const wCanvas = canvas.width, hCanvas = canvas.height;
const wImg = img.width, hImg = img.height;
const dragMarginX = wImg - wCanvas, dragMarginY = hImg - hCanvas;
const ctx = canvas.getContext('2d');
if (!ctx) throw new Error('Canvas API error');
let confirmedPos = [ 0, 0 ];
let dragging = false;
let dragStartPos = [ 0, 0 ];
let dragMovePos = [ ...confirmedPos ];
let zoomScale = 1;
const drawMap = () => {
ctx.save(); ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, wCanvas, hCanvas); ctx.restore();
ctx.drawImage(
img, dragMovePos[ 0 ], dragMovePos[ 1 ],
wCanvas * zoomScale, hCanvas * zoomScale,
0, 0, wCanvas, hCanvas
);
/*
Draw optional map data, points of interest, overlays,
other stuff over the map. Example:
mapData.forEach((poi) => {
const [ x, y ] = poi.location.map((v, i) => v - dragMovePos[ i ]);
const rs = renderStyle[ poi.type ];
const textOffset = rs.drawIndicator(ctx, [ x, y ]);
ctx.fillText(poi.name, x + textOffset[ 0 ], y + textOffset[ 1 ]);
});
*/
/*
Draw optional debug information. Example:
ctx.font = '14px Arial';
ctx.fillText(`confirmed_pos=${ confirmedPos }`, 20, hCanvas - 80);
ctx.fillText(`drag_start_pos=${ dragStartPos }`, 20, hCanvas - 60);
ctx.fillText(`drag_move_pos=${ dragMovePos }`, 20, hCanvas - 40);
ctx.fillText(`zoom_scale=${ zoomScale }`, 20, hCanvas - 20);
*/
};
const stopDrag = () => { dragging = false; confirmedPos = [ ...dragMovePos ]; drawMap(); };
// ---------- CANVAS EVENTS ----------
canvas.onmousedown = ({ clientX: x, clientY: y }) => {
dragging = true; dragStartPos = [ x, y ];
};
canvas.onmouseup = () => {
stopDrag();
};
canvas.onmouseleave = () => {
stopDrag();
};
canvas.onmousemove = (event) => {
event.preventDefault();
if (!dragging) return;
const { clientX: x, clientY: y } = event;
const tx = confirmedPos[ 0 ] + (dragStartPos[ 0 ] - x);
const ty = confirmedPos[ 1 ] + (dragStartPos[ 1 ] - y);
dragMovePos[ 0 ] = tx <= 0 ? 0 : tx >= dragMarginX ? dragMarginX : tx;
dragMovePos[ 1 ] = ty <= 0 ? 0 : ty >= dragMarginY ? dragMarginY : ty;
drawMap();
};
drawMap();
};
}
export default attachMapRenderer;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment