如何对齐多边形外边缘上的点以获得 svg 中较粗的边框?

How to align points on the outer edges of polygon for thicker border in svg?

我的问题是:

我有一个通过取一些点绘制的多边形,我在多边形 edges/outline 上显示这些点。当我增加多边形的 stroke-width 时,点在轮廓的中心对齐。我们如何实现 edge/border 外侧的点对齐?

实际情况如下图,点在border/stroke

上居中对齐

工作区域link为此 https://codepen.io/jinata92/pen/JjKZeqE

我正在寻找如下图所示的解决方案,这些点应该在 border/stroke

的外边缘对齐

var height = 100,
  width = 100;
var polygon;
var arrVertexes = [
  [6, 6],
  [94, 6],
  [94, 94],
  [6, 94]
];

var svg, gContainer;

function config() {
  svg = d3
    .select(".main")
    .attr("width", width)
    .attr("height", height)
    .attr("viewBox", `0 0 ${width} ${height}`);

  gContainer = svg.select("g");
}

function drawPolygon() {
  polygon = gContainer
    .append("polygon")
    .attr("points", arrVertexes)
    .attr("class", "segment");
}

function drawCircle() {
  gContainer
    .selectAll("circle")
    .data(arrVertexes)
    .enter()
    .append("circle")
    .attr("class", "vertex")
    .classed("handle", true)
    .attr("cx", function(d) {
      return d[0];
    })
    .attr("cy", function(d) {
      return d[1];
    })
    .attr("r", 4);
}

config();
drawPolygon();
drawCircle();
body {
  background-color: grey;
}

svg {
  position: absolute;
  overflow: visible;
}

.resize-div {
  position: relative;
  overflow: visible;
}

.polygon {
  stroke: yellow;
  fill: transparent;
}

.vertex,
.dot {
  fill: black;
  stroke: none;
}

.segment {
  stroke-width: 30;
  stroke: yellow;
}
<script src="https://d3js.org/d3.v4.min.js"></script>

<div style="width:100px;height:100px; left: 400px;
                    top:50px;" class="resize-div">
  <svg class="main" height="100%" width="100%">
    <g class="polygon"></g>

  </svg>
</div>

stroke-width 始终应用于两侧,因此线的中心仍在所需位置。但是有一些解决方法。一种是只绘制形状,但也应用 clip path 等于元素,但 没有 笔画宽度:

var height = 100,
  width = 100;
var polygon;
var arrVertexes = [
  [6, 6],
  [94, 6],
  [94, 94],
  [6, 94]
];

var svg, gContainer;

function config() {
  svg = d3
    .select(".main")
    .attr("width", width)
    .attr("height", height)
    .attr("viewBox", `0 0 ${width} ${height}`);

  gContainer = svg.select("g");
}

function drawPolygon() {
  polygon = gContainer
    .append("polygon")
    .attr("clip-path", "url('#my-clip-path')")
    .attr("points", arrVertexes)
    .attr("class", "segment");

  // Append a clip path
  svg.append("defs")
    .append("clipPath")
    .attr("id", "my-clip-path")
    .append("polygon")
    .attr("points", arrVertexes)
    .attr("class", "segment");
}

function drawCircle() {
  gContainer
    .selectAll("circle")
    .data(arrVertexes)
    .enter()
    .append("circle")
    .attr("class", "vertex")
    .classed("handle", true)
    .attr("cx", function(d) {
      return d[0];
    })
    .attr("cy", function(d) {
      return d[1];
    })
    .attr("r", 4);
}

config();
drawPolygon();
drawCircle();
body {
  background-color: grey;
}

svg {
  position: absolute;
  overflow: visible;
}

.resize-div {
  position: relative;
  overflow: visible;
}

.polygon {
  stroke: yellow;
  fill: transparent;
}

.vertex,
.dot {
  fill: black;
  stroke: none;
}

.segment {
  stroke-width: 30;
  stroke: yellow;
}
<script src="https://d3js.org/d3.v4.min.js"></script>

<div style="width:100px;height:100px; left: 400px;
                    top:50px;" class="resize-div">
  <svg class="main" height="100%" width="100%">
    <g class="polygon"></g>

  </svg>
</div>

或者,您可以在另一个多边形之上绘制一个多边形,但要向内一点。使用边界框计算外多边形的中心,并将内多边形的坐标向内移动一些像素:

var height = 100,
  width = 100;
var polygon;
var arrVertexes = [
  [6, 6],
  [94, 6],
  [94, 94],
  [6, 94]
];

var svg, gContainer;

function config() {
  svg = d3
    .select(".main")
    .attr("width", width)
    .attr("height", height)
    .attr("viewBox", `0 0 ${width} ${height}`);

  gContainer = svg.select("g");
}

function drawPolygon() {
  polygon = gContainer
    .append("polygon")
    .attr("points", arrVertexes)
    .attr("class", "segment-border");

  // Get the bounding box so you can calculate the centre
  const boundingBox = polygon.node().getBBox();
  const centre = {
    x: boundingBox.x + boundingBox.width / 2,
    y: boundingBox.y + boundingBox.height / 2,
  };

  const innerVertexes = arrVertexes.map(d => [
    d[0] < centre.x ? d[0] + 15 : d[0] - 15,
    d[1] < centre.y ? d[1] + 15 : d[1] - 15,
  ]);
  polygon = gContainer
    .append("polygon")
    .attr("points", innerVertexes)
    .attr("class", "segment");
}

function drawCircle() {
  gContainer
    .selectAll("circle")
    .data(arrVertexes)
    .enter()
    .append("circle")
    .attr("class", "vertex")
    .classed("handle", true)
    .attr("cx", function(d) {
      return d[0];
    })
    .attr("cy", function(d) {
      return d[1];
    })
    .attr("r", 4);
}

config();
drawPolygon();
drawCircle();
body {
  background-color: grey;
}

svg {
  position: absolute;
  overflow: visible;
}

.resize-div {
  position: relative;
  overflow: visible;
}

.polygon {
  stroke: yellow;
  fill: transparent;
}

.vertex,
.dot {
  fill: black;
  stroke: none;
}

.segment-border {
  fill: yellow;
}

.segment {
  fill: white;
}
<script src="https://d3js.org/d3.v4.min.js"></script>

<div style="width:100px;height:100px; left: 400px;
                    top:50px;" class="resize-div">
  <svg class="main" height="100%" width="100%">
    <g class="polygon"></g>

  </svg>
</div>