Центральная вращающаяся стрелка в Konva.js - PullRequest
0 голосов
/ 25 января 2019

Я пишу тебе, потому что я на самом деле застрял.Мне нужно создать стрелку с помощью 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 голосов
/ 25 января 2019

Практически все библиотеки компьютерных рисунков используют точки и прямоугольники. Вам нужно подумать о том, чтобы ваша стрелка была нарисована в прямоугольном пространстве.

Обратите внимание, что Konva немного необычна в графических библиотеках, так как у нарисованных эллипсом форм точки вращения по умолчанию установлены по центру. И на сайте Konva docs есть отличное объяснение сценария смещения / ротации здесь .

В вашем коде, где создается треугольная форма, вы используете

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>
...