SVG:在网格上生成越来越多的数字
SVG: generate increasing numbers on grid
所以基本上我有一个网格,它使用 paths/rects 的 parrerns 来绘制网格。在这个网格上,我想在 x 和 y 方向上放置数字。就像您可能从学校知道的坐标系。
我尝试将文本放入模式中,但有两个问题:
- 每个矩形中的文本都相同(不重复)
- 每个矩形都包含文本(而不仅仅是“轴”)
我的猜测是我需要另一个 svg 来解决最后一个问题。
这些是我的模式:
<defs>
<pattern id="smallGrid" width="15px" height="15px" patternUnits="userSpaceOnUse">
<path d="M 15 0 L 0 0 0 15" fill="none" stroke="gray" stroke-width="0.5"/>
</pattern>
<pattern id="grid" width="75" height="75" patternUnits="userSpaceOnUse">
<text x="20" y="70">foo</text> <== Here is the text I inserted
<rect width="75" height="75" fill="url(#smallGrid)"/>
<path d="M 75 0 L 0 0 0 75" fill="none" stroke="blue" stroke-width="4"/>
</pattern>
</defs>
模式被放置在一个 <svg>
标签中,引用它们的 id,如下所示:
<svg>
<g id="viewport">
<rect id="gridParent" fill="url(#grid)"/>
</g>
</svg>
最终结果看起来像这样:
但我想做这样的事情:
感谢您给我的所有提示!!!提前致谢。
正如@Robert Longson 已经指出的:
svg <pattern>
是相当静态的——所以你不能实现任何动态计数器。
如果您不需要突出显示各个列(例如使用不同的填充颜色),您可以在 <text>
元素后附加一些 javaScript.
本质上,您需要遍历由网格宽度和高度定义的所有 columns/grid 单元格,并添加具有适当 x 和 y 坐标的 <text>
元素。
在这种情况下:
(width/height) 600x300 = 8 列; 4行; 32 个网格单元
每次到达迭代索引被列数整除,
当前 y 偏移量根据总行数递增。
示例:向 svg 网格添加标签
const svg = document.querySelector('svg');
const bb = svg.getBBox();
const strokeWidth = 4;
//get viewBox and adjust it to avoid overflow caused by grid strokes
const [x, y, width, height] = [bb.x, bb.y, bb.width + strokeWidth / 2, bb.height + strokeWidth / 2];
svg.setAttribute('viewBox', [x, y, width, height].join(' '));
const cols = Math.floor((width - strokeWidth / 2) / 75);
const rows = Math.floor((height - strokeWidth / 2) / 75);
// add labels
addGridLabelsCoord(svg, cols, rows, width, height, strokeWidth);
function addGridLabelsCoord(svg, cols, rows, width = 1, height = 1, strokeWidth = 1) {
// set initial y/x offset according to stroke width to avoid cropped outer strokes
let offsetX = (width - strokeWidth / 2) / cols;
let offsetY = (height - strokeWidth / 2) / rows;
let currentRow = 1;
let currentCol = 1;
let shiftX = 0;
let shiftY = 0;
let cellCount = cols * rows;
let nameSpace = 'http://www.w3.org/2000/svg';
// loop through all columns
for (let i = 0; i < cellCount; i++) {
// if current index is divisible by columns – move to next row
if (i > 0 && i % (cols) === 0) {
shiftX = 0;
shiftY += offsetY;
currentCol = 1;
currentRow++;
}
// add labels only for first row and first columns
if (currentRow == 1 || currentCol == 1) {
let colLabel = currentCol == 1 ? currentRow - 1 : i;
// add new cell to output
let text = document.createElementNS(nameSpace, 'text');
text.setAttribute('x', +(shiftX + offsetX / 2).toFixed(1));
text.setAttribute('y', +(shiftY + offsetY / 2).toFixed(1));
text.setAttribute('dominant-baseline', 'central');
text.setAttribute('text-anchor', 'middle');
text.textContent = colLabel;
svg.appendChild(text);
}
// increment x offset for next column
shiftX += offsetX;
currentCol++;
}
}
<svg viewBox="0 0 600 300">
<defs>
<pattern id="smallGrid" width="15px" height="15px" patternUnits="userSpaceOnUse">
<path d="M 15 0 L 0 0 0 15" fill="none" stroke="gray" stroke-width="0.5" />
</pattern>
<pattern id="grid" width="75" height="75" patternUnits="userSpaceOnUse">
<rect width="75" height="75" fill="url(#smallGrid)" />
<path d="M 75 0 L 0 0 0 75" fill="none" stroke="blue" stroke-width="4" />
</pattern>
</defs>
<rect x="0" y="0" width="100%" height="100%" id="gridParent" fill="url(#grid)" />
</svg>
所以基本上我有一个网格,它使用 paths/rects 的 parrerns 来绘制网格。在这个网格上,我想在 x 和 y 方向上放置数字。就像您可能从学校知道的坐标系。
我尝试将文本放入模式中,但有两个问题:
- 每个矩形中的文本都相同(不重复)
- 每个矩形都包含文本(而不仅仅是“轴”)
我的猜测是我需要另一个 svg 来解决最后一个问题。
这些是我的模式:
<defs>
<pattern id="smallGrid" width="15px" height="15px" patternUnits="userSpaceOnUse">
<path d="M 15 0 L 0 0 0 15" fill="none" stroke="gray" stroke-width="0.5"/>
</pattern>
<pattern id="grid" width="75" height="75" patternUnits="userSpaceOnUse">
<text x="20" y="70">foo</text> <== Here is the text I inserted
<rect width="75" height="75" fill="url(#smallGrid)"/>
<path d="M 75 0 L 0 0 0 75" fill="none" stroke="blue" stroke-width="4"/>
</pattern>
</defs>
模式被放置在一个 <svg>
标签中,引用它们的 id,如下所示:
<svg>
<g id="viewport">
<rect id="gridParent" fill="url(#grid)"/>
</g>
</svg>
最终结果看起来像这样:
但我想做这样的事情:
感谢您给我的所有提示!!!提前致谢。
正如@Robert Longson 已经指出的:
svg <pattern>
是相当静态的——所以你不能实现任何动态计数器。
如果您不需要突出显示各个列(例如使用不同的填充颜色),您可以在 <text>
元素后附加一些 javaScript.
本质上,您需要遍历由网格宽度和高度定义的所有 columns/grid 单元格,并添加具有适当 x 和 y 坐标的 <text>
元素。
在这种情况下:
(width/height) 600x300 = 8 列; 4行; 32 个网格单元
每次到达迭代索引被列数整除, 当前 y 偏移量根据总行数递增。
示例:向 svg 网格添加标签
const svg = document.querySelector('svg');
const bb = svg.getBBox();
const strokeWidth = 4;
//get viewBox and adjust it to avoid overflow caused by grid strokes
const [x, y, width, height] = [bb.x, bb.y, bb.width + strokeWidth / 2, bb.height + strokeWidth / 2];
svg.setAttribute('viewBox', [x, y, width, height].join(' '));
const cols = Math.floor((width - strokeWidth / 2) / 75);
const rows = Math.floor((height - strokeWidth / 2) / 75);
// add labels
addGridLabelsCoord(svg, cols, rows, width, height, strokeWidth);
function addGridLabelsCoord(svg, cols, rows, width = 1, height = 1, strokeWidth = 1) {
// set initial y/x offset according to stroke width to avoid cropped outer strokes
let offsetX = (width - strokeWidth / 2) / cols;
let offsetY = (height - strokeWidth / 2) / rows;
let currentRow = 1;
let currentCol = 1;
let shiftX = 0;
let shiftY = 0;
let cellCount = cols * rows;
let nameSpace = 'http://www.w3.org/2000/svg';
// loop through all columns
for (let i = 0; i < cellCount; i++) {
// if current index is divisible by columns – move to next row
if (i > 0 && i % (cols) === 0) {
shiftX = 0;
shiftY += offsetY;
currentCol = 1;
currentRow++;
}
// add labels only for first row and first columns
if (currentRow == 1 || currentCol == 1) {
let colLabel = currentCol == 1 ? currentRow - 1 : i;
// add new cell to output
let text = document.createElementNS(nameSpace, 'text');
text.setAttribute('x', +(shiftX + offsetX / 2).toFixed(1));
text.setAttribute('y', +(shiftY + offsetY / 2).toFixed(1));
text.setAttribute('dominant-baseline', 'central');
text.setAttribute('text-anchor', 'middle');
text.textContent = colLabel;
svg.appendChild(text);
}
// increment x offset for next column
shiftX += offsetX;
currentCol++;
}
}
<svg viewBox="0 0 600 300">
<defs>
<pattern id="smallGrid" width="15px" height="15px" patternUnits="userSpaceOnUse">
<path d="M 15 0 L 0 0 0 15" fill="none" stroke="gray" stroke-width="0.5" />
</pattern>
<pattern id="grid" width="75" height="75" patternUnits="userSpaceOnUse">
<rect width="75" height="75" fill="url(#smallGrid)" />
<path d="M 75 0 L 0 0 0 75" fill="none" stroke="blue" stroke-width="4" />
</pattern>
</defs>
<rect x="0" y="0" width="100%" height="100%" id="gridParent" fill="url(#grid)" />
</svg>