Konva.js中的中心旋转箭头

时间:2019-01-25 03:36:00

标签: javascript konvajs

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

我已经附加了我的JS文件(用于创建箭头),CSS和HTML文件,可以通过调用JS文件来显示结果。

这是我的问题:当我在HTML文件中输入一个值(风向)时,我希望箭头旋转指示的角度(风向)。可能是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>

1 个答案:

答案 0 :(得分:1)

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

请注意,Konva在图形库中有点不寻常,因为椭圆绘制的形状的旋转点默认为其中心。在Konva文档网站here上,对偏移/旋转方案有很好的解释。

在创建三角形的代码中,使用

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>