I have a web page where various amounts of HTML elements (Div's all with the class Character) are generated depending on a sperate PHP Script pulling from an SQL backend.
Once The elements are created this script should make them able to click and drag the elements around the screen. The code works for mobile but doesn't for Desktop. The result is that the elements snap move after the first click whenever the cursor touches them and it seems as tho the mouseup event is never called.
I've tried many variations and below is my latest attempt.
var elements = document.querySelectorAll('.Character');
// Loop through the list of elements
for (var i = 0; i < elements.length; i ) {
// Get the current element
var Character = elements[i];
//moblie touch events
Character.addEventListener("touchmove", dragTouch);
//desktop click events
Character.addEventListener("mousedown", dragMouseDown);
}
var pos1 = 0,
pos2 = 0,
pos3 = 0,
pos4 = 0;
function dragTouch(e) {
var touchLocation = e.targetTouches[0];
//set Location to centre of charcter icon
var offsetX = this.offsetWidth / 2;
var offsetY = this.offsetHeight / 2;
//Move character
this.style.left = (touchLocation.clientX - offsetX) "px";
this.style.top = (touchLocation.clientY - offsetY) "px";
}
var initialX = 0;
var initialY = 0;
function dragMouseDown(e) {
// Save the initial position of the mouse cursor
initialX = e.pageX;
initialY = e.pageY;
// call a function whenever the cursor moves:
this.addEventListener("mousemove", elementDrag.bind(this));
this.addEventListener("mouseup", dragMouseUp);
}
// Use the initial position of the mouse cursor to calculate the element's new position
function elementDrag(e) {
var currentX = e.pageX;
var currentY = e.pageY;
this.style.top = this.offsetTop (currentY - initialY) "px";
this.style.left = this.offsetLeft (currentX - initialX) "px";
}
function dragMouseUp() {
// stop moving when mouse button is released:
this.removeEventListener("mousemove", elementDrag);
}
.Character {
position: absolute;
z-index: 9;
background-color: #50a581;
border-radius: 50%;
width: 50px;
height: 50px;
display: flex;
justify-content: center;
align-content: center;
flex-direction: column;
text-align: center;
cursor: pointer;
left: 10px;
top: 10px;
}
#mapContainer {
position: relative;
background-image: url(./../images/maps/dragons_rest_Dragons_rest.jpeg);
background-repeat: no-repeat;
background-position: top center;
height: 90vh;
background-size: contain;
max-width: 100%;
max-height: 100%;
}
<!DOCTYPE html>
<html>
<head>
<link href='./../fontawesome/css/all.min.css' rel='stylesheet' type='text/css'/>
<link href='./../css/myStyle.css' rel='stylesheet' type='text/css' />
</head>
<body>
<header>
<div id="nav-placeholder"></div>
</header>
<div id="mapContainer">
<?php
// Connect to the database
$db = new mysqli('localhost', 'webserver', '654321', 'webserver');
// Query the database for the data you want to display
$result = $db->query('SELECT charID, name, color FROM charTable');
// Check if there are any results
if ($result->num_rows > 0) {
// Loop through the results
$list = array();
while($row=mysqli_fetch_array($result,MYSQLI_ASSOC)){
$list[] = array (
'charID' => $row['charID'],
'charName' => $row['name'],
'charColor' => $row['color'],
);
}
foreach ($list as $item){
$charID = $item['charID'];
$charName = $item['charName'];
$charColor = $item['charColor'];
$style = "style='background-color:".$charColor.";'";
$html = "<div class='Character'draggable='true' $style>$charName</div>";
echo $html;
}
}
?>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV 2 9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3 MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
<script>
$(function(){
$("#nav-placeholder").load("navbarNew.html");
});
</script>
<script src="./../js/movementV3.js"></script>
</body>
</html>
CodePudding user response:
Why not using the dragend event?
document.addEventListener( "dragover", e => e.preventDefault() );
const chars = document.querySelectorAll(".Character");
for ( let i = 0, len = chars.length; i < len; i ){
const rect = chars[i].getBoundingClientRect();
chars[i].addEventListener( "dragend", e => end.call( chars[i], e, [rect.left, rect.top]) );
chars[i].addEventListener("touchmove", e => dragTouch.call( chars[i], e) );
}
function end(e, [left,top]){
this.style.left = (e.clientX - left - (this.offsetWidth/2)) "px";
this.style.top = (e.clientY - top - (this.offsetHeight/2)) "px";
}
function dragTouch(e) {
let touchLocation = e.targetTouches[0];
let offsetX = this.offsetWidth / 2;
let offsetY = this.offsetHeight / 2;
this.style.left = (touchLocation.clientX - offsetX) "px";
this.style.top = (touchLocation.clientY - offsetY) "px";
}
<style>
.Character {
position: relative;
top: 0;
left: 0;
}
</style>
<button draggable="true">Drag Me #1</button>
<button draggable="true">Drag Me #2</button>
<button draggable="true">Drag Me #3</button>