使用 fabricjs 创建重复图像模式
Create a repetitive image pattern using fabricjs
正如标题所说,我正在尝试通过在我的 canvas 元素中重复相同的图像来创建平铺图案。
这是我目前尝试过的方法:<canvas id='c' width='345' height='345'></canvas>
let canvas = new fabric.Canvas('c',{backgroundColor: "#fff"});
const logo = 'https://www.logomaker.com/wpstatic/uploads/2018/11/bakerylogo2.png';
canvas.add(
new fabric.Line([7,10,17,10],{
fill: "grey",
stroke: "grey",
strokeWidth: 3
}),
new fabric.Line([10,10,10,150],{
fill: "grey",
stroke: "grey",
strokeWidth: 3
}),
new fabric.IText("500mm",{
left: 20,
top: 152,
fill: "grey",
stroke: "grey",
fontSize: 10,
angle: 90
}),
new fabric.Line([10, 190, 10, 315], {
fill: "grey",
stroke: "grey",
strokeWidth: 3
}),
new fabric.Line([7,315,17,315],{
fill: "grey",
stroke: "grey",
strokeWidth: 3
}),
new fabric.Line([30,333,30,320],{
fill: "grey",
stroke: "grey",
strokeWidth: 3
}),
new fabric.Line([30,325,150,325],{
fill: "grey",
stroke: "grey",
strokeWidth: 3
}),
new fabric.IText("380mm",{
left: 152,
top: 320,
fill: "grey",
stroke: "grey",
fontSize: 10,
}),
new fabric.Line([187,325,310,325],{
fill: "grey",
stroke: "grey",
strokeWidth: 3
}),
new fabric.Line([310,333,310,320],{
fill: "grey",
stroke: "grey",
strokeWidth: 3
}),
)
fabric.Image.fromURL(logo, function(img) {
var oImg = img.set({
left: 40,
top: 40,
angle: 310
}).scale(0.1);
canvas.add(oImg);
})
canvas.renderTop();
,但现在卡住了。
这里有一个 jsfiddle,如果它有助于更快地可视化问题:https://jsfiddle.net/1fevg8dc/3/
任何正确方向的帮助都会对我有很大帮助,因为我真的很难理解 fabricjs 的文档。
我的最终目标是在图像(声明为徽标)上应用灰度滤镜并将图像旋转 45 度,并在我
的线条内创建图案
作为 fabric.js 背景的平铺重复图案实际上并不难做到。但是,您的问题是您希望它成一定角度并应用灰度滤镜。
无论如何,首先我们需要创建一个 canvas.js Shape
对象 - 这将作为我们的背景,因此需要覆盖整个视口。
let shape = new fabric.Rect({
width: canvas.width,
height: canvas.height,
left: 0,
top: 0,
selectable: false
});
不过我们还没有将它添加到舞台上。因为我们想用图像填充形状,所以我们需要先加载它。对于此任务,我们使用 Image 对象的 .fromURL()
方法。
fabric.Image.fromURL("https://corsanywhere.herokuapp.com/https://www.logomaker.com/wpstatic/uploads/2018/11/bakerylogo2.png", function(img) {}, {crossOrigin: 'anonymous'})
在空回调函数中 - function(img) {}
- 必须发生以下情况:
- 将图像转换为灰度
- 使用此图像作为形状的填充
- 旋转填充,例如45°
第一步是使用 fabric.js built-in 过滤器
img.filters.push(new fabric.Image.filters.Grayscale());
img.applyFilters();
第二步涉及创建一个 Pattern
对象,然后将其应用于 Shape
对象。
最后一步是棘手的部分。填充没有旋转 属性。相反,它使用 patternTransform
属性 通过变换矩阵进行变换。此 patternTransform 是一个包含 6 个值的数组,用于控制位置、缩放和倾斜。对于 45 度旋转,它必须是这样的:
let angle = -45 * Math.PI / 180;
let transformMatrix=[Math.cos(angle), Math.sin(angle), -Math.sin(angle), Math.cos(angle), 0, 0];
让我们详细说明一下变换矩阵。正如我所说,它包含六个值。如果我们给
那些有意义的名字看起来有点像这样:
matrix= [scaleX, skewY, skewX, scaleY, translateX, translateY];
我们可以看到没有控制旋转的值。那是因为在矩阵中,旋转
是倾斜和缩放的组合。如果我们回顾一下自己的转变:
let transformMatrix = [Math.cos(angle), Math.sin(angle), -Math.sin(angle), Math.cos(angle), 0, 0];
确实是 scaleX
、skewY
、skewX
和 scaleY
属性被填充。
如果我们要改变矩阵的比例,我们需要改变的是 scaleX
和 scaleY
特性。然而,在这种情况下,它有点不同,因为我们已经应用了旋转。幸运的是
这并不难。刻度本身是一个十进制数,其中1表示不变,2是双刻度
例如,0.5 是比例的一半。所以如果我们想把图案变成原来大小的一半,我们
需要将 scaleX、skewY、skewX 和 scaleY 乘以 0.5。
let angle = -45 * Math.PI / 180;
let scale = 0.5;
let transformMatrix = [Math.cos(angle) * scale, Math.sin(angle) * scale, -Math.sin(angle) * scale, Math.cos(angle) * scale, 0, 0];
现在,如果我们将所有内容放在一起,我们将得出以下结果:
let canvas = this.__canvas = new fabric.Canvas('c');
let shape = new fabric.Rect({
width: canvas.width,
height: canvas.height,
left: 0,
top: 0,
selectable: false
});
fabric.Image.fromURL("https://corsanywhere.herokuapp.com/https://www.logomaker.com/wpstatic/uploads/2018/11/bakerylogo2.png", function(img) {
img.filters.push(new fabric.Image.filters.Grayscale());
img.applyFilters();
let angle = -45 * Math.PI / 180;
let scale = 0.5;
shape.set('fill', new fabric.Pattern({
source: img._element,
repeat: 'repeat',
patternTransform: [Math.cos(angle) * scale, Math.sin(angle) * scale, -Math.sin(angle) * scale, Math.cos(angle) * scale, 0, 0]
}));
canvas.add(shape);
canvas.renderAll();
}, {
crossOrigin: 'anonymous'
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/500/fabric.min.js" integrity="sha512-ft2xOUYF7h2UeYQUbol4GJHrkGPVrgimINEYwLI23hyxN1JIy6EEj2vEc8RWWIIExvUKZvYq3oJTDrbif2oSVw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<canvas id="c" width="800" height="600" style="border:1px solid #ccc"></canvas>
正如标题所说,我正在尝试通过在我的 canvas 元素中重复相同的图像来创建平铺图案。
这是我目前尝试过的方法:<canvas id='c' width='345' height='345'></canvas>
let canvas = new fabric.Canvas('c',{backgroundColor: "#fff"});
const logo = 'https://www.logomaker.com/wpstatic/uploads/2018/11/bakerylogo2.png';
canvas.add(
new fabric.Line([7,10,17,10],{
fill: "grey",
stroke: "grey",
strokeWidth: 3
}),
new fabric.Line([10,10,10,150],{
fill: "grey",
stroke: "grey",
strokeWidth: 3
}),
new fabric.IText("500mm",{
left: 20,
top: 152,
fill: "grey",
stroke: "grey",
fontSize: 10,
angle: 90
}),
new fabric.Line([10, 190, 10, 315], {
fill: "grey",
stroke: "grey",
strokeWidth: 3
}),
new fabric.Line([7,315,17,315],{
fill: "grey",
stroke: "grey",
strokeWidth: 3
}),
new fabric.Line([30,333,30,320],{
fill: "grey",
stroke: "grey",
strokeWidth: 3
}),
new fabric.Line([30,325,150,325],{
fill: "grey",
stroke: "grey",
strokeWidth: 3
}),
new fabric.IText("380mm",{
left: 152,
top: 320,
fill: "grey",
stroke: "grey",
fontSize: 10,
}),
new fabric.Line([187,325,310,325],{
fill: "grey",
stroke: "grey",
strokeWidth: 3
}),
new fabric.Line([310,333,310,320],{
fill: "grey",
stroke: "grey",
strokeWidth: 3
}),
)
fabric.Image.fromURL(logo, function(img) {
var oImg = img.set({
left: 40,
top: 40,
angle: 310
}).scale(0.1);
canvas.add(oImg);
})
canvas.renderTop();
,但现在卡住了。
这里有一个 jsfiddle,如果它有助于更快地可视化问题:https://jsfiddle.net/1fevg8dc/3/
任何正确方向的帮助都会对我有很大帮助,因为我真的很难理解 fabricjs 的文档。
我的最终目标是在图像(声明为徽标)上应用灰度滤镜并将图像旋转 45 度,并在我
的线条内创建图案作为 fabric.js 背景的平铺重复图案实际上并不难做到。但是,您的问题是您希望它成一定角度并应用灰度滤镜。
无论如何,首先我们需要创建一个 canvas.js Shape
对象 - 这将作为我们的背景,因此需要覆盖整个视口。
let shape = new fabric.Rect({
width: canvas.width,
height: canvas.height,
left: 0,
top: 0,
selectable: false
});
不过我们还没有将它添加到舞台上。因为我们想用图像填充形状,所以我们需要先加载它。对于此任务,我们使用 Image 对象的 .fromURL()
方法。
fabric.Image.fromURL("https://corsanywhere.herokuapp.com/https://www.logomaker.com/wpstatic/uploads/2018/11/bakerylogo2.png", function(img) {}, {crossOrigin: 'anonymous'})
在空回调函数中 - function(img) {}
- 必须发生以下情况:
- 将图像转换为灰度
- 使用此图像作为形状的填充
- 旋转填充,例如45°
第一步是使用 fabric.js built-in 过滤器
img.filters.push(new fabric.Image.filters.Grayscale());
img.applyFilters();
第二步涉及创建一个 Pattern
对象,然后将其应用于 Shape
对象。
最后一步是棘手的部分。填充没有旋转 属性。相反,它使用 patternTransform
属性 通过变换矩阵进行变换。此 patternTransform 是一个包含 6 个值的数组,用于控制位置、缩放和倾斜。对于 45 度旋转,它必须是这样的:
let angle = -45 * Math.PI / 180;
let transformMatrix=[Math.cos(angle), Math.sin(angle), -Math.sin(angle), Math.cos(angle), 0, 0];
让我们详细说明一下变换矩阵。正如我所说,它包含六个值。如果我们给 那些有意义的名字看起来有点像这样:
matrix= [scaleX, skewY, skewX, scaleY, translateX, translateY];
我们可以看到没有控制旋转的值。那是因为在矩阵中,旋转 是倾斜和缩放的组合。如果我们回顾一下自己的转变:
let transformMatrix = [Math.cos(angle), Math.sin(angle), -Math.sin(angle), Math.cos(angle), 0, 0];
确实是 scaleX
、skewY
、skewX
和 scaleY
属性被填充。
如果我们要改变矩阵的比例,我们需要改变的是 scaleX
和 scaleY
特性。然而,在这种情况下,它有点不同,因为我们已经应用了旋转。幸运的是
这并不难。刻度本身是一个十进制数,其中1表示不变,2是双刻度
例如,0.5 是比例的一半。所以如果我们想把图案变成原来大小的一半,我们
需要将 scaleX、skewY、skewX 和 scaleY 乘以 0.5。
let angle = -45 * Math.PI / 180;
let scale = 0.5;
let transformMatrix = [Math.cos(angle) * scale, Math.sin(angle) * scale, -Math.sin(angle) * scale, Math.cos(angle) * scale, 0, 0];
现在,如果我们将所有内容放在一起,我们将得出以下结果:
let canvas = this.__canvas = new fabric.Canvas('c');
let shape = new fabric.Rect({
width: canvas.width,
height: canvas.height,
left: 0,
top: 0,
selectable: false
});
fabric.Image.fromURL("https://corsanywhere.herokuapp.com/https://www.logomaker.com/wpstatic/uploads/2018/11/bakerylogo2.png", function(img) {
img.filters.push(new fabric.Image.filters.Grayscale());
img.applyFilters();
let angle = -45 * Math.PI / 180;
let scale = 0.5;
shape.set('fill', new fabric.Pattern({
source: img._element,
repeat: 'repeat',
patternTransform: [Math.cos(angle) * scale, Math.sin(angle) * scale, -Math.sin(angle) * scale, Math.cos(angle) * scale, 0, 0]
}));
canvas.add(shape);
canvas.renderAll();
}, {
crossOrigin: 'anonymous'
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/500/fabric.min.js" integrity="sha512-ft2xOUYF7h2UeYQUbol4GJHrkGPVrgimINEYwLI23hyxN1JIy6EEj2vEc8RWWIIExvUKZvYq3oJTDrbif2oSVw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<canvas id="c" width="800" height="600" style="border:1px solid #ccc"></canvas>