Search code examples
javascriptcanvasfabricjsdraw

Start next line from somewhere else


Now i have choice of different colors, but when selecting other color, line is still drawn from last point of latest line. How could i draw in new fresh place after choosing other color?

function drawLine() {
    canvas.on("mouse:down", function(event) {
        var pointer = canvas.getPointer(event.e);
        var positionX = pointer.x;
        var positionY = pointer.y;

        var circlePoint = new fabric.Circle({
            radius: 1,
            fill: pipeColor,
            left: positionX,
            top: positionY,
            selectable: false,
            originX: "center",
            originY: "center",
            hoverCursor: "auto"
        });

        canvas.add(circlePoint);

        // Store the points to draw the lines
        pipePoints.push(circlePoint);
        // console.log(pipePoints);
        if (pipePoints.length > 1) {
            var startPoint = pipePoints[pipePoints.length - 2];
            var endPoint = pipePoints[pipePoints.length - 1];

            var pipeLine = new fabric.Line(
                [
                    startPoint.get("left"),
                    startPoint.get("top"),
                    endPoint.get("left"),
                    endPoint.get("top")
                ],
                {
                    stroke: pipeColor,
                    strokeWidth: 2,
                    hasControls: false,
                    hasBorders: false,
                    selectable: false,
                    lockMovementX: true,
                    lockMovementY: true,
                    hoverCursor: "default",
                    originX: "center",
                    originY: "center"
                }
            );

            pipeLines.push(pipeLine);

            canvas.add(pipeLine);
        }
    });

$('#colorpicker').change(function () {
    canvas.item(0).selectable = false;
    pipeColor = $(this).val();
    drawLine();
});
}

For now I can draw any lines i want starting at point X and finishing at point Y, but when i change color of line i wanna start at point Z not point Y


Solution

  • It is not much FabricJS related question. It is more about the implementation and the needs of the app. It can vary cause of requirements and the programmer's experience. Anyway, here is an example width a demo how you can potentially draw multiple lines and go back to the previous lines and continue editing them. You can check the inline StackOverflow snipper or check it on CodeSandbox:

    https://codesandbox.io/s/stackoverflow-60753858-fabric-js-1720-6ke80

    var canvas = new fabric.Canvas("canvas");
    var currentLine = "water";
    document
      .getElementsByClassName("options")[0]
      .addEventListener("click", function(e) {
        if (e.target.classList.contains("line-type")) {
          // Remove active class from previous element
          document
            .querySelector(".line-type.is-active")
            .classList.remove("is-active");
    
          e.target.classList.add("is-active");
          currentLine = e.target.dataset.lineType;
          console.warn("Current line: " + currentLine);
        }
      });
    
    var linesData = {
      water: {
        linePoints: [],
        lineLines: [],
        color: "blue"
      },
      electricity: {
        linePoints: [],
        lineLines: [],
        color: "yellow"
      },
      internet: {
        linePoints: [],
        lineLines: [],
        color: "gray"
      }
    };
    
    canvas.on("mouse:down", function(event) {
      var pointer = canvas.getPointer(event.e);
      var positionX = pointer.x;
      var positionY = pointer.y;
    
      // Add small circle as an indicative point
      var circlePoint = new fabric.Circle({
        radius: 5,
        fill: linesData[currentLine].color,
        left: positionX,
        top: positionY,
        selectable: false,
        originX: "center",
        originY: "center",
        hoverCursor: "auto"
      });
    
      canvas.add(circlePoint);
    
      // Store the points to draw the lines
      linesData[currentLine].linePoints.push(circlePoint);
      if (linesData[currentLine].linePoints.length > 1) {
        // Just draw a line using the last two points, so we don't need to clear
        // and re-render all the lines
        var startPoint =
          linesData[currentLine].linePoints[
            linesData[currentLine].linePoints.length - 2
          ];
        var endPoint =
          linesData[currentLine].linePoints[
            linesData[currentLine].linePoints.length - 1
          ];
    
        var waterLine = new fabric.Line(
          [
            startPoint.get("left"),
            startPoint.get("top"),
            endPoint.get("left"),
            endPoint.get("top")
          ],
          {
            stroke: linesData[currentLine].color,
            strokeWidth: 4,
            hasControls: false,
            hasBorders: false,
            selectable: false,
            lockMovementX: true,
            lockMovementY: true,
            hoverCursor: "default",
            originX: "center",
            originY: "center"
          }
        );
    
        linesData[currentLine].lineLines.push(waterLine);
    
        canvas.add(waterLine);
      }
    });
    
    canvas.renderAll();
    
    document
      .getElementById("clear-water-pipe")
      .addEventListener("click", function(e) {
        linesData[currentLine].linePoints.forEach(function(point) {
          canvas.remove(point);
        });
        linesData[currentLine].linePoints = [];
    
        linesData[currentLine].lineLines.forEach(function(line) {
          canvas.remove(line);
        });
        linesData[currentLine].lineLines = [];
      });
    body {
      font-family: sans-serif;
    }
    canvas {
      border: 2px solid #333;
    }
    button {
      margin-top: 10px;
      padding: 10px;
      border: 1px solid #555;
      cursor: pointer;
    }
    .options {
      padding-top: 10px;
    }
    .lines {
      display: flex;
      align-items: center;
    }
    .lines > div {
      border: 2px solid #333;
      color: white;
      margin-right: 10px;
      padding: 10px;
    }
    .lines > div.is-active {
      border: 5px solid red;
    }
    .water-pipe {
      background-color: blue;
    }
    .lines .electricity-line {
      background-color: yellow;
      color: #555;
    }
    .internet-line {
      background-color: gray;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.22/fabric.min.js"></script>
    
    <div id="app">
      <canvas id="canvas" width="500" height="350"></canvas>
    
      <div class="options">
        <div class="lines" id="lines">
          <div class="line-type water-pipe is-active" data-line-type="water">
            Water pipe
          </div>
          <div class="line-type electricity-line" data-line-type="electricity">
            Electricity line
          </div>
          <div class="line-type internet-line" data-line-type="internet">
            Internet line
          </div>
        </div>
        <button id="clear-water-pipe">Clear active line</button>
      </div>
    </div>