将节点置于旋转音符的中心

Place node centred on rotated note

我有以下示例阶段。

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();

当矩形没有旋转时,我可以将工具提示正确地放置在节点的中心。当矩形有一些旋转时,工具提示不再居中。

如何在不改变矩形属性或旋转工具提示的情况下将工具提示置于矩形节点的中心?

JSBIN 示例:

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

我向矩形添加了偏移量,以其中心点旋转它并设法使工具提示居中。

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>

首先,您需要在 html 脚本标记中更新 Konva 声明,因为您引用的是旧版本。

<script src="https://unpkg.com/konva@7.0.3/konva.min.js"></script>

因为这个形状是一个矩形,所以你可以调用 rectangle.getClientRect() 来获取舞台上的位置,然后使用简单的中心数学来放置你的标签。将此代码滑入当前代码的末尾,即您执行最后一个 layer.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();

这将使标签的指针指向旋转矩形的中心,标签未旋转。下面的工作片段 - 运行 全屏显示。

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/konva@7.0.3/konva.min.js"></script>
  <div id="container"></div>

编辑:在评论中,OP 指出实际用例要求舞台在添加标签之前是可拖动的,并且在拖动之后标签位置的计算失败。这是因为 getClientRect() 给出了客户端容器中的位置,而没有针对舞台移动进行调整。要使代码与拖动阶段一起工作,请将设置 tooltip.x & y 的两行更改为由 stage.x & y 调整,如下所示:

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