使用 KonvaJS 绘制和旋转图像

Posted

技术标签:

【中文标题】使用 KonvaJS 绘制和旋转图像【英文标题】:Drawing and rotated images using KonvaJS 【发布时间】:2020-07-01 17:26:40 【问题描述】:

所以我一直在尝试使用 Konva 来绘制图像、文本和形状的数量,一切都很好,直到我尝试在混合中添加旋转。我知道 Konva 使用原点(默认情况下可以通过偏移移动的左上角)来旋转图像,但我需要位置始终位于左上角。

所以我试图计算、旋转重新定位对象以模仿我想要的东西,但这总是导致图像位置与我的初始状态不同,这是一种不需要的行为。

所以我的问题是,Konva 可以从中心旋转图像,同时在旋转后保持原点位置在左上角吗?

*使用代码示例编辑: 绿色框/文本旋转但位置全错。我需要在左边的位置。

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

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


const rotatePoint= (x, y , rad)=> 
  const rcos = Math.cos(rad);
  const rsin = Math.sin(rad);
  return 
    x: x * rcos - y * rsin,
    y: y * rcos + x * rsin
  


const rotateAroundCenter = (node, rotation) =>   
  const topLeft =  x: -node.width() / 2, y: -node.height() / 2 ;
  const current = rotatePoint(topLeft.x, topLeft.y, Konva.getAngle(node.rotation()));
  const rotated = rotatePoint(topLeft.x, topLeft.y, Konva.getAngle(rotation));
  const dx = rotated.x - current.x,
        dy = rotated.y - current.y;
  
  node.rotation(rotation); 
  
  node.x(node.x() + dx);
  node.y(node.y() + dy);
  
  return node;


let x = 100,
    y = 50, 
    width = 50,
    height = 50;
    

const rotation = 90;

const text =  width, height, fontSize: 15, fontFamily: 'Calibri', text: 'Simple Text', opacity: 0.5 ;
const rect =  width, height, strokeWidth: 2
let pos = x, y;
layer.add(new Konva.Circle( ...pos, radius:5, fill: 'black' )); 
layer.add(new Konva.Text( ...pos, ...text, fill: 'black' )); 
layer.add(new Konva.Rect( ...pos, ...rect, stroke: 'purple' )); 
layer.add(new Konva.Text( ...pos, ...text, fill: 'purple', rotation: rotation )); 
layer.add(new Konva.Rect( ...pos, ...rect, stroke: 'purple', rotation: rotation ));

pos = x, y:150;

layer.add(new Konva.Circle( ...pos, radius:5, fill: 'black' )); 
layer.add(rotateAroundCenter(new Konva.Text( ...pos, ...text, fill: 'green' ), rotation)); 
layer.add(rotateAroundCenter(new Konva.Rect( ...pos, ...rect, stroke: 'green' ), rotation)); 



layer.draw();
<!DOCTYPE html>
<html>
<head>
<meta name="description" content="KonvaJS Template">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/konva/4.2.0/konva.min.js"></script>
  <meta charset="utf-8">
</head>
<body>
  <div id="container"></div>
</body>
</html>

【问题讨论】:

请提供您的一些代码或您的问题的最小表示 您可以手动将节点的位置移动到所需的数量,以将节点保持在屏幕的预期位置。 【参考方案1】:

好吧,基本上必须按照 lavrton 说的做,将形状放在一个组中(位置正确),然后在组内旋转和偏移形状。

const stage = new Konva.Stage(
  container: 'container',
  width: 300,
  height: 700
);

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

const rotatePoint = ( x, y , rad) => 
  const rcos = Math.cos(rad);
  const rsin = Math.sin(rad);
  return  x: x * rcos - y * rsin, y: y * rcos + x * rsin ;


// will work for shapes with top-left origin, like rectangle
const rotateAroundCenter = (node, rotation) => 
  //current rotation origin (0, 0) relative to desired origin - center (node.width()/2, node.height()/2)
  const topLeft =  x: -node.width() / 2, y: -node.height() / 2 ;
  const current = rotatePoint(topLeft, Konva.getAngle(node.rotation()));
  const rotated = rotatePoint(topLeft, Konva.getAngle(rotation));
  const dx = rotated.x - current.x,
        dy = rotated.y - current.y;
  
  const r = Math.floor(rotation / 90) % 4;  
  switch(r)
    case 1:
    case 3:
      node.x(node.x() + dx + node.height()/2);
      node.y(node.y() + dy + node.width()/2);
      break;
    case 2:
    default: 
      node.x(node.x() + dx + node.width()/2);
      node.y(node.y() + dy + node.height()/2);
      break;
  

  node.rotation(rotation);
  
  return node;


let x = 200, y = 250, width = 30, height = 75, text = "? ? ? ? ?", opacity = 0.4;

drawShapes = (x, y, width, height, rotation) =>   
  layer.add(new Konva.Text(x:0, y, fill: 'black', text: (rotation+"°").padStart(5,"_")));
  
  layer.add(new Konva.Rect(x, y, width, height, fill: 'black', rotation));
  layer.add(new Konva.Text(x, y, width, height, fill: 'white', rotation, text));

  const group = new Konva.Group( x, y,/* clip:x:0,y:0,width:200,height:200*/)
  
  group.add(rotateAroundCenter(new Konva.Rect(x:-width/2,y:-height/2, width, height,fill: 'grey', opacity), rotation));
  group.add(rotateAroundCenter(new Konva.Text(x:-width/2,y:-height/2, width, height,fill: 'black', text), rotation));
  layer.add(group, new Konva.Circle(x, y, radius: 2, fill: 'black'));

drawShapes(x, 50, width, height,   0);
drawShapes(x, 200, width, height,  90);
drawShapes(x, 350, width, height, 180);
drawShapes(x, 500, width, height, 270);


layer.draw();
<!DOCTYPE html>
<html>
<head>
<meta name="description" content="KonvaJS Template">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/konva/4.2.0/konva.min.js"></script>
  <meta charset="utf-8">
</head>
<body>
  <div id="container" style="height:700px"></div>
</body>
</html>

【讨论】:

以上是关于使用 KonvaJS 绘制和旋转图像的主要内容,如果未能解决你的问题,请参考以下文章

在 KonvaJS 上使用带有 globalCompositeOperation 的图像掩码?

如何在 KonvaJS 中的图层上绘制倒置元素

KonvaJS:如何用箭头连接两个形状?

如何在 Konvajs 画布中上传和加载图像?

Konvajs 在移动绘图线时绘制第一个点

画布不绘制图像 - Electron + Vue