2016-05-10 2 views
0

Я с задачей, в которой мне нужно создать два очень специфический типа Pattern Brush использование Fabric.jsСоздание пользовательского Pattern Brush

  1. пунктирной линии с X в конце концов.
  2. Простые стрелки линии.

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

Любое руководство или предложение было бы очень полезно.

Это то, что я пытался за кисть номер 1, но это не решает цель:

var hLinePatternBrush = new fabric.PatternBrush(canvas); 
hLinePatternBrush.getPatternSrc = function() { 

    var patternCanvas = fabric.document.createElement('canvas'); 
    patternCanvas.width = patternCanvas.height = 10; 
    var ctx = patternCanvas.getContext('2d'); 

    ctx.strokeStyle = '#ffffff'; 
    ctx.strokeLineCap ="round"; 
    ctx.lineWidth = 5; 
    ctx.beginPath(); 
    ctx.moveTo(5, 0); 
    ctx.lineTo(5, 10); 
    ctx.closePath(); 
    ctx.stroke(); 

    return patternCanvas; 
}; 
canvas.freeDrawingBrush = hLinePatternBrush; 

И кисть № 2 я понятия не имеют вообще.

+0

** Предложение: ** Создать 'group', содержащий вашу полилинию, и это конец маркера ("X" или стрелка). Маркер может быть изображением или другой полилинией Ткань, независимо). Возможно, установите полилинию 'strokeDashArray' в нужные тире. Это автоматически доставит вам пунктирную линию. Затем на 'mouse: up' (конец перетаскивания, что угодно) извлекают« точки »полилинии. Примените «X» или стрелку на конечной точке. Для стрелки вы можете вычислить поворот стрелки, используя «Math.atan2» в векторе последних двух точек в полилинии. – markE

+0

Да, я сделал аналогичный подход. У меня возникают трудности с углом стрелки. –

ответ

0

Вот моя реализация проблемы. Может помочь кому-то в будущем.

fabric.Path.prototype.selectable = false; 
    fabric.Triangle.prototype.selectable = false; 
    fabric.Text.prototype.selectable = false; 



    /* ------------------------ Player Path Brush --------------------- */ 


    var vLinePatternBrush = new fabric.PencilBrush(canvas); 

    vLinePatternBrush.color = '#fff'; 
    if($("#line_type").val() == 'choose_type' || $("#line_type").val() == 'player_path') 
    { 
     vLinePatternBrush.strokeDashArray = [5, 15]; 
    } 
    else 
    { 
     vLinePatternBrush.strokeDashArray = [0,0]; 
    } 

    vLinePatternBrush.hasControls = false; 

    canvas.freeDrawingBrush = vLinePatternBrush; 
    //canvas.freeDrawingBrush.color = '#fff'; 
    canvas.freeDrawingBrush.width = 4; 

    //Choosing the Right Brush as per Users Requirement 
    $("#line_type").change(function(e){ 
     if($("#line_type").val() == 'choose_type' || $("#line_type").val() == 'player_path') 
     { 

      canvas.freeDrawingBrush = vLinePatternBrush; 
      canvas.freeDrawingBrush.color = '#fff'; 
      canvas.freeDrawingBrush.width = 4; 
      vLinePatternBrush.strokeDashArray = [5, 15]; 

     } 
     else 
     { 
      var normalLine = new fabric['PencilBrush'](canvas); 
      normalLine.strokeDashArray = [0,0]; 
      canvas.freeDrawingBrush = normalLine; 
      canvas.freeDrawingBrush.color = '#fff'; 
      canvas.freeDrawingBrush.width = 4; 
      console.log('here'); 
     } 
    }); 

    // This is required to make sure that the objects can be selected if wrapped inside a path line. 
    canvas.on('object:added', function(e) { 
     console.log(e); 
     if(e.target.type == 'path' || e.target.type == 'text' || e.target.type == 'triangle') 
     { 
      console.log('Sending Object to Background'); 
      canvas.sendToBack(e.target); 
     } 
    }); 

// Обработка X и часть Стрелки После Пути рисуются

canvas.on('path:created', function(path) { 
    console.log(path); 

    if($("#line_type").val() == 'choose_type' || $("#line_type").val() == 'player_path') 
    { 
     console.log(path.path.path[(path.path.path.length -1)]); 



     var x1 = path.path.path[0][1]; 
     var y1 = path.path.path[0][2]; 
     var x2 = path.path.path[(path.path.path.length -1)][1]; 
     var y2 = path.path.path[(path.path.path.length -1)][2]; 

     var angle = calcArrowAngle(x1,y1,x2,y2); 
     angle = angle - 90; 

     var text = new fabric.Text('+', { 
      left: path.path.path[(path.path.path.length -1)][1], 
      top: path.path.path[(path.path.path.length -1)][2], 
      fill: 'white', 
      originX: 'center', 
      originY: 'center', 
      flipx: true, 
      selectable: false, 
      flipy: true, 
      fontSize: 80, 
      fontFamily: 'ABeeZee', 
      fill: 'white', 
      angle: angle, 
      hasControls: false 
     }); 

     canvas.add(text); 
    } 



    if($("#line_type").val() == 'ball_path') 
    { 
     console.log(path.path.path[(path.path.path.length -1)]); 

     var x1 = path.path.path[0][1]; 
     var y1 = path.path.path[0][2]; 
     var x2 = path.path.path[(path.path.path.length -1)][1]; 
     var y2 = path.path.path[(path.path.path.length -1)][2]; 

     var angle = calcArrowAngle(x2,y2,x1,y1); 
     angle = angle - 90; 

     arrow = new fabric.Triangle({ 
      left: (path.path.path[(path.path.path.length -1)][1] + 2), 
      top: (path.path.path[(path.path.path.length -1)][2] + 2), 
      originX: 'center', 
      originY: 'center', 
      hasBorders: false, 
      hasControls: false, 
      lockScalingX: true, 
      lockScalingY: true, 
      lockRotation: true, 
      pointType: 'arrow_start', 
      angle: angle, 
      width: 15, 
      height: 15, 
      fill: 'white', 
      hasControls: false 

     }); 

     canvas.add(arrow); 
    } 
    // This is specific to my implementation for undo and redo. Once can ignore 
    updateModifications(true); 

}); 

В первой секции коды я просто создаю два простые pencilBrush один с DottedLines и один нормальный линии

Во второй части я получаю точную точку, где путь закончился (может быть, это не лучший способ сделать это, но это сработало для меня). Как только я получу Точку, я удаляю желаемую форму в этом положении.

CalcArrowAngle: Кредиты StackOverflow

function calcArrowAngle(x1, y1, x2, y2) { 
     var angle = 0, 
     x, y; 

     x = (x2 - x1); 
     y = (y2 - y1); 

     if (x === 0) { 
      angle = (y === 0) ? 0 : (y > 0) ? Math.PI/2 : Math.PI * 3/2; 
     } else if (y === 0) { 
      angle = (x > 0) ? 0 : Math.PI; 
     } else { 
      angle = (x < 0) ? Math.atan(y/x) + Math.PI : (y < 0) ? Math.atan(y/x) + (2 * Math.PI) : Math.atan(y/x); 
     } 

     return (angle * 180/Math.PI); 
    } 

Я не говорю, что это лучший способ сделать это. Но он решил проблему в руке.

ВЫВОД PNG: Lines