Динамически генерируемые подвижные векторные фигуры в Paper.js - PullRequest
0 голосов
/ 02 июля 2018

Я пытаюсь отобразить фигуру типа стрелки в Paper.js. Я был в состоянии создать сегменты, которые отрисовывают кончик стрелки, но не смог создать какие-либо дополнительные точки, которые бы заканчивали контур стрелки. Для моих собственных целей тестирования в настоящее время это всего 3 линии, однако мне нужно создать фигуру, которая может иметь заливки и т. Д., Поэтому мне нужно иметь возможность очертить стрелку и динамически перемещать группу при перемещении мыши в направлении , Мне нужна жирная стрела!

Каждая точка, которую я выбираю, несмотря на то, что она связана с положением текущего вектора, кажется, вращается сама по себе при манипулировании стрелкой.

Удары головой против этого в течение нескольких дней без удачи.

Вот с чем я работаю -

var vectorStart, vector; 

var vectorItem = new Group();

onMouseDrag = function (event) {
    var arrowLength = 50;
    vectorItem.remove();
    engaged = true;
    vectorStart = view.center;
    var end = vectorStart + vector;
    vector = event.point - vectorStart;
    console.log('arrow pointer location: ' + event.point);
    var vectorArrow = vector.normalize(arrowLength);
    vectorItem = new Group([
        new Path([vectorStart, end]),
        new Path([
            end + vectorArrow.rotate(120),
            end,
            end + vectorArrow.rotate(-120),
        ]),
    ]);
    vectorItem.strokeWidth = 1;
    vectorItem.strokeColor = 'black';
    this.onMouseUp = function() {
        vectorItem.remove();
    }
}

Вот ссылка на эскиз , содержащий мой код.

Что я не понимаю, так это как добавить точки к Пути, который генерирует стрелку, чтобы создать форму. Кажется, все вращается само по себе и не ведет себя так, как мне нужно.

Любая помощь будет отличной!

Ответы [ 2 ]

0 голосов
/ 22 сентября 2018

Вот некоторый код, который создает стрелку. Объект инициализируется с помощью нижней точки мыши и рисует стрелку с наконечником в точке, куда перетаскивается мышь.

function Arrow (mouseDownPoint) {
    this.start = mouseDownPoint;
    this.headLength = 20;
    this.tailLength = 9;
    this.headAngle = 35;
    this.tailAngle = 110
}

Arrow.prototype.draw = function (point) {
    var end = point;
    var arrowVec = this.start.subtract(end);

    // parameterize {headLength: 20, tailLength: 6, headAngle: 35, tailAngle: 110}
    // construct the arrow
    var arrowHead = arrowVec.normalize(this.headLength);
    var arrowTail = arrowHead.normalize(this.tailLength);

    var p3 = end;                  // arrow point

    var p2 = end.add(arrowHead.rotate(-this.headAngle));   // leading arrow edge angle
    var p4 = end.add(arrowHead.rotate(this.headAngle));    // ditto, other side

    var p1 = p2.add(arrowTail.rotate(this.tailAngle));     // trailing arrow edge angle
    var p5 = p4.add(arrowTail.rotate(-this.tailAngle));    // ditto

    // specify all but the last segment, closed does that
    this.path = new paper.Path(this.start, p1, p2, p3, p4, p5);
    this.path.closed = true;

    this.path.strokeWidth = 1
    this.path.strokColor = 'black'
    this.path.fillColor = 'black'

    return this.path
}

Мне нравится конусообразный хвост, но вы можете избавиться от этого, поиграв с конструктором длины.

Вот эскиз с мышью

0 голосов
/ 21 сентября 2018

Простой способ нарисовать контур стрелки - это объединить 3 прямоугольника.
Paper.js позволяет вам сделать это с помощью метода Path.unite () .

Вот обзор алгоритма рисования

enter image description here

Вот Набросок , демонстрирующий мое решение.

//
// CONSTANTS
//

// user defined
var STROKE_WIDTH = 40;
var HEAD_LENGTH  = 300;
var STYLE        = {
    fillColor  : 'orange',
    strokeColor: 'black',
    strokeWidth: 5
};

// computed
var WIDTH    = STROKE_WIDTH * 2;
var DIAGONAL = Math.sqrt(Math.pow(STROKE_WIDTH * 2, 2) * 2);


//
// METHODS
//

/**
 * Draws an arrow between two points.
 * For simplicity sake, arrow is drawn horizontally at origin first
 * then it is moved and rotated according to start / end points.
 * It is composed of 3 rectangles which are united into a single shape.
 * @param {Point} start
 * @param {Point} end
 */
function drawArrow(start, end)
{
    // calculate distance between points
    var distance = start.getDistance(end);
    // make sure it is not lower than diagonal
    if (distance < DIAGONAL)
    {
        distance = DIAGONAL;
    }

    // draw rectangles
    var directionRectangle = new Path.Rectangle(new Point(0, -STROKE_WIDTH), new Point(distance - DIAGONAL, STROKE_WIDTH));
    var topRectangle       = new Path.Rectangle(new Point(0, -STROKE_WIDTH), new Point(HEAD_LENGTH, STROKE_WIDTH));

    // move top rectangle to the right
    topRectangle.translate(directionRectangle.bounds.rightCenter - topRectangle.bounds.rightCenter + [ WIDTH, 0 ]);

    // make bottom rectangle by cloning top one
    var bottomRectangle = topRectangle.clone();

    // offset top and bottom rectangles
    topRectangle.position -= [ 0, STROKE_WIDTH ];
    bottomRectangle.position += [ 0, STROKE_WIDTH ];

    // rotate then to form arrow head
    topRectangle.rotate(45, topRectangle.bounds.bottomRight - [ WIDTH, 0 ]);
    bottomRectangle.rotate(-45, bottomRectangle.bounds.topRight - [ WIDTH, 0 ]);

    // join the 3 rectangles into one path
    var arrow = directionRectangle.unite(topRectangle).unite(bottomRectangle);

    // move and rotate this path to fit start / end positions
    arrow.translate(start - directionRectangle.bounds.leftCenter);
    arrow.rotate((end - start).angle, start);

    // apply custom styling
    arrow.style = STYLE;

    // remove construction items
    directionRectangle.remove();
    topRectangle.remove();
    bottomRectangle.remove();
}

function onMouseDrag(event)
{
    // clear canvas
    project.clear();
    // draw arrow according to mouse position
    drawArrow(event.downPoint, event.point);
}


//
// INIT
//

// display instructions
new PointText({
    point        : view.center,
    justification: 'center',
    content      : 'Draw arrow by dragging and dropping with your mouse.'
});
...