Страницы

Поиск по вопросам

пятница, 20 декабря 2019 г.

Как такое реализовать на canvase?

#javascript #html #canvas


Нужно чтобы карта была в целом 1000на1000, но ВИДНАЯ часть лишь 100на100, как это
сделать? Можно ли как-то указать координаты начала ВИДИМОГО экрана и его конец.
    


Ответы

Ответ 1



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; }


Ответ 2



Набросал на коленке решение. Создаю огромную карту тайлов 200 на 200. Генерю в каждый тайл случайный цвет, но с градиентом на всю карту, чтоб было заметно как окно движется над картой. Затем запускаю над картой окно по кругу против часовой стрелки начиная с правого края карты. Рендерятся только видимые тайлы. Может где ошибся и есть погрешности округления, но думаю можно меня простить :) Главное, что суть понятна. 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(); } })();

Комментариев нет:

Отправить комментарий