Действие по клику на элемент Canvas

195
07 января 2019, 04:30

Я пытаюсь сделать плейбл, в котором пользователь кликает на врага и его персонаж начинает его бить. Проблема с кликом на canvas, никак не получается его реализовать. Нужно, чтобы при клике на определенную область, изображение персонажа поменялось на другое. Возможно ли это сделать и как? Вот имеющийся код

var canvas = document.getElementById("game"); 
var context = canvas.getContext('2d'); 
var canvasLeft = canvas.offsetLeft; 
var canvasTop = canvas.offsetTop; 
 
var pers1 = {x:350, y:630}; 
var pers2=[]; 
var dragon = {x:470, y:600}; 
 
 
var barimg = new Image(); 
barimg.src = "img/bar.png"; 
 
var hpRedimg = new Image(); 
hpRedimg.src = "img/hpRed.png"; 
 
var hpGreenimg = new Image(); 
hpGreenimg.src = "img/hpGreen.png"; 
 
 
var pers2img = new Image(); 
pers2img.src = "img/bandit-sp.png"; 
 
var pers1img = new Image(); 
pers1img.src = "img/bandit.png"; 
 
var dragonimg = new Image(); 
dragonimg.src = "img/dragon.png"; 
 
var fonimg = new Image(); 
fonimg.src = "img/bg.png"; 
 
 
fonimg.onload = function(){ 
   game(); 
} 
 
 
function game() { 
 
   update(); 
   render(); 
   requestAnimFrame(game); 
} 
 
function update() { 
 
// здесь код клика 
} 
 
 
function render() { 
context.drawImage(fonimg, 0, 0, 1000, 1000); 
context.drawImage(barimg, 100, 30, 700, 70); 
context.drawImage(pers1img, pers1.x, pers1.y, 100, 170); 
context.drawImage(dragonimg, dragon.x, dragon.y, 300, 200); 
context.drawImage(pers2img, 128*Math.floor(pers2.animx), 128*Math.floor(pers2.animy),128, 128, pers2.x, pers2.y, 100, 100 ); 
context.drawImage(hpGreenimg, pers1.x+20, pers1.y-20, 60, 10); 
context.drawImage(hpRedimg, dragon.x+50, dragon.y-20, 60, 10); 
 
} 
 
 
function resizeGame() { 
var gameArea = document.getElementById('gameArea'); 
var widthToHeight = 1 / 1; 
var newWidth = window.innerWidth; 
var newHeight = window.innerHeight; 
var newWidthToHeight = newWidth / newHeight; 
 
if (newWidthToHeight > widthToHeight) { 
newWidth = newHeight * widthToHeight; 
gameArea.style.height = newHeight + 'px'; 
gameArea.style.width = newWidth + 'px'; 
} else { 
newHeight = newWidth / widthToHeight; 
gameArea.style.width = newWidth + 'px'; 
gameArea.style.height = newHeight + 'px'; 
} 
 
gameArea.style.marginTop = (-newHeight / 2) + 'px'; 
gameArea.style.marginLeft = (-newWidth / 2) + 'px'; 
 
var gameCanvas = document.getElementById('game'); 
gameCanvas.width = newWidth; 
gameCanvas.height = newHeight; 
} 
 
window.addEventListener('resize', resizeGame, false); 
window.addEventListener('orientationchange', resizeGame, false); 
 
var requestAnimFrame = (function() { 
return window.requestAnimationFrame || 
window.webkitRequestAnimationFrame || 
window.mozRequestAnimationFrame || 
window.oRequestAnimationFrame || 
window.msRequestAnimationFrame || 
function(callback){ 
window.setTimeout(callback, 1000/20); 
}; 
})();
.gameArea { 
  position: absolute; 
  left:     50%; 
  top:      50%; 
 
} 
.game{ 
  width: 100%; 
  height: 100%; 
 
  display: block; 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> 
 
<div id="gameArea" class="gameArea"> 
  <canvas id="game" class="game"></canvas> 
</div>

Answer 1

const canvas = document.getElementById("canvas"); 
const output = document.querySelector("#output"); 
 
const ctx = canvas.getContext('2d'); 
ctx.fillStyle = "red"; 
ctx.fillRect(50, 50, 50, 50); 
 
ctx.fillStyle = "green"; 
ctx.fillRect(100, 120, 80, 50); 
 
canvas.addEventListener("click", e => { 
  output.innerText = `Координаты клика: ${e.offsetX}, ${e.offsetY}. `; 
  if(e.offsetX < 100 && e.offsetX > 50 && e.offsetY > 50 && e.offsetY < 100) { 
    output.innerText += `Вы кликнули по красной фигуре!`; 
    output.style.color = 'red'; 
  } else if(e.offsetX < 180 && e.offsetX > 100 && e.offsetY > 120 && e.offsetY < 170) { 
    output.innerText += `Вы кликнули по зеленой фигуре!`; 
    output.style.color = 'green'; 
  } else { 
    output.style.color = 'black';  
  } 
});
#canvas { 
  margin: 10px; 
  border: 10px solid blue; 
} 
 
#output { 
  padding: 1em; 
  border: 1px solid gray; 
   
}
<div id="output">Кликай по холсту!</div> 
<canvas id="canvas" width=200 height=200></canvas>

Запустите код и кликайте по холсту, чтобы посмотреть как это работает (результат выводится в верхнем блоке).

Это простой вариант отслеживания клика. Заметьте, я использую offsetX и offsetY - координаты относительно левого верхнего угла, без учета границ и отступов (поэтому при клике по синей границе координаты отрицательные), то есть эти координаты и есть координаты холста.

Подробнее о событии MouseEvent и доступных свойствах читайте здесь.

Answer 2

Насколько знаю на обычно канвасе без библиотек это тяжело сделать.

Вот как менять если использовать Raphael:

const paper = Raphael(document.getElementById('papercanvas'), 100, 100) 
const images = [ 
	'http://s53.radikal.ru/i142/0909/b1/c3e1eb475a50.gif', 
	'http://s53.radikal.ru/i142/0909/b1/c3e1eb475a50.gif' 
] 
const img = paper.image(images[0], 20, 20, 80, 80) 
 
img.click(changeImageSource) 
 
 
function changeImageSource() { 
	let src 
	this.state = !this.state 
   
  if (this.state) 
  	src = 'http://s60.radikal.ru/i168/0909/3a/21117ba1e58d.gif' 
  else 
  	src = 'http://s53.radikal.ru/i142/0909/b1/c3e1eb475a50.gif' 
     
  this.attr('src', src) 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/raphael/2.2.7/raphael.min.js"></script> 
Нажмите на персонажа для переключения картинки 
<div id="papercanvas"></div>

READ ALSO
NodeJS синхронный get

NodeJS синхронный get

Нужно установить getter для поляGetter должен делать запрос к базе данных

171
WebSocket в Javascript

WebSocket в Javascript

На сервере(tcp) стоит python скрипт, на модуле socket, не могу подключиться, открываю Console в гугл хром и получается такй вывод:

147
Не отсылать запросы

Не отсылать запросы

Задача в следующем: На странице есть несколько блоковПри наведении мыши на блок отправляется запрос на сервер и ответ вставляется в этот...

169
Как лучше загружать файлы на сервер?

Как лучше загружать файлы на сервер?

Занимаюсь разработкой веб-приложений уже около годаЗагрузку файлов на сервер, например, при регистрации в системе, делал таким образом, что...

178