javascript: coloca el nodo centrado en la nota girada

CorePress2024-01-25  83

Tengo la siguiente etapa de ejemplo.

const rectangle = new Konva.Rect({
  width: 300,
  height: 100,
  x: stage.width() / 2,
  y: stage.height() / 2,
  fill: 'blue',
  rotation: 140
});
layer.add(rectangle);
layer.draw();


const tooltip = new Konva.Label({
  x: rectangle.x() + (rectangle.width() / 2),
  y: rectangle.y() + (rectangle.height() / 2),
  opacity: 0.75
});
tooltip.add(
  new Konva.Tag({
    fill: 'green',
    pointerDirection: 'down',
    pointerWidth: 6,
    pointerHeight: 4,
    lineJoin: 'round'
  })
);
tooltip.add(new Konva.Text({
  text: 'Hello world',
  fontSize: 12,
  padding: 5,
  fill: 'white',
}));
layer.add(tooltip);
layer.draw();

Cuando el rectángulo no tiene rotación puedo colocar la información sobre herramientas correctamente en el centro del nodo. Cuando el rectángulo tiene cierta rotación, la información sobre herramientas ya no está centrada.

Sin cambiar los atributos del rectángulo o rotar la información sobre herramientas, ¿cómo puedo colocar la información sobre herramientas en el centro del nodo del rectángulo?

Ejemplo de JSBIN:

https://jsbin.com/wopoxuligi/edit?html,js,output



------------------------------------

Primero, debe actualizar su declaración de Konva en la etiqueta del script html, ya que hace referencia a una versión anterior.

<script src="https://unpkg.com/[email protected]/konva.min.js"></script>

Porque estoLa forma es un rect al que puedes llamar rectángulo.getClientRect() para obtener la posición en el escenario, luego usa matemáticas centrales simples para colocar tu etiqueta. Inserte este código al final de su código actual donde hace la última capa.draw();

const cliRect = rectangle.getClientRect();
let pos = {
        x: cliRect.x + (cliRect.width )/2,
        y: cliRect.y + (cliRect.height )/2
};
tooltip.x(pos.x)
tooltip.y(pos.y)
layer.draw();

Esto dejará el puntero de la etiqueta apuntando al centro del rectángulo girado, con la etiqueta sin girar. Fragmento de trabajo a continuación: ejecútelo en pantalla completa.

const stage = new Konva.Stage({
  container: 'container',
  width: window.innerWidth,
  height: window.innerHeight,
  draggable: true
});

const layer = new Konva.Layer();
stage.add(layer);

const rectangle = new Konva.Rect({
  width: 300,
  height: 100,
  x: stage.width() / 2,
  y: stage.height() / 2,
  fill: 'blue',
  rotation: 140
});
layer.add(rectangle);
layer.draw();
 
const tooltip = new Konva.Label({
  x: rectangle.x() + (rectangle.width() / 2),
  y: rectangle.y() + (rectangle.height() / 2),
  opacity: 0.75
});
 
tooltip.add(
  new Konva.Tag({
    fill: 'green',
    pointerDirection: 'down',
    pointerWidth: 6,
    pointerHeight: 4,
    lineJoin: 'round'
  })
);
tooltip.add(new Konva.Text({
  text: 'Hello world',
  fontSize: 12,
  padding: 5,
  fill: 'white',
}));
layer.add(tooltip);


const cliRect = rectangle.getClientRect();
// Extra red rect to illustrate client rect. Not needed in solution
const rectangle1 = new Konva.Rect({
  width: cliRect.width,
  height: cliRect.height,
  x: cliRect.x,
  y: cliRect.y,
  stroke: 'red'
});
layer.add(rectangle1);


let pos = {
        x: cliRect.x + (cliRect.width )/2,
        y: cliRect.y + (cliRect.height )/2
};
 
// Set tooltip position taking account of stage draggind
tooltip.x(pos.x - stage.x())
tooltip.y(pos.y - stage.y())  

console.log(pos)



layer.draw();
<script src="https://unpkg.com/[email protected]/konva.min.js"></script>
  <div id="container"></div>

EDITAR: En un comentario, el OP señaló que el caso de uso real requiere que el escenario se pueda arrastrar antes de agregar la etiqueta y que después de arrastrar falla el cálculo de la posición de la etiqueta. Esto se debe a que getClientRect() proporciona la posición en el contenedor del cliente sin ajuste para el movimiento del escenario. Para que el código funcione con una etapa arrastrada, cambiee las dos líneas que configuran tooltip.x & y para ajustar según el escenario.x & y, de la siguiente manera:

tooltip.x(pos.x - stage.x())
tooltip.y(pos.y - stage.y())  

1

¡Gracias, esto funciona! Pero tengo una limitación en mi caso de uso real. El escenario se puede arrastrar. Tan pronto como mueve el escenario y luego agrega la información sobre herramientas, no está en la ubicación correcta. He actualizado el ejemplo con el mensaje "Agregar información sobre herramientas" Botón jsbin.com/vabutomoqo/edit?html,js,output

- isADon

28/03/2021 a las 11:08



------------------------------------

Agregué desplazamiento al rectángulo para rotarlo por su punto central y logré tener la información sobre herramientas centrada.

const stage = new Konva.Stage({
  container: 'container',
  width: window.innerWidth,
  height: window.innerHeight
});

const layer = new Konva.Layer();
stage.add(layer);

var group1 = new Konva.Group({
  draggable: true
});
const rectWidth = 300;
const rectHeight = 100;

const rectangle = new Konva.Rect({
  width: rectWidth,
  height: rectHeight,
  x: stage.width() / 2,
  y: stage.height() / 2,
  fill: 'blue',
  rotation: 140,
  offset: {
    x: rectWidth / 2,
    y: rectHeight / 2,
  },
});

const tooltip = new Konva.Label({
  x: rectangle.x() + (rectangle.width() / 2),
  y: rectangle.y() + (rectangle.height() / 2),
  offset: {
    x: rectangle.width() / 2,
    y: rectangle.height() / 2,
  },
  opacity: 0.75
});
tooltip.add(
  new Konva.Tag({
    fill: 'green',
    pointerDirection: 'down',
    pointerWidth: 6,
    pointerHeight: 4,
    lineJoin: 'round'
  })
);
tooltip.add(new Konva.Text({
  text: 'Hello world',
  fontSize: 12,
  padding: 5,
  fill: 'white',
}));

layer.add(rectangle);
layer.add(tooltip);
layer.draw();
<script src="https://unpkg.com/konva@^2/konva.min.js"></script>

<div id="container"></div>

1

Una solución que vale la pena, aunque cambiar el desplazamiento puede tener algunas consecuencias inesperadas en el código posterior.

- Wombat vencido

28/03/2021 a las 10:40

Su guía para un futuro mejor - libreflare
Su guía para un futuro mejor - libreflare