【发布时间】:2023-02-05 03:19:26
【问题描述】:
我正在使用 fabric.js、typescript 和 vite 创建一个可平移、可缩放、无限网格编辑器。 因为我实现了捕捉到网格,所以最好有一个网格实际位置的视觉帮助。 我开始只是用 css 简单地制作网格(或点域,因为这样更好),像这样:
:root {
--dot-opacity: 40%; /* 22.5% */
--dot-color: hsla(0, 0%, 35%, var(--dot-opacity));
--dot-spacing: 16px;
--dot-size: 2px;
--main-bg: #19191b;
}
并将其添加到包装器元素中。
background-color: var(--main-bg);
background-repeat: repeat; */
background-image: radial-gradient(circle, var(--dot-color) var(--dot-size), transparent var(--dot-size));
background-size: var(--dot-spacing) var(--dot-spacing);
background-attachment: local;
background-position-x: calc(var(--dot-spacing) / 2) ;
background-position-y: calc(var(--dot-spacing) / 2) ; */
这工作得很好,但是一旦你想通过 fabric.js canvas.viewportTransform 实现平移,点就不再对齐了。
我仍然想像现在一样保留网格的动态/参数特性,但以某种方式使用 fabric.js 将画布背景设置为重复的点矩阵,并使用画布视口变换进行平移。
我试过的:
我制作了一个带有 4 个圆圈的 svg,每个角一个,在视图框中只显示每个圆圈的 1/4 - 一个图块。 我尝试生成它们的方式有两种,并且都可以生成有效的 svg:
const circlePositions = [[size, 0], [0, 0], [size, size], [0, size]]
const circleStyle = `fill:#ffffff;stroke:#9d5867;stroke-width:0;`
第一次尝试:通过document.createElementNS:(assingAttributesSVG 只是循环 Object.entries 并使用 svg.setAttribute)
const tileSvgElem = document.createElementNS("http://www.w3.org/2000/svg", "svg")
assignAttributesSVG(tileSvgElem, { width: size, height: size, viewBox: `0 0 ${size} ${size}`, version: "1.1" })
tileSvgElem.innerHTML = `<defs/><g>${
circlePositions
.map(([cx, cy]) => `<circle style="${circleStyle}" cx="${cx}" cy="${cy}" r="${r}"/>`)
.join("\n")
}</g></svg>`
第二次尝试:通过纯字符串:
const tileSvgString = `<svg width="${size}" height="${size}" viewBox="0 0 ${size} ${size}" version="1.1" xmlns="http://www.w3.org/2000/svg"><defs/><g>
${circlePositions.map(([cx, cy]) => `<circle style="${circleStyle}" cx="${cx}" cy="${cy}" r="${r}"/>`).join("\n")}
</g></svg>`
这两者都符合预期,但是我无法将它们设置为画布背景:
试图将其设置为背景
- 显然 fabric.js 处理 svg 的方式与图像不同 - 我不能只使用
canvas.setBackgroundColor或canvas.SetBackgroundImage设置 svg 元素。打字稿告诉我typeof SVGSVGElement is not SVGImageElement,或者类似的东西。 - 我尝试使用
fabric.Image、fabric.Pattern - 还有
fabric.loadSVGFromString=>fabric.util.groupSVGElements(objects, options) - 同时创建一个
fabric.StaticCanvas和.getElement()
我还尝试将 svg 内联为 data:svg,有和没有 url(""):
function inlineSVGString(svgString: string) {
return `data:image/svg+xml;utf8,${encodeURIComponent(svgString)}`
}
function urlSVGString(svgString: string) {
return `url("${inlineSVGString(svgString)}")`
}
展示
毕竟,我仍然无法为 fabric.js 画布获得重复的点矩阵/点域背景。我该怎么做呢?
可能有一些非常明显的方法可以做到这一点,我错过了,我几天前刚拿起 fabric.js,但文档不是很好,因为它们是从 JSDoc 自动生成的,所以我有点依赖演示,教程、codepen 示例和 fabric.js 的 typescript defs
其他想法:
- 仍然使用旧的 css 方法,但使用
canvas.on('mouse:move')->this.viewportTransform并将background-position-x和background-position-y设置为当前变换 % 网格大小
【问题讨论】:
标签: javascript typescript svg html5-canvas fabricjs