Поскольку радиусы шестиугольников являются переменной x, вы не можете использовать здесь паттерны.основная идея такова:
- фон svg белый;
- шестиугольники имеют
fill:black;
- , чтобы нарисовать шестиугольники, которые необходимо вычислитьцентр описанного круга.Вы делаете это, используя значение радиуса описанной окружности
R
.Это создает гексагональную решетку. - Внутри гексагональной решетки необходимо изменить радиус описанной окружности для шестиугольников в зависимости от y следующим образом:
let r = R * Math.sin(angle)
где угол зависит от функцииx и вычисляется следующим образом: let angle = map(x, 0, H, 0, Math.PI);
Это означает, что x
принимает значение от 0 до 200 (H
), а угол будет иметь значение между o и Math.PI.
Пожалуйста, прочитайте комментарии в моем коде.
const SVG_NS = 'http://www.w3.org/2000/svg';
const SVG_XLINK = "http://www.w3.org/1999/xlink"
// variables used to draw the hexagon stack
let R = 5;// the radius of the circumscribed circle
let h = R * Math.sin(Math.PI / 3);//half height of the hexagon
let offset = 1.5 * R;//used to offset every second row of hexagons
let W = 200,H=200;//svg's viewBox = "0 0 200 200"
//draw the hexagonal lattice
let i = 0;
for(let y = 0; y<H; y+=h){
i++
let o = (i%2 == 0) ? offset : 0;
for(let x = o; x<W; x+=3*R){
hex(x,y)
}
}
// a function used to draw the hexagom
// the radius of the hexagon depends on the x value
function hex(x,y) {
// the radius of the drawn hexagon is in function of the x value
let angle = map(x, 0, H, 0, Math.PI);
let r = R * Math.sin(angle) - .5
let points = ""
for (var a = 0; a < 6; a++) {
let o = {}
o.x = x + r * Math.cos(a * Math.PI / 3);
o.y = y + r * Math.sin(a * Math.PI / 3);
points+= `${o.x}, ${o.y} `
}
let hexagon = drawSVGelmt({points:points},"polygon", svg)
}
// a function used to draw a new svg element
function drawSVGelmt(o,tag, parent) {
let elmt = document.createElementNS(SVG_NS, tag);
for (let name in o) {
if (o.hasOwnProperty(name)) {
elmt.setAttributeNS(null, name, o[name]);
}
}
parent.appendChild(elmt);
return elmt;
}
function map(n, a, b, _a, _b) {
let d = b - a;
let _d = _b - _a;
let u = _d / d;
return _a + n * u;
}
svg{background:white; border:1px solid;width:90vh;}
polygon{fill:black}
<svg id="svg" viewBox = "0 0 200 200" >
</svg>
ОБНОВЛЕНИЕ
ОП комментирует:
Это то, что я хочу, но я 'Я пытаюсь сделать шаблон, чтобы я мог затем использовать этот шаблон для маски для изображения
и более поздних версий:
в основном то, что вы сделали, работает, но мне нужношаблон для повторения по всей странице, потому что изображение будет иметь ширину 100% и высоту около 800 пикселей
В этом случае вы можете поместить все шестиугольники в группу и использовать clipPath
, чтобы обрезать группу следующим образом.:
var SVG_NS = 'http://www.w3.org/2000/svg';
var SVG_XLINK = "http://www.w3.org/1999/xlink"
let H = 800,W=500
var R = 5;
//var l = R;
var h = R * Math.sin(Math.PI / 3);
var offset = 1.5 * R;
let i = 0;
for(let y = 0; y<H; y+=h){
i++
let o = (i%2 == 0) ? offset : 0;
for(let x = o; x<W; x+=3*R){
hex(x,y)
}
}
function hex(x,y) {
let angle = map(x, 0, W, 0, Math.PI);
let r = R * Math.sin(angle) - .5
let points = ""
for (var a = 0; a < 6; a++) {
let o = {}
o.x = x + r * Math.cos(a * Math.PI / 3);
o.y = y + r * Math.sin(a * Math.PI / 3);
points+= `${o.x}, ${o.y} `
}
let hexagon = drawSVGelmt({points:points},"polygon", svg)
}
function drawSVGelmt(o,tag, parent) {
let elmt = document.createElementNS(SVG_NS, tag);
for (let name in o) {
if (o.hasOwnProperty(name)) {
elmt.setAttributeNS(null, name, o[name]);
}
}
parent.appendChild(elmt);
return elmt;
}
function map(n, a, b, _a, _b) {
let d = b - a;
let _d = _b - _a;
let u = _d / d;
return _a + n * u;
}
svg{background:white; border:1px solid;}
polygon{fill:black}
<svg viewBox = "0 0 500 800" >
<clipPath id="clip">
<polygon points="250,0 100,100 0 300 100,600 200,800 400,600 500,500 400,200 250,0"/>
</clipPath>
<g id="svg" style="clip-path: url(#clip)"></g>
</svg>
И если вы не укажете ширину элемента svg, он займет всю доступную ширину, т. Е.: 100%.