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

169
21 октября 2018, 00:20

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

Answer 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; 
}
<div id="camera"> 
  <canvas id="canvas"></canvas> 
</div>

Answer 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(); 
    } 
})();
<canvas id=c width=200 height=140></canvas>

READ ALSO
Как это сверстать?

Как это сверстать?

Есть макет и мне интересно как можно сверстать навигацию(белый блок сверху)Размер макета 1600px, а отступы по 210px, получается размер контента(центровщика)...

183
Как не загружать изображения в скрытых блоках?

Как не загружать изображения в скрытых блоках?

Есть скрытые блоки внутри которых много контента + изображенийКак можно сделать, чтобы изображения загружались только когда блок становился...

165
Как вывести данные JSON в аттрибут data-*

Как вывести данные JSON в аттрибут data-*

Есть загнанные в локальное хранилище данные (таблица):

151