Reputation: 168
I am creating a thing that is kind of cool and basically, it's just drawing without the use of a canvas because I thought "What the hell, I'll play around with some JS". Right now my computer can handle around 4,000 different elements before becoming laggy and I can make that number larger if I could tell if there was a div under the new div I am creating, and then remove it.
How can I detect if there is already an element where the script is going to be creating a new element and remove the existing element without the use of external libraries?
<!DOCTYPE html>
<html>
<head>
<title>Drawing thing</title>
</head>
<body onmousedown="setYes()" onmouseup="setNo()">
<div id="appendThingsHere"></div>
<style>
.circle{
height:50px;
width:50px;
background:blue;
border-radius:50%;
position:absolute;
-moz-user-select:none;
-webkit-user-select:none;
user-select:none;
}
body{
overflow:hidden;
}
#appendThingsHere{
height:100%;
width:100%;
background:none;
position:absolute;
top:0;
left:0;
}
</style>
<script>
var mouseDown = "no";
var elements = 0;
function setYes(){
mouseDown = "yes";
}
function setNo(){
mouseDown = "no";
}
document.body.onmousemove = function(e){
if(mouseDown === "yes"){
if(elements < 4000){
var newCircle = document.createElement("div");
newCircle.className = "circle";
newCircle.style.top = e.clientY - 25 + 'px';
newCircle.style.left = e.clientX - 25 + 'px';
try{
var elem = document.elementFromPoint(e.clientX - 25 + 'px', e.clientY - 25 + 'px');
elem.parentElement.removeChild(elem);
elements = elements - 1;
alert("Got one!");
}
catch(err){
}
elements ++;
document.getElementById('appendThingsHere').appendChild(newCircle);
}
}
}
</script>
</body>
</html>
http://jsbin.com/hocowa/edit?html,output
Upvotes: 0
Views: 2617
Reputation: 242
The best option is to do all the logic in JavaScript and track using an array. Use the DOM only for display purposes and you should see an improvement.
Upvotes: 1
Reputation: 1434
If you want to ensure no new element with same position with the elements before, you can create Array
to hold the drawn positions and draw new element only if the new position is not exist in the array. Example:
var mouseDown = "no";
var elements = 0;
var elmList = [];
function setYes() {
mouseDown = "yes";
}
function setNo() {
mouseDown = "no";
}
document.body.onmousemove = function (e) {
if ( mouseDown === "yes" ) {
if ( elements < 4000 ) {
var offset = (e.clientY - 25) + 'x' + (e.clientX - 25);
if ( elmList.indexOf(offset) < 0 ) {
var newCircle = document.createElement("div");
newCircle.className = "circle";
newCircle.style.top = e.clientY - 25 + 'px';
newCircle.style.left = e.clientX - 25 + 'px';
elements++;
elmList.push(offset);
document.getElementById('appendThingsHere').appendChild(newCircle);
}
}
}
}
Upvotes: 0
Reputation: 6196
Assuming this is an experiment to tinker with js... you could do this
On the handler where you draw each new div, keep track of the last one drawn
var previousCircle,
yThreshold = 10,
xThreshold = 10;
document.body.onmousemove = function(e){
if(mouseDown === "yes"){
if(elements < 4000){
var ty = Math.abs(parseInt(previousCircle.style.top, 10) - e.clientY) < yThreshold;
var tx = Math.abs(parseInt(previousCircle.style.left, 10) - e.clientX) < xThreshold;
if (ty && tx){
// if thresholds pass (new is far away enough from old) then draw a new one
var newCircle = document.createElement("div");
newCircle.className = "circle";
newCircle.style.top = e.clientY - 25 + 'px';
newCircle.style.left = e.clientX - 25 + 'px';
previousCircle = newCircle;
}
You basically decide to draw a new circle or not, based on the distance to the last circle drawn. You can tweak the "decision" with the threshold vars, the threshold condition ìf (ty || tx)
or you could even calculate a vector magnitude (radius from center of each circle) to keep things geometrically correct: radius = sqrt( (newY - oldY)^2 + (newX - oldX)^2 )
.
Granted, this only tracks drawings in sequence, not previous iterations. For that to work you would need to do collision checking on each draw cycle and that means iterating over all drawn divs and comparing their position to the position of the new circle. This is highly inefficient. You could speed up things a bit if you keep track of drawn circles in a index which avoids querying the DOM, only memory.
var drawnCircles = [];
for (var i in drawnCircles){
if (Math.abs(drawnCircles[i].top - e.clientY) < yThreshold && //same for x){
// draw your new circle
var newCircle = document.createElement("div");
newCircle.className = "circle";
newCircle.style.top = e.clientY - 25 + 'px';
newCircle.style.left = e.clientX - 25 + 'px';
// and keep track of it
drawnCircles.push({top: e.clientY, left: e.clientX});
}
}
Upvotes: 1
Reputation: 6813
You could use document.elementFromPoint(x, y);
Don't think you'd be able to handle multiple elements in a single point though. May have to iterate whilst there is an element at point to either remove or ignore.
Upvotes: 2