检查 DOM 元素是否存在于 DIV 中,然后 运行 函数按顺序分配给这些元素

Check if DOM elements are present inside a DIV then run functions assigned to those elements in order

我正在尝试使用 htmlcss 和 [=32= 开发游戏]js。目前我专注于在不使用 canvas 标签 的情况下操纵 DOM 元素。我的想法是创建一个伪图形化编程语言,类似于Blockly环境。到目前为止,我已经在 #toolbox 中插入了 3 个可点击元素,它们在 #workspace.

中创建了它们的副本

现在,我正在尝试将函数分配给 #workspace 中存在的元素,一旦按下 运行 按钮就会按出现顺序执行,因此创建一个能够移动 #output_section.

内的粉红色方块的命令队列

因此我无法理解如何编写能够验证元素是否存在然后能够执行分配给这些元素的不同功能的函数。

有什么想法吗? :D

我正在使用 Jquery 3.3.1

function addRed() {
    var redWorkspace = document.createElement("DIV");
    redWorkspace.className = "remove-block block red";
    document.getElementById("workspace").appendChild(redWorkspace);
};

function addBlue() {
    var blueWorkspace = document.createElement("DIV");
    blueWorkspace.className = "remove-block block blue";
    document.getElementById("workspace").appendChild(blueWorkspace);
};

function addGreen() {
    var greenWorkspace = document.createElement("DIV");
    greenWorkspace.className = "remove-block block green";
    document.getElementById("workspace").appendChild(greenWorkspace);
};

$("#clear_workspace").click(function () {
    $("#workspace").empty();
});

$(document).on("click", ".remove-block", function () {
    $(this).closest("div").remove();
});
html,
body {
    margin: 0;
    padding: 0;
}

#workspace {
    display: flex;
    height: 100px;
    padding: 10px;
    background: black;
}

#toolbox {
    display: flex;
    padding: 10px;
    width: 300px;
}

#output_section {
    height: 500px;
    width: 500px;
    border: solid black;
    margin: 10px;
    position: relative;
}

#moving_square {
    position: absolute;
    bottom: 0;
    right: 0;
    width: 100px;
    height: 100px;
    background: pink;
}

.block {
    height: 100px;
    width: 100px;
}


.red {
    background: red;
}

.blue {
    background: cyan;
}

.green {
    background: green;
}

.grey {
    background: #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<body>
    <div id="workspace"></div>
    <div id="workspace-menu">
       <button id="run_workspace">Run</button>
        <button id="clear_workspace">Clear</button>
    </div>
    <div id="toolbox" class="grey">
    <div onclick="addRed()" class="block red">Left</div>
    <div onclick="addBlue()" class="block blue">Up</div>
    <div onclick="addGreen()" class="block green">Right</div>
    </div>
    <div id="output_section">
        <div id="moving_square"></div>
    </div>
</body>
</html>

完全未经测试,但 运行 按钮的作用类似于:

$("#run_workspace").click(function() {
    $("#workspace .block").each(function(elem) {
        if (elem.hasClass("red")) {
            moveObjectLeft();
        }  else if (elem.hasClass("green")) {
            moveObjectRight();
        }  else if (elem.hasClass("blue")) {
            moveObjectUp();
        } 
    });
});

通常,最好将所有必需的信息存储在数组和对象中,并仅使用 HTML 来显示您的数据。

此外,如果您已经在使用 jQuery - 全部 100% 使用它)
做了一些改进:

let mobs = {
  pinky: {
    node: $('#moving_square'),
    coors: { top: 400, left: 400 },
    step: 30,
    moveQueue: [],
    // moveTimeout ???
  },
}; // storing here all created objects, that must move.
/* Each [moveQueue] array will store the chain of moves, like ["up", "up", "left"]

You can take each "key-word" of move, and get required function buy that key,
from the 'move' object */

let move = { // Think about how to simlify this object and functions. It's possible!)
  left: function (obj) {
    let left = obj.coors.left = (obj.coors.left - obj.step);
    obj.node.css('left', left + 'px');
  },
  up: function (obj) {
    let top = obj.coors.top = (obj.coors.top - obj.step);
    obj.node.css('top', top + 'px');
  },
  right: function (obj) {
    let left = obj.coors.left = (obj.coors.left + obj.step);
    obj.node.css('left', left + 'px');
  }
};

let stepTimeout = 1000;
let running = false;
let timeouts = {}; // store all running timeouts here, 
// and clear everything with for( key in obj ) loop, if required

$('#toolbox .block').on('click', function () {
  let color = $(this).attr('data-color');
  let workBlock = '<div class="remove-block block ' + color + '"></div>';
  $('#workspace').append(workBlock);

  mobs.pinky.moveQueue.push( $(this).text().toLowerCase() ); // .attr('data-direction');
  // instead of pinky - any other currently selected object
  
  // $(this).text().toLowerCase() — must be "left", "up", "right"
});

$('#run_workspace').on('click', function () {
  running = true;
  runCode();

  function runCode() {
    for (let obj in mobs) { // mobile objects may be multiple
      // Inside the loop, obj == mobs each key name. Here it's == "pinky"
      
      let i = 0;
      let pinky = mobs[obj];

      localRun();
      
      function localRun() {
        let direction = pinky.moveQueue[i]; // getting direction key by array index.
        
        move[direction](pinky); // calling the required function from storage.

        if (pinky.moveQueue[++i] && running ) {
          // self-calling again, if moveQueue has next element.
          // At the same time increasing i by +1 ( ++i )
          timeouts[obj] = setTimeout(localRun, stepTimeout);
        }
      }
    }
  }

});


$("#clear_workspace").click(function () {
  $("#workspace").empty();
});

$('#workspace').on("click", ".remove-block", function () {
  $(this).closest("div").remove();
});
html,
body {
  margin: 0;
  padding: 0;
}

#workspace {
  display: flex;
  height: 100px;
  padding: 10px;
  background: black;
}

#toolbox {
  display: flex;
  padding: 10px;
  width: 300px;
}

#output_section {
  height: 500px;
  width: 500px;
  border: solid black;
  margin: 10px;
  position: relative;
}

#moving_square {
  position: absolute;
  top: 400px;
  left: 400px;
  width: 100px;
  height: 100px;
  background: pink;
}

.block {
  height: 100px;
  width: 100px;
}

.red {
  background: red;
}

.blue {
  background: cyan;
}

.green {
  background: green;
}

.grey {
  background: #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="workspace"></div>
<div id="workspace-menu">
  <button id="run_workspace">Run</button>
  <button id="clear_workspace">Clear</button>
</div>
<div id="toolbox" class="grey">
  <div data-color="red" class="block red">Left</div>
  <div data-color="blue" class="block blue">Up</div>
  <div data-color="green" class="block green">Right</div>
</div>
<div id="output_section">
  <div id="moving_square"></div>
</div>

但是...jQuery 仅用于点击...翻译成 JS:

let mobs = {
  pinky: {
    node: document.getElementById('moving_square'),
    coors: { top: 400, left: 400 },
    step: 30,
    moveQueue: [],
  },
};

let move = {
  left: function (obj) {
    let left = obj.coors.left = (obj.coors.left - obj.step);
    obj.node.style.left = left + 'px';
  },
  up: function (obj) {
    let top = obj.coors.top = (obj.coors.top - obj.step);
    obj.node.style.top = top + 'px';
  },
  right: function (obj) {
    let left = obj.coors.left = (obj.coors.left + obj.step);
    obj.node.style.left = left + 'px';
  }
};

let stepTimeout = 1000;
let running = false;
let timeouts = {};

let blocks = document.querySelectorAll('#toolbox .block');
let workSpace = document.getElementById('workspace');

blocks.forEach(function(block){
  block.addEventListener('click', function(){
    let color = this.dataset.color;
    let workBlock = '<div class="remove-block block ' + color + '"></div>';
    
    workSpace.insertAdjacentHTML('beforeend', workBlock);
    
    mobs.pinky.moveQueue.push( this.textContent.toLowerCase() );
  });
});

document.getElementById('run_workspace').addEventListener('click', function () {
  running = true;
  runCode();

  function runCode() {
    for (let obj in mobs) { // mobile objects may be multiple
      // Inside the loop, obj == mobs each key name. Here it's == "pinky"
      
      let i = 0;
      let pinky = mobs[obj];

      localRun();
      
      function localRun() {
        let direction = pinky.moveQueue[i]; // getting direction key by array index.
        
        move[direction](pinky); // calling the required function from storage.

        if (pinky.moveQueue[++i] && running ) {
          // self-calling again, if moveQueue has next element.
          // At the same time increasing i by +1 ( ++i )
          timeouts[obj] = setTimeout(localRun, stepTimeout);
        }
      }
    }
  }

});


document.getElementById("clear_workspace").addEventListener('click', function () {
  workSpace.textContent = "";
});

workSpace.addEventListener('click', function (e) {
  if( e.target.classList.contains('remove-block') ){
    e.target.remove();
  }
});
html,
body {
  margin: 0;
  padding: 0;
}

#workspace {
  display: flex;
  height: 100px;
  padding: 10px;
  background: black;
}

#toolbox {
  display: flex;
  padding: 10px;
  width: 300px;
}

#output_section {
  height: 500px;
  width: 500px;
  border: solid black;
  margin: 10px;
  position: relative;
}

#moving_square {
  position: absolute;
  top: 400px;
  left: 400px;
  width: 100px;
  height: 100px;
  background: pink;
}

.block {
  height: 100px;
  width: 100px;
}

.red {
  background: red;
}

.blue {
  background: cyan;
}

.green {
  background: green;
}

.grey {
  background: #ccc;
}
<div id="workspace"></div>
<div id="workspace-menu">
  <button id="run_workspace">Run</button>
  <button id="clear_workspace">Clear</button>
</div>
<div id="toolbox" class="grey">
  <div data-color="red" class="block red">Left</div>
  <div data-color="blue" class="block blue">Up</div>
  <div data-color="green" class="block green">Right</div>
</div>
<div id="output_section">
  <div id="moving_square"></div>
</div>