Creating an editable polygon, with the feature of point adding, how to convert it to draggable with the points?

Viewed 21

I am using KonvaJS for image annotation, in my application, user can select points on canvas and create a custom polygon, everything is okay so far, but i need to implement one more feature, let's say user created a polygon and add it on the list after that, user should edit the polygon by adding new points to the polygon, I managed to implement a part of it but i am confused in some point.

My code works, i group points and polygon and add them to the layer as a group and the group has a draggable property, but adding new points the polygon feature does not seem to be working correctly, can you help me find out what is wrong with this code?

Here is the code:

var stage = new Konva.Stage({
  container: 'container',   // id of container <div>
  width: 500,
  height: 500
});

var layer = new Konva.Layer();

var circles = [
  new Konva.Circle({
    x: 10,
    y: 10,
    radius: 5,
    stroke: '#ff0000',
    strokeWidth: 1,
    draggable: true,
  }),
  new Konva.Circle({
    x: 50,
    y: 50,
    radius: 3,
    stroke: '#ff0000',
    strokeWidth: 1,
    draggable: true,
  }),
  new Konva.Circle({
    x: 50,
    y: 100,
    radius: 3,
    stroke: '#ff0000',
    strokeWidth: 1,
    draggable: true,
  }),
  new Konva.Circle({
    x: 20,
    y: 40,
    radius: 3,
    stroke: '#ff0000',
    strokeWidth: 1,
    draggable: true,
  })
];

const circlesToPoints = (circles) => {
  return circles.map(circle => 
    [circle.attrs.x, circle.attrs.y]
  ).reduce((prev, current) =>  prev.concat(current))
}

var polygon = new Konva.Line({
  points: circlesToPoints(circles),
  fill: '#ff000088',
  stroke: '#ff0000',
  strokeWidth: 1,
  draggable: false,
  closed: true,
  dash:[]
});

var touched = false;

const addEventToCircle = (circle) => {
  circle.on('dragmove', (e) => {
    console.log(JSON.stringify(e))
    console.log(`drag move. x: ${circle.attrs.x}, y: ${circle.attrs.y}`)
    polygon.points(circlesToPoints(circles))
    layer.draw()
  })
  circle.on('mouseover', (e)  => {
    circle.radius(10)
    layer.draw()
  })
  circle.on('mouseout', ()  => {
    circle.radius(5)
    layer.draw()
  })
}

circles.map((circle) => addEventToCircle(circle))

polygon.on('click', (e) => {
  console.log('click')
  console.log(e)
  var mousePos = stage.getPointerPosition();
  const x = mousePos.x
  const y = mousePos.y
  const points = polygon.attrs.points
  for (i=0; i < points.length / 2; i++) {
    const s_x = points[i * 2]
    const s_y = points[i * 2 + 1]
    const e_x = points[(i * 2 + 2) % points.length]
    const e_y = points[(i * 2 + 3) % points.length]
    
    console.log(`i: ${i}, x: ${x}, y: ${y}, sx: ${s_x}, sy: ${s_y}, ex: ${e_x}, ey: ${e_y}`)
    if (((s_x <= x && x <= e_x) || (e_x <= x && x <= s_x)) && 
        ((s_y <= y && y <= e_y) || (e_y <= y && y <= s_y))) {
      point = new Konva.Circle({
        x: x,
        y: y,
        radius: 3,
        stroke: '#ff0000',
        strokeWidth: 1,
        draggable: true,
      });
      addEventToCircle(point)
      console.log(`insert at ${i + 1}`)
      circles.splice(i + 1, 0, point)
      polygon.points(circlesToPoints(circles))
      layer.add(point)
      layer.draw()
      break;
    }
  }
})
let shape = new Konva.Group({
        width: 300,
        height: 300,
        draggable: true
      })
      this.shape = shape
      shape.add(polygon)
      circles.forEach(circle => shape.add(circle))


layer.add(shape);
stage.add(layer);
layer.draw();

0 Answers
Related