javascript - Konva.js 中的中心旋转箭头

标签 javascript konvajs

我写信给你是因为我真的被困住了。我必须使用 Konva.js 创建一个箭头(我根据模型对我的进行了个性化设置:https://konvajs.github.io/docs/overview.html)。

我附上了我的 JS 文件(用于创建箭头)、CSS 和通过调用 JS 文件显示结果的 HTML 文件。

这是我的问题:当我在 HTML 文件中输入一个值(风向)时,我希望我的箭头旋转指示的 Angular (方向)。它可以是 45°、90°、135°...(所以 NE、E、SE...)。但实际上,我的箭头会旋转,但也会在屏幕上围绕左上角移动。我不知道为什么。我希望它只自转。你会怎么做?

我已经看到它可以与 offsetX 和 offsetY 一起使用,但不知道是否有更好的解决方案或如何使用它。这就是为什么我需要你的帮助。

function draw_fleche_vent(direction){
  var direction = direction//new Konva.Transformer({
  //   rotationSnaps: [0, 45, 90, 135, 180, 225, 270, 315, 360],
  // });
  // var force = "";
  // get
  // var rotationSnaps = transformer.rotationSnaps();

  // set
  // transformer.rotationSnaps([0, 45, 90, 135, 180, 225, 270, 315, 360]);

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

  var layer = new Konva.Layer();


  /*
  * create a triangle shape by defining a
  * drawing function which draws a triangle
  */
  var triangle = new Konva.Shape({
    sceneFunc: function (context, shape) {
      context.beginPath();
      context.moveTo(225, 10);
      context.lineTo(150, 190);
      context.quadraticCurveTo(230, 90, 300, 190);
      context.closePath();
      //context.offset({context.width/2, context.height/2});
      //context.position({context.width/2,context.height/2});
      context.fillStrokeShape(shape);
    },
    fill: '#FF5757',
    stroke: 'black',
    strokeWidth: 4
  });

  //var c = document.getElementById(context);
  //context.rotate(direction * Math.PI / 180) ;
  

  triangle.rotate(direction);
  layer.add(triangle);
  stage.add(layer);
  

// console.log('ca marche');

    // switch (direction) {
    //   case 0: 
    //     // ayer.add(triangle);.add(direction);
    //     // add the triangle shape to the layer
    //     layer.add(triangle);
    //     // triangle.rotate(0);

    //     // add the layer to the stage
    //     stage.add(layer);
    //   console.log('on est dans le switch 0');
    //   break;
    //   case 45: 
    //     //context.rotate();
    //     // add the triangle shape to the layer
    //     layer.add(triangle);
    //     triangle.rotate(45);
    //     // add the layer to the stage
    //     stage.add(layer);
    //   console.log('on est dans le switch 45');
    //   break;
    //   case 90:
    //     // context.rotate(Math.PI / 180);
    //     // add the triangle shape to the layer
    //     layer.add(triangle);
    //     triangle.rotate(90);
    //     // add the layer to the stage
    //     stage.add(layer);

    //     console.log('on est dans le switch 90');
    //     break; 
    //   case 135: 
    //     // add the triangle shape to the layer
    //     layer.add(triangle);
    //     triangle.rotate(135);
    //     // add the layer to the stage
    //     stage.add(layer);
    //   console.log('on est dans le switch 135');
    //   break;
    //   case 180: 
    //     // add the triangle shape to the layer
    //     layer.add(triangle);
    //     triangle.rotate(180);
    //     // add the layer to the stage
    //     stage.add(layer);
    //   console.log('on est dans le switch 180');
    //   break;
    //   case 225: 
    //     // add the triangle shape to the layer
    //     layer.add(triangle);
    //     triangle.rotate(225);
    //     // add the layer to the stage
    //     stage.add(layer);
    //   console.log('on est dans le switch 225');
    //   break;
    //   case 270: 
    //     // add the triangle shape to the layer
    //     layer.add(triangle);
    //     triangle.rotate(270);
    //     // add the layer to the stage
    //     stage.add(layer);
    //   console.log('on est dans le switch 270');
    //   break;
    //   case 315: 
    //     // add the triangle shape to the layer
    //     layer.add(triangle);
    //     triangle.rotate(315);
    //     // add the layer to the stage
    //     stage.add(layer);
    //   console.log('on est dans le switch 315');
    //   break;
    //   case 360: 
    //     // add the triangle shape to the layer
    //     layer.add(triangle);
    //     triangle.rotate(360);
    //     // add the layer to the stage
    //     stage.add(layer);
    //     console.log('on est dans le switch 360');
    //   break;
    // }

  // add the triangle shape to the layer
  // layer.add(triangle);

  // add the layer to the stage
  // stage.add(layer);
}

// function rotation(){
//   triangle.rotate(45);
//   stage.draw();
//   console.log('loaded');
// }
body {
      margin: 0;
      padding: 0;
      overflow: hidden;
      background-color: #F0F0F0;
}
<!DOCTYPE html>
<html>

<head>
  <script type = "text/javascript" src="konva.min.js"></script>
  <link rel="stylesheet" href="main.css" />
  <script type = "text/javascript" src = "fleche.js"></script>
  <meta charset="utf-8">
  <title>Arrow - Try</title>

</head>

<body>
  <div id="container"></div>
    <script type = "text/javascript">
         draw_fleche_vent(45);
    </script>
</body>

</html>

最佳答案

几乎所有计算机绘图库的工作方式都是使用点和矩形。您需要考虑将箭头绘制在矩形空间中。

请注意,Konva 在图形库中有点不寻常,因为椭圆形的旋转点默认为它们的中心。在 Konva 文档网站上有关于偏移/旋转场景的很好解释 here .

在创建三 Angular 形的代码中使用

context.beginPath();
context.moveTo(225, 10);
...

起点 (beginPath) 是包含绘图的矩形的左上角。所以这是点(0,0)。

应用于形状的任何位置更改或旋转更改都使用此点作为移动中心。

如您所见,这意味着旋转似乎意外地移动了形状。

可以通过 offSet(x, y) 函数移动旋转点。顾名思义,这会将旋转点移动给定值。

您必须准确决定旋转点应该移动到哪里,这取决于您绘制的形状。一个好的起点通常是使用围绕形状的矩形的中心。

var dX = node.width()/2;
var dY = node.height()/2;
node.offset(dX, dY)

请注意,更改偏移量会移动形状,因此您需要重新定位形状

node.position({x:node.x() + dX, y: node.y() + dY})

最后 - 当发布代码示例时,尝试将它们缩减到能够说明基本问题的程度。所以下次把所有被注释的代码都去掉,除了有用的注释。

// Set up the canvas / stage
var div = $('#container');

var stage = new Konva.Stage({container: 'container', width: div.width(), height: div.height()});
var layer = new Konva.Layer({draggable: false});
stage.add(layer)

// make a triangle 
 var triangle = new Konva.Shape({
    sceneFunc: function (context, shape) {
      context.beginPath();
      context.moveTo(25, 00);
      context.lineTo(0, 60);
      context.quadraticCurveTo(0, 60, 50, 60);
      context.closePath();
      context.fillStrokeShape(shape);
    },
    fill: 'cyan',
    stroke: 'transparent'
  });

// make a rect hsape to illustrate the rectangle that the triangle is drawn into
var rect = new Konva.Rect({
    x: 0,
    y: 0,
    width: 50,
    height: 60,
    stroke: 'magenta',
    strokeWidth: 1
  });

// add both to a group
var group1 = new Konva.Group();
group1.position({x:50, y:50})
group1.add(triangle)
group1.add(rect)
  
// note the size of the group before we stick the cross to it as the cross affects the size.
// we will use this for offset and position later
var szWidth = group1.getClientRect().width/2;
var szHeight = group1.getClientRect().height/2;

// make a big red X to show the rotation point.
var cross = new Konva.Shape({
    name: 'cross',
    sceneFunc: function (context, shape) {
      context.beginPath();
      context.moveTo(0, 10);
      context.lineTo(10, 0);
      context.moveTo(0, 0);
      context.lineTo(10, 10);
      context.fillStrokeShape(shape);
    },
    strokeWidth: 2,
    stroke: 'red',
    x: -5,
    y: -5
  });

group1.add(cross)

// clone the first group to make a second, overriding the x position
var group3 = group1.clone({
  x: 120,
  opacity: .4  // give this one low opacity to make it faint.
});  

// clone a node and override the x position - this is the one we will spin.
var group2 = group1.clone({
  x: 120
});  

// load all into the layer
layer.add(group1)
layer.add(group3)
layer.add(group2)

// offset group2 drawing & rotating point (call this the origin)
group2.offsetX(szWidth);
group2.offsetY(szHeight);

// IMPORTANT: but now we need to move the shape to compensate for the offset of the 'origin'.
group2.move({x: szWidth, y: szHeight})

// move the big red cross to show where the origin is now.
var cross2 = group2.findOne('.cross');
cross2.move({x: szWidth, y: szHeight});

stage.draw()

// hook the button click event to make the rotation happen
$('#rotate10').on('click', function(){
  group1.rotate(10);
  group2.rotate(10);
  layer.draw();

})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/konva/2.5.1/konva.min.js"></script>
<div>
<p>Left arrow is rotating without offset. The right arrow has both offset() and move() applied.</p>
<button id='rotate10' class='btn'>Rotate 10 degrees clockwise</button>
</div>
<div id='container' style="position: absolute; top: 40px; z-index: -1; display: inline-block; left: 0px;  width: 260px; height: 140px; background-color: silver;"></div>

关于javascript - Konva.js 中的中心旋转箭头,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54358612/

相关文章:

c# - 如何使用 ASP.NET 和 jQuery 返回 JSON

javascript - Meteor cookie 和服务器端路由

javascript - ajax 预检失败,Firefox 中的 OPTIONS 响应为 200

javascript - 如何避免在 konva 中捕捉期间矩形宽度或高度意外增长

javascript - Vue Typescript Konva。 Canvas onClick 抛出 "Uncaught SyntaxError: Function statements require a function name"

javascript - 从元素中删除类而不影响正在进行的 css 转换

javascript - 如何将事件传输到 Canvas 中 { KonvaJS 中的指针事件 : none }; (!)

Typescript 类型 a 不可分配给类型 b

javascript - 将 Konva 层节点拟合到 "viewport"

javascript - 列出对象内的对象