【问题标题】:Drawing a scalloped rectangle绘制扇形矩形
【发布时间】:2016-12-02 20:18:58
【问题描述】:

我正在尝试用鼠标绘制扇形矩形,如下图所示

我可以用下面的代码绘制矩形

function Rectangle(start, end) {
  var w = (end.x - start.x);
  var h = (end.y - start.y);
  return ["M", start.x, start.y, "L", (start.x + w), start.y, "L", start.x + w, start.y + h, "L", start.x, start.y + h, "L", start.x, start.y].join(' ');
}

var point;
document.addEventListener('mousedown', function(event) {
  point = {
    x: event.clientX,
    y: event.clientY
  }
});

document.addEventListener('mousemove', function(event) {
  var target = {
    x: event.clientX,
    y: event.clientY
  }
  if(point) {
    var str = Rectangle(point, target);
    document.getElementById('test').setAttribute('d', str);
  }
});

document.addEventListener('mouseup', function(event) {
  point = null;
});
body, html {
  height: 100%;
  width: 100%;
  margin: 0;
  padding: 0
}
svg {
  height:100%;
  width: 100%
}
<svg>
    <path id="test" style="stroke-width: 4; stroke: RGBA(212, 50, 105, 1.00); fill: none" />
  </svg>

但是当我尝试转换成扇形矩形时,我看到不同的模式完全匹配 Infinite Monkey Theorm

我尝试的方法是在虚拟元素上绘制矩形路径。将每个点的长度乘以 15 直到总长度。然后在这些点之间绘制弧线。它不工作。另外,我想避免使用getPointAtLength,因为它的移动支持不是很好。

var pathEle = document.createElementNS('http://www.w3.org/2000/svg', 'path');
pathEle.setAttribute('d', rectangle(point, target));
window.pathEle = pathEle;

var points = [];
for (var i = 0; i < pathEle.getTotalLength(); i += 15) {
  points.push(pathEle.getPointAtLength(i));
}

document.getElementById('test1').setAttribute('d', toSVGPath(points));

【问题讨论】:

  • 如果矩形边的长度不是 15 的倍数会怎样?应该如何处理这么小的剩余长度?
  • @PaulLeBeau 它不会是对称的。附图中的第一个框是我想要实现的完美示例。角落应该变成弧线。所以数字15是随机取的,我假设应该是计算值

标签: javascript svg


【解决方案1】:

这样的?

我正在使用弧线来制作扇贝。您可能需要调整扇贝的计算方式以获得更好的角。但我会把它留给你。

var scallopSize = 30;

function Rectangle(start, end) {
  var minX = Math.min(start.x, end.x);
  var minY = Math.min(start.y, end.y);
  var w = Math.abs(end.x - start.x);
  var h = Math.abs(end.y - start.y);

  // Calculate scallop sizes
  var numW = Math.round(w / scallopSize);
  if (numW === 0) numW = 1;
  var numH = Math.round(h / scallopSize);
  if (numH === 0) numH = 1;
  var stepW = w / numW;
  var stepH = h / numH;

  // top
  var p = minX + stepW/2;  // start each size at half a scallop along
  var path = ["M", p, minY];
  for (var i=1; i < numW; i++) {   // numW-1 scallops per side
    p += stepW;
    path.push('A');
    path.push(stepW/2 + 1);   // Add 1 to the radius to ensure it's
    path.push(stepW/2 + 1);   // big enough to span the stepW
    path.push("0 0 1");
    path.push(p);
    path.push(minY);
  }
  // top right
  var p = minY + stepH/2;
  path.push('A');
  path.push(stepH/2.8);  // 2 * sqrt(2)
  path.push(stepH/2.8);  // corners are a little smaller than the scallops
  path.push("0 0 1");
  path.push(minX + w);
  path.push(p);
  // right
  for (var i=1; i < numH; i++) {
    p += stepH;
    path.push('A');
    path.push(stepH/2 + 1);
    path.push(stepH/2 + 1);
    path.push("0 0 1");
    path.push(minX + w);
    path.push(p);
  }
  // bottom right
  var p = minX + w - stepW/2;
  path.push('A');
  path.push(stepH/2.8);
  path.push(stepH/2.8);  
  path.push("0 0 1");
  path.push(p);
  path.push(minY + h);
  // bottom
  for (var i=1; i < numW; i++) {
    p -= stepW;
    path.push('A');
    path.push(stepW/2 + 1);
    path.push(stepW/2 + 1);
    path.push("0 0 1");
    path.push(p);
    path.push(minY + h);
  }
  // bottom left
  var p = minY + h - stepH/2;
  path.push('A');
  path.push(stepH/2.8);
  path.push(stepH/2.8);  
  path.push("0 0 1");
  path.push(minX);
  path.push(p);
  // left
  for (var i=1; i < numH; i++) {
    p -= stepH;
    path.push('A');
    path.push(stepH/2 + 1);
    path.push(stepH/2 + 1);
    path.push("0 0 1");
    path.push(minX);
    path.push(p);
  }
  // top left
  path.push('A');
  path.push(stepH/2.8);
  path.push(stepH/2.8);  
  path.push("0 0 1");
  path.push(minX + stepW/2);
  path.push(minY);
  path.push('Z');

  return path.join(' ');
}

var point;
document.addEventListener('mousedown', function(event) {
  point = {
    x: event.clientX,
    y: event.clientY
  }
});

document.addEventListener('mousemove', function(event) {
  var target = {
    x: event.clientX,
    y: event.clientY
  }
  if(point) {
    var str = Rectangle(point, target);
    document.getElementById('test').setAttribute('d', str);
  }
});

document.addEventListener('mouseup', function(event) {
  point = null;
});
body, html {
  height: 100%;
  width: 100%;
  margin: 0;
  padding: 0
}
svg {
  height:100%;
  width: 100%
}
<svg>
    <path id="test" style="stroke-width: 4; stroke: RGBA(212, 50, 105, 1.00); fill: none" />
  </svg>

【讨论】:

  • 这正是我正在寻找的东西。你能把角调整成和其他扇贝一样大吗?
  • 我将把它留给你作为练习。我的回答旨在向您展示如何开始。如果您想聘请我让这个示例完全按照您的要求运行,请告诉我。
  • 它正在工作。 :) 顺便说一句,如果你想和我一起工作,我很高兴听到这个消息 :) 如果准备好了,请发送电子邮件
猜你喜欢
  • 2014-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-17
  • 1970-01-01
  • 2016-10-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多