It is necessary that the card be a total of 1000-1000, but the visible part is only 100-100, how to do it? Is it possible to somehow specify the coordinates of the beginning of the VISIBLE screen and its end. 
- Knowing the size and position of the window, determine the tiles that fall into it, draw them all, and then shift them to the desired position. - Lexx918
- similar question with solution in English SO Draw tilemap only on visible canvas area - Lexx918
- Quite a different topic of the question, Lexx918 - Holter
|
2 answers
let cameraWidth = 100; let cameraHeight = 100; let camera = document.getElementById("camera"); let canvas = document.getElementById("canvas"); document.addEventListener("mousemove", function(e) { // Motion camera.style.left = e.clientX - cameraWidth / 2 + "px"; camera.style.top = e.clientY - cameraHeight / 2 + "px"; canvas.style.left = -e.clientX + "px"; canvas.style.top = -e.clientY + "px"; }); #camera { position: absolute; width: 100px; height: 100px; border: 2px solid #ccc; overflow: hidden; } #canvas { position: absolute; width: 500px; height: 300px; background: url(http://www.tedgoas.com/content/blog/22-stack-overflow-design/-stack-overflow-cover.jpg) no-repeat; } <div id="camera"> <canvas id="canvas"></canvas> </div> - In your case, it looks more like a hack and has nothing to do with the canvas ) - ThisMan
- @ThisMan not quite understand what the problem is? - Alexandr Maliovaniy
- I like it catch plus - Excess Suslik
|
Sketched a solution on my knee. I create a huge map of tiles 200 by 200. Genera in each tile is a random color, but with a gradient over the entire map, so that it can be seen as the window moves over the map. Then I run a window counterclockwise over the map starting from the right edge of the map. Only visible tiles are rendered. Maybe where there was a mistake and there are rounding errors, but I think you can forgive me :) The main thing is that the essence is clear.
Math.rad = function(deg) { return deg * Math.PI / 180; }; let tilesTotalX = 200, tilesTotalY = 200, tilesVisibleX = 10, tilesVisibleY = 7, tileWidth = 20, tileHeight = 20; let worldSize = { w: tilesTotalX * tileWidth, h: tilesTotalY * tileHeight }; let windowSize = { w: tilesVisibleX * tileWidth, h: tilesVisibleY * tileHeight }; let tiles = []; for (let row = 0; row < tilesTotalY; row++) { tiles.push([]); for (let col = 0; col < tilesTotalX; col++) { let r = (Math.floor(0xFF * (row / tilesTotalY))).toString(16), g = (Math.floor(0xFF * (col / tilesTotalX))).toString(16), b = (Math.floor(0xFF * Math.random())).toString(16); tiles[row].push(`#${r}${g}${b}`); } } let angle = 0, step = .3; let circle = { x: Math.round((worldSize.w - windowSize.w) / 2), y: Math.round((worldSize.h - windowSize.h) / 2), r: Math.round(((worldSize.h - windowSize.h) / 2) * .8), }; let ctx = c.getContext("2d"); ctx.fillStyle = "#f0f0f0"; ctx.fillRect(0, 0, windowSize.w, windowSize.h); let fps = 16, fpsInterval = 1000 / fps, then = Date.now(); (function animate(){ requestAnimationFrame(animate); let now = Date.now(), elapsed = now - then; if (elapsed > fpsInterval) { then = now - (elapsed % fpsInterval); angle += step; angle %= 360; //console.log(angle); let windowPosition = { x: Math.round(circle.x + Math.cos(Math.rad(angle)) * circle.r), y: Math.round(circle.y - Math.sin(Math.rad(angle)) * circle.r) }; let firstVisibleRowIndex = Math.floor(windowPosition.y / tileHeight), firstVisibleColIndex = Math.floor(windowPosition.x / tileWidth), lastVisibleRowIndex = Math.floor((windowPosition.y + windowSize.h) / tileHeight), lastVisibleColIndex = Math.floor((windowPosition.x + windowSize.w) / tileWidth); let offset = { x: windowPosition.x - tileWidth * Math.floor(windowPosition.x / tileWidth), y: windowPosition.y - tileHeight * Math.floor(windowPosition.y / tileHeight) }; ctx.save(); ctx.translate(-offset.x, -offset.y); for (let row = firstVisibleRowIndex; row <= lastVisibleRowIndex; row++) { for (let col = firstVisibleColIndex; col <= lastVisibleColIndex; col++) { ctx.fillStyle = tiles[row][col]; ctx.fillRect( tileWidth * (col - firstVisibleColIndex), tileHeight * (row - firstVisibleRowIndex), tileWidth, tileHeight ); } } ctx.restore(); } })(); <canvas id=c width=200 height=140></canvas> - Lexx918, thank you very much for your efforts. But, unfortunately, I am new and more than half did not understand. That is, for the alleged "camera", you need to add a separate element to the canvas through fillRect and the size of this element is equal to the part that needs to be displayed on the VISIBLE screen? - Holter
- I just need to understand how to make and display only the visible part of the screen and it was possible to position it through the coordinates, and then I'll figure it out myself. Can you help please? Because at me all canvas is at once displayed on the screen. For example, I create a canvas: <canvas id = "c" width = "500" height = "500"> and now I have 500x500 immediately displayed, but I need only 100x100 to be seen, and the rest of the area is hidden. - Holter
- @Holter for the answer, you need more input. Where do you get data for 500x500? Is it possible to remove only 100 by 100? if so, just draw them. if not, why not? the canvas you will always have is exactly 100 by 100. it remains to understand how to correctly extract the data for it. Perhaps this is generally a question not about rendering, but about receiving data from a source. while on the issue is not clear. - Lexx918
- I will describe in more detail the goal. There is a canvas, its size is 500x500: <canvas id = "c" width = "500" height = "500">. When the page loads, the canvas is displayed entirely 500x500, BUT I need to display part of this canvas 100x100. Here's the question: how do I create this “camera” with a size of 100x100? - Holter
- In your answer to the question, you made the system as needed. But there is still a movement of this camera itself, the generation of tiles, that’s where I’ve got confused and I don’t know where exactly the part of the code is responsible for creating the camera. - Holter
|