Полноценный Drag N Drop, фигуры не прилипают к доске d3.js?

Дан код. Взят у пользователя Stranger in the Q, и чуток подправлен. Halma Stranger in the Q Помогите хотя бы сделать так чтобы фигуры прилипали при отпускании мыши к точке (120,120) (это касается только тронутой фигуры)...

//ctrl+wheel увеличить масштаб
<!DOCTYPE html>
<meta charset="utf-8">
<title>My Project 1.0.0.1</title>
<html>
<script src="https://d3js.org/d3.v5.min.js"></script>
 <style>
html,body{
  overflow-y:hidden;
}
</style>
<body>
<script>
//src="https://d3js.org/d3.v5.min.js"
//scr="d3.js"
var delta = 100;

var x7k = [200]
var y4k = [200]
var ii = 0
for(var y=0; y<=8;y++){
   for(var x=0; x<=8;x++){
    ii++;
    x7k[ii]=x*delta;
    y4k[ii]=y*delta;
}}
var canvas = d3.select("body")
   .append("svg")
   .attr("height", 1024)
   .attr("width", 1366);
/*var img0=canvas.append("svg:image")
   
  .attr("xlink:href", "1.svg")
  .attr("x",677)
  .attr("y",0)
  var img1=canvas.append("svg:image")
*/
for (var ii=2;ii<=81;ii=ii+2){
  img1=canvas.append("svg:image")
  .attr("xlink:href", "1.svg")
  .attr("x",x7k[ii])
  .attr("y",y4k[ii])
  }
/*var img2=canvas.append("svg:image")  
  img2=canvas.append("svg:image")
  .attr("xlink:href", "2.svg")
  .attr("x",x7k[8])
  .attr("y",y4k[0])
  */
  
var polygon0=canvas.append("polygon")
    polygon0=canvas.append("polygon")
    polygon0.attr("points", [0,0,111,122,222,222,212,122])// здесь было исправлено
    polygon0.style("fill", `rgba(100,11,11,0.5)`)
    polygon0.style("stroke", "black")
    polygon0.style("strokeWidth", "1px")  
    
var radius = 45;
var circle_data1 = d3.range(18).map(function(i) {
  return {x: 100+i*50, y: rnd()};
});
 
var circles = d3.select("svg")
  .append("g")
  .attr("class", "circles")
  .selectAll("circle")
  .data(circle_data1)
  //.data(circle_data2)
  .enter()
  .append("circle")
  .attr("cx", function(d,i) {return (d.x)})
  .attr("cy", function(d,i) {return (d.y)})
  .attr("r", radius)
  .style('transition', "200ms")
  .attr("fill", function(d,i) {
    if(i<=8){
	return `rgba(100,112,222,0.5)`
	
	}
	
	
	
	else {return `rgba(0,255,121,0.5)` }
  })
  
  
  
  
  
  
  .call(d3.drag().on("start", function(d) {
          d3.select(this)
            .raise()
            .attr('stroke', 'black')
            .style('transition', "unset")
        }).on("drag", function(d) {
          d3.select(this)
            .attr("cx", d.x = d3.event.x)
            .attr("cy", d.y = d3.event.y);
        }).on("end", function(d) {
          d3.select(this)
            .attr('stroke', 'transparent')
            .style('transition', "200ms")
        })
  );
/*ball.onmouseup = function() {
    document.onmousemove = null;
    ball.onmouseup = null;
  };*/
function upd () {

  var newData = [
    50, 50,   150, 50,   250, 50,
    50, 150, 150, 150,   250, 150,
    50, 250, 150, 250,   250, 250,
    (6-1)*100+50, (6-1)*100+50,   (7-1)*100+50, (6-1)*100+50,    (8-1)*100+50, (6-1)*100+50,
    (6-1)*100+50, (7-1)*100+50,   (7-1)*100+50, (7-1)*100+50,    (8-1)*100+50, (7-1)*100+50,
    (6-1)*100+50, (8-1)*100+50,   (7-1)*100+50, (8-1)*100+50,    (8-1)*100+50, (8-1)*100+50
    
      ///*//////
    
  ]

  circle_data1.forEach(function(d, i) {
    d.x = newData[i * 2]
    d.y = newData[i * 2 + 1]
	
  })

  circles.data(circle_data1)
    .attr("cx", function(d) {return (d.x)})
    .attr('stroke', 'black')
    .attr("cy", function(d) {return (d.y)})
}
upd();
function rnd() {
  return 20 + Math.random() * 110
}
</script>
</body>
</html>


Ответы (2 шт):

Автор решения: Arthur Alunts

Получилось. Добавил залипание к точке (120, 120) Теперь осталось сделать функцию проверки и возвращения координаты. А так, все - работает. Как будет готово, напишу сюда.

//ctrl+wheel увеличить масштаб
<!DOCTYPE html>
<meta charset="utf-8">
<title>My Project 1.0.0.1</title>
<html>
<script src="https://d3js.org/d3.v5.min.js"></script>
 <style>
html,body{
  overflow-y:hidden;
}
</style>
<body>
<script>
//src="https://d3js.org/d3.v5.min.js"
//scr="d3.js"
var delta = 100;

var x7k = [200]
var y4k = [200]
var ii = 0
for(var y=0; y<=8;y++){
   for(var x=0; x<=8;x++){
    ii++;
    x7k[ii]=x*delta;
    y4k[ii]=y*delta;
}}
var canvas = d3.select("body")
   .append("svg")
   .attr("height", 1024)
   .attr("width", 1366);
/*var img0=canvas.append("svg:image")
   
  .attr("xlink:href", "1.svg")
  .attr("x",677)
  .attr("y",0)
  var img1=canvas.append("svg:image")
*/
for (var ii=2;ii<=81;ii=ii+2){
  img1=canvas.append("svg:image")
  .attr("xlink:href", "1.svg")
  .attr("x",x7k[ii])
  .attr("y",y4k[ii])
  }
/*var img2=canvas.append("svg:image")  
  img2=canvas.append("svg:image")
  .attr("xlink:href", "2.svg")
  .attr("x",x7k[8])
  .attr("y",y4k[0])
  */
  
var polygon0=canvas.append("polygon")
    polygon0=canvas.append("polygon")
    polygon0.attr("points", [0,0,111,122,222,222,212,122])// здесь было исправлено
    polygon0.style("fill", `rgba(100,11,11,0.5)`)
    polygon0.style("stroke", "black")
    polygon0.style("strokeWidth", "1px")  
    
var radius = 45;
var circle_data1 = d3.range(18).map(function(i) {
  return {x: 100+i*50, y: rnd()};
});
 
var circles = d3.select("svg")
  .append("g")
  .attr("class", "circles")
  .selectAll("circle")
  .data(circle_data1)
  //.data(circle_data2)
  .enter()
  .append("circle")
  .attr("cx", function(d,i) {return (d.x)})
  .attr("cy", function(d,i) {return (d.y)})
  .attr("r", radius)
  .style('transition', "200ms")
  .attr("fill", function(d,i) {
    if(i<=8){
	return `rgba(100,112,222,0.5)`
	
	}
	
	
	
	else {return `rgba(0,255,121,0.5)` }
  })
  
  
  
  
  
  
  .call(d3.drag().on("start", function(d) {
          d3.select(this)
            .raise()
            .attr('stroke', 'black')
            .style('transition', "unset")
        }).on("drag", function(d) {
          d3.select(this)
            .attr("cx", d.x = d3.event.x)
            .attr("cy", d.y = d3.event.y)
			.attr('stroke', 'red')
			
        }).on("end", function(d,i) {
          d3.select(this)
            .attr("cx", d.x = 120)//здесь добавил код залипания к тоске (120; 120);
            .attr("cy", d.y = 120)//здесь добавил код залипания к тоске (120; 120);
			.attr('stroke', 'transparent')
            .style('transition', "200ms")
			.attr('stroke', 'black')
        })
  );
/*ball.onmouseup = function() {
    document.onmousemove = null;
    ball.onmouseup = null;
  };*/
function upd () {

  var newData = [
    50, 50,   150, 50,   250, 50,
    50, 150, 150, 150,   250, 150,
    50, 250, 150, 250,   250, 250,
    (6-1)*100+50, (6-1)*100+50,   (7-1)*100+50, (6-1)*100+50,    (8-1)*100+50, (6-1)*100+50,
    (6-1)*100+50, (7-1)*100+50,   (7-1)*100+50, (7-1)*100+50,    (8-1)*100+50, (7-1)*100+50,
    (6-1)*100+50, (8-1)*100+50,   (7-1)*100+50, (8-1)*100+50,    (8-1)*100+50, (8-1)*100+50
    
      ///*//////
    
  ]

  circle_data1.forEach(function(d, i) {
    d.x = newData[i * 2]
    d.y = newData[i * 2 + 1]
	
  })

  circles.data(circle_data1)
    .attr("cx", function(d) {return (d.x)})
    .attr('stroke', 'black')
    .attr("cy", function(d) {return (d.y)})
}
upd();
function rnd() {
  return 20 + Math.random() * 110
}
</script>
</body>
</html>

→ Ссылка
Автор решения: Arthur Alunts

Вот полная реализация кода уголки на 2 player. Здесь применен Drag N Drop метод с библиотекой d3.js и работа @Stranger in the Q с кружочками + мое умение прибавлять к коду привычки... Исправлена ошибка с клеткой 1*1 (Фигура теперь правильно виснит) (качаем файл Halma 1.0 Alunts A.A.);

→ Ссылка