Граница видимости и граница холста

107
24 декабря 2020, 05:00

Такой вопрос: допустим у нас есть некоторая локация, в которой сможет передвигаться игрок, она большая, но заранее известно, какие объекты в каких местах на ней находятся. Есть игрок, мы видим вокруг игрока в определенном радиусе, а то что за радиусом видимости мы не видим. Вопрос в том, как это реализовать на canvas. До этого, как я раньше делал, все видимые объекты сразу же рисовались на видимом поле.

Answer 1

Простейший способ - считать bounding box объекта и перед отрисовкой проверять попал ли он на экран, попробуйте поиграть с количеством точек в этом примере, чтобы найти предел производительности Вашего компьютера, тогда можно будет понять как эта оптимизация влияет на производительность

var width, height; 
var canvas = d3.select("canvas").call(d3.zoom().on("zoom", zoom)); 
resize(); 
var context = canvas.node().getContext("2d"); 
var randomX = d3.randomNormal(width / 2, 80); 
var randomY = d3.randomNormal(height / 2, 80); 
var data = d3.range(1e4).map(function() {  
    return [randomX(), randomY()];  
}); 
let r1 = 1; 
var transform = {x:0, y:0, k:1}; 
 
draw(); 
 
function zoom() { 
  transform = d3.event.transform; 
  context.save(); 
  context.clearRect(0, 0, width, height); 
  context.translate(transform.x, transform.y); 
  context.scale(transform.k, transform.k); 
  draw(); 
  context.restore(); 
} 
 
function draw() { 
  var i = -1, n = data.length, d, c=0; 
  context.beginPath(); 
  let rect = visibleRect(); 
   
    context.beginPath() 
  context.fillStyle = 'red'; 
  while (++i < n) { 
    d = data[i]; 
     
    if (inScreen(d, rect)) { 
      c++; 
      context.moveTo(d[0], d[1]); 
      context.arc(d[0], d[1], r1, 0, 2 * Math.PI); 
    } 
  } 
  context.fill(); 
  log.textContent = 'кругов нарисовано: ' + c + ', используйте drag и wheel' 
} 
 
function resize() { 
  width = canvas.node().width = window.innerWidth; 
  height = canvas.node().height = window.innerHeight-22; 
} 
 
function visibleRect() { 
  let pad = 50; 
  let x = transform.x-pad,  
      y = transform.y-pad,  
      k = transform.k, 
      w = width-pad*2, 
      h = height-pad*2; 
       
  context.beginPath() 
  context.fillStyle = 'rgba(0,0,0,0.1)'; 
  context.rect(-x/k, -y/k, w/k, h/k); 
  context.fill(); 
  return [-x/k, -y/k, w/k-x/k, h/k-y/k] 
} 
 
function inScreen(d, r) { 
  return d[0] > r[0]-r1 && d[1] > r[1]-r1 && d[0]<r[2]+r1 && d[1]<r[3]+r1 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> 
<body style="margin:0;overflow:hidden"> 
<canvas></canvas> 
<div id="log"></div> 
</body>

Недостаток такого подхода - перебор всех элементов, чтобы этого избежать придется использовать структуры данных - например квадродерево

READ ALSO
Как сверстать такой семи-круг?

Как сверстать такой семи-круг?

Подскажите пожалуйста каким образом можно сделать такой семи круг с пунктами?

134
Разработка лайков на Django

Разработка лайков на Django

Итак, всем привет, возникли сложности в разработке системы лайков, видимо что-то недопонимаюВот моя модель постов

122
JQuery div onChange внутри &lt;a href

JQuery div onChange внутри <a href

Я пытаюсь добавить событие click на div, который находится внутри a, Я не хочу, чтобы событие a href срабатывало при запуске события щелчка

132