javascript - 如何着手允许在网格上的点之间绘制矢量?

标签 javascript jquery html svg html5-canvas

在基本上只使用 Python 和 C# 之后,我目前正在努力过渡到 HTML5 和 Java。

我正在(尝试)制作一个点网格,请参阅下面的代码,在点之间绘制线(请参阅下面的代码),单击时,最终结果是我可以绘制平面图使用它(我是一名建筑商)。

我也在尝试找出如何单独删除绘制的线条,而不必按“重置”按钮,也许可以通过右键单击它们。

无论如何,由于太新了,这让我很头疼。我一直在摆弄 paper.js 和 jquery,现在已经好几天没有运气了。

你们中的任何人能否为我指明正确的方向,以获取我所追求的教程/示例或有关在哪里寻求帮助的任何建议?

如果做不到这一点,如何在这个网格上制作一个“点”“可点击”并使其对应于矢量的起点和终点?

我已经包含了我正在使用的代码。

点网格:

https://codepen.io/veljamatic/pen/pypxRR

矢量,使用 paper.js(由此处的教程制成,最终结果位于页面底部 http://paperjs.org/tutorials/geometry/vector-geometry/):

var values = {
    fixLength: false,
    fixAngle: false,
    showCircle: false,
    showAngleLength: true,
    showCoordinates: false
};

var vectorStart, vector, vectorPrevious;
var vectorItem, items, dashedItems;

function processVector(event, drag) {
    vector = event.point - vectorStart;
    if (vectorPrevious) {
        if (values.fixLength && values.fixAngle) {
        vector = vectorPrevious;
        } else if (values.fixLength) {
        vector.length = vectorPrevious.length;
        } else if (values.fixAngle) {
            vector = vector.project(vectorPrevious);
        }
    }
    drawVector(drag);
}

function drawVector(drag) {
    if (items) {
        for (var i = 0, l = items.length; i < l; i++) {
            items[i].remove();
        }
    }
    if (vectorItem)
        vectorItem.remove();
    items = [];
    var arrowVector = vector.normalize(10);
    var end = vectorStart + vector;
    vectorItem = new Group([
        new Path([vectorStart, end]),
        new Path([
            end + arrowVector.rotate(135),
            end,
            end + arrowVector.rotate(-135)
        ])
    ]);
    vectorItem.strokeWidth = 0.75;
    vectorItem.strokeColor = '#e4141b';
    // Display:
    dashedItems = [];
    // Draw Circle
    if (values.showCircle) {
        dashedItems.push(new Path.Circle({
            center: vectorStart,
            radius: vector.length
        }));
    }
    // Draw Labels
    if (values.showAngleLength) {
        drawAngle(vectorStart, vector, !drag);
        if (!drag)
            drawLength(vectorStart, end,                                vector.angle < 0 ? -1 : 1, true);
}
var quadrant = vector.quadrant;
if (values.showCoordinates && !drag) {
    drawLength(vectorStart, vectorStart + [vector.x, 0],
            [1, 3].indexOf(quadrant) != -1 ? -1 : 1, true, vector.x, 'x: ');
    drawLength(vectorStart, vectorStart + [0, vector.y], 
            [1, 3].indexOf(quadrant) != -1 ? 1 : -1, true, vector.y, 'y: ');
}
for (var i = 0, l = dashedItems.length; i < l; i++) {
    var item = dashedItems[i];
    item.strokeColor = 'black';
    item.dashArray = [1, 2];
    items.push(item);
}
// Update palette
values.x = vector.x;
values.y = vector.y;
values.length = vector.length;
values.angle = vector.angle;
}

function drawAngle(center, vector, label) {
    var radius = 25, threshold = 10;
    if (vector.length < radius + threshold ||   Math.abs(vector.angle) < 15)
        return;
    var from = new Point(radius, 0);
    var through = from.rotate(vector.angle / 2);
    var to = from.rotate(vector.angle);
    var end = center + to;
    dashedItems.push(new Path.Line(center,
            center + new Point(radius + threshold,  0)));
    dashedItems.push(new Path.Arc(center + from, center +   through, end));
    var arrowVector = to.normalize(7.5).rotate(vector.angle < 0 ? -90 : 90);
    dashedItems.push(new Path([
            end + arrowVector.rotate(135),
            end,
            end + arrowVector.rotate(-135)
    ]));
    if (label) {
        // Angle Label
        var text = new PointText(center
                + through.normalize(radius + 10)    + new Point(0, 3));
        text.content = Math.floor(vector.angle * 100) /     100 + '°';
        text.fillColor = 'black';
        items.push(text);
    }
}

function drawLength(from, to, sign, label, value, prefix) {
    var lengthSize = 5;
    if ((to - from).length < lengthSize * 4)
        return;
    var vector = to - from;
    var awayVector = vector.normalize(lengthSize).rotate(90     * sign);
    var upVector = vector.normalize(lengthSize).rotate(45 *     sign);
    var downVector = upVector.rotate(-90 * sign);
    var lengthVector = vector.normalize(
            vector.length / 2 - lengthSize *    Math.sqrt(2));
    var line = new Path();
    line.add(from + awayVector);
    line.lineBy(upVector);
    line.lineBy(lengthVector);
    line.lineBy(upVector);
    var middle = line.lastSegment.point;
    line.lineBy(downVector);
    line.lineBy(lengthVector);
    line.lineBy(downVector);
    dashedItems.push(line);
    if (label) {
        // Length Label
        var textAngle = Math.abs(vector.angle) > 90
                ? textAngle = 180 + vector.angle    : vector.angle;
        // Label needs to move away by different amounts    based on the
        // vector's quadrant:
        var away = (sign >= 0 ? [1, 4] : [2,    3]).indexOf(vector.quadrant) != -1
                ? 8 : 0;
        value = value || vector.length;
        var text = new PointText({
            point: middle +     awayVector.normalize(away + lengthSize),
            content: (prefix || '') +   Math.floor(value * 1000) / 1000,
            fillColor: 'black',
            justification: 'center'
        });
        text.rotate(textAngle);
        items.push(text);
    }
}

var dashItem;

function onMouseDown(event) {
    var end = vectorStart + vector;
    var create = false;
    if (event.modifiers.shift && vectorItem) {
        vectorStart = end;
        create = true;
    } else if (vector && (event.modifiers.option
            || end && end.getDistance(event.point) <    10)) {
        create = false;
    } else {
        vectorStart = event.point;
    }
    if (create) {
        dashItem = vectorItem;
        vectorItem = null;
    }
    processVector(event, true);
//  document.redraw();
}

function onMouseDrag(event) {
    if (!event.modifiers.shift && values.fixLength &&   values.fixAngle)
        vectorStart = event.point;
    processVector(event, event.modifiers.shift);
}

function onMouseUp(event) {
    processVector(event, false);
    if (dashItem) {
        dashItem.dashArray = [1, 2];
        dashItem = null;
    }
    vectorPrevious = vector;
}

最佳答案

请阅读我代码中的注释。

您可以为此添加一个按钮菜单: 为了绘制最后一条线,您需要删除点数组中的最后一个点 为了开始一组新的线,您可以创建一个点数组。

我希望这能帮助你开始你的项目。

const ctx = canvas.getContext("2d");
let cw = (canvas.width = window.innerWidth);
let ch = (canvas.height = window.innerWidth);
//the size of the cell relative to the width of the window
let size = cw / 50;
// the cells array
let cells = [];
// the points array.
let points = [];

class Cell {
  constructor(x, y, r) {
    this.x = x;
    this.y = y;
    this.r = r;
  }

  draw() {
    ctx.beginPath();
    ctx.moveTo(this.x - this.r, this.y - this.r);
    ctx.lineTo(this.x + this.r, this.y - this.r);
    ctx.lineTo(this.x + this.r, this.y + this.r);
    ctx.lineTo(this.x - this.r, this.y + this.r);
    ctx.closePath();
    //no stroke 
  }
  center() {
    // this is drawing a dot in the middle of the cell
    ctx.beginPath();
    ctx.arc(this.x, this.y, 2, 0, 2 * Math.PI);
    ctx.fill();
  }
}


// draw the grid of cells
for (let y = size / 2; y < ch; y += 2 * size) {
  for (let x = size / 2; x < cw; x += 2 * size) {
    cells.push(new Cell(x, y, size));
  }
}

cells.forEach(c => {
  //uncomment to see the cells
  //c.draw()
  //ctx.stroke();
  c.center();
});



canvas.addEventListener("click", evt => {
  // the mouse position
  let m = oMousePos(canvas, evt);
  // clear the context
  ctx.clearRect(0, 0, cw, ch);
  //redraw every center
  cells.forEach(c => {
    c.center();
  });

  
  for (let i = 0; i < cells.length; i++) {
    cells[i].draw();
    //check if the mouse is inside the cell
    if (ctx.isPointInPath(m.x, m.y)) {
      // marc the clicked cel with a red dot
      ctx.fillStyle = "red";
      cells[i].center();
      //store the number of the clicked cell in the points array
      points.push(i); 
      ctx.fillStyle = "black";
      //exit the loop
      break;
    }
  }
if(points.length >0){drawLines();}
});



function drawLines() {
  ctx.beginPath();
  ctx.strokeStyle = "black";
  ctx.moveTo(cells[points[0]].x, cells[points[0]].y);
  for (let i = 1; i < points.length; i++) {
    ctx.lineTo(cells[points[i]].x, cells[points[i]].y);
  }
  ctx.stroke();
}


// a function to detect the mouse position
function oMousePos(canvas, evt) {
  var ClientRect = canvas.getBoundingClientRect();
  return {
    x: Math.round(evt.clientX - ClientRect.left),
    y: Math.round(evt.clientY - ClientRect.top)
  };
}

function Init() {
  // get again the size of the canvas
  cw = canvas.width = window.innerWidth;
  ch = canvas.height = window.innerWidth;
  //the size of every cell
  size = cw / 50;
  // empty the cells array
  cells = [];
  // draw again the grid of cells
  for (let y = size / 2; y < ch; y += 2 * size) {
    for (let x = size / 2; x < cw; x += 2 * size) {
      cells.push(new Cell(x, y, size));
    }
  }
  //draw the center of every cell
  cells.forEach(c => {
    c.center();
  });
  //draw the lines
  if(points.length >0){drawLines();}
}



window.setTimeout(function() {
  Init();
  window.addEventListener("resize", Init, false);
}, 15);
canvas{background:#efefef}
<canvas id="canvas"></canvas>

关于javascript - 如何着手允许在网格上的点之间绘制矢量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55521612/

相关文章:

javascript - 使用否定守卫

javascript - 是否可以删除 Outlook 加载项中的漫游数据?

javascript - 如何创建模式登录弹出窗口?

javascript - 可视化调色板查询javascript circosjs

ios - 在 native iOS 应用程序中启用自动播放

html - 相对div内绝对div的高度

javascript - 非常长的 CSS 列的分节符

javascript - 使用 Xcode 远程构建到 Mac 上的 Cordova "Error mounting to image"和 "No devices found to debug"

javascript - useContext() 返回未定义

jquery - 如何使 Bootstrap 轮播 slider 使用移动左/右滑动