Fabric-js 模式:如何根据缩放和模糊矩形从不带大小的矩形为 canvas 背景创建模式
Fabric-js patterns: How create pattern for canvas background from Rects without size depending on Zoom and blured Rects
作为最终目标,我需要为 canvas 创建经典的国际象棋背景来表示 'transparent' 背景,并可选择将其变为真正的透明并返回(在程序中,此处没有直接的用户交互) - 所以我对其他方法持开放态度。
在当前状态下,我已经或多或少地创建了正确的模式并将其添加到 canvas,但我还有两个问题需要解决:
- 两个 Rects 和 Rects 与背景之间的过渡变得模糊而不是锐利。
- 将图案添加到 canvas 时,它会根据页面加载时的页面视觉效果 size/zoom 进行缩放,而不是图案的编程大小和 canvas。 (要检查缩放然后 运行 再次啜饮)
代码:
// initialize fabric canvas and assign to global windows object for debug
var canvas = window._canvas = new fabric.Canvas('c');
const newTransparent = function() {
const chessStatic = new fabric.StaticCanvas();
chessStatic.setHeight(10);
chessStatic.setWidth(10);
chessStatic.renderAll();
chessStatic.setBackgroundColor('lightgrey');
const greyRect = new fabric.Rect({
width: 5,
height: 5,
left: 0,
top: 0,
// fill: 'grey',
strokeWidth: 0
});
greyRect.set('fill', 'rgba(150, 150, 150, 1)')
const lightGreyRect = new fabric.Rect({
width: 5,
height: 5,
left: 5,
top: 5,
// fill: 'grey',
strokeWidth: 0
});
lightGreyRect.set('fill', 'rgba(187, 187, 187, 1)')
chessStatic.add(greyRect);
chessStatic.add(lightGreyRect);
const greyRect2 = greyRect;
chessStatic.add(greyRect);
chessStatic.add(lightGreyRect);
chessStatic.calcOffset();
chessStatic.renderAll();
const transparentPattern = new fabric.Pattern({
source: function() {
return chessStatic.getElement();
},
repeat: 'repeat'
});
return transparentPattern;
}
canvas.setBackgroundColor(newTransparent(), canvas.renderAll.bind(canvas));
fabric.util.addListener(document.getElementById('toggle-repeat'), 'click', function () {
canvas.setBackgroundColor(newTransparent(), canvas.renderAll.bind(canvas));
const lightGreyRect = new fabric.Rect({
width: 5,
height: 5,
left: 5,
top: 5,
// fill: 'grey',
strokeWidth: 0
});
lightGreyRect.set('fill', 'rgba(187, 187, 187, 1)')
canvas.add(lightGreyRect);
canvas.renderAll();
});
fabric.util.addListener(document.getElementById('toggle-bgcolor'), 'click', function () {
if (canvas.backgroundColor instanceof fabric.Pattern) {
canvas.setBackgroundColor('rgba(0, 225, 64, 0.6)', canvas.renderAll.bind(canvas));
}
else {
canvas.setBackgroundColor({source: 'http://fabricjs.com/assets/escheresque_ste.png'}, canvas.renderAll.bind(canvas));
}
});
canvas {
border: 1px solid #999;
}
button {
margin-top: 20px;
}
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<canvas id="c" width="400" height="400"></canvas>
<button id="toggle-repeat">Toggle repeat</button>
<button id="toggle-bgcolor">Toggle background</button>
页面缩放存储在同一个 window 变量中,其中真实像素和虚拟像素之间的比率是(macbook 的 retina 和手机的 hidpis)。
所以当你想做一些不受页面缩放级别影响的事情时,禁用 retinaScaling 并且 canvas 将停止考虑 devicepixelratio
的值。或者您也可以在初始化 canvas.
之前将其设置为最小整数
fabric.devicePixelRatio = Math.max(Math.floor(fabric.devicePixelRatio), 1);
// initialize fabric canvas and assign to global windows object for debug
var canvas = window._canvas = new fabric.Canvas('c', { enableRetinaScaling: false });
const newTransparent = function() {
const chessStatic = new fabric.StaticCanvas(null, { enableRetinaScaling: false });
chessStatic.setHeight(10);
chessStatic.setWidth(10);
chessStatic.renderAll();
chessStatic.setBackgroundColor('lightgrey');
const greyRect = new fabric.Rect({
width: 5,
height: 5,
left: 0,
top: 0,
// fill: 'grey',
strokeWidth: 0
});
greyRect.set('fill', 'rgba(150, 150, 150, 1)')
const lightGreyRect = new fabric.Rect({
width: 5,
height: 5,
left: 5,
top: 5,
// fill: 'grey',
strokeWidth: 0
});
lightGreyRect.set('fill', 'rgba(187, 187, 187, 1)')
chessStatic.add(greyRect);
chessStatic.add(lightGreyRect);
const greyRect2 = greyRect;
chessStatic.add(greyRect);
chessStatic.add(lightGreyRect);
chessStatic.calcOffset();
chessStatic.renderAll();
const transparentPattern = new fabric.Pattern({
source: function() {
return chessStatic.getElement();
},
repeat: 'repeat'
});
return transparentPattern;
}
canvas.setBackgroundColor(newTransparent(), canvas.renderAll.bind(canvas));
fabric.util.addListener(document.getElementById('toggle-repeat'), 'click', function () {
canvas.setBackgroundColor(newTransparent(), canvas.renderAll.bind(canvas));
const lightGreyRect = new fabric.Rect({
width: 5,
height: 5,
left: 5,
top: 5,
// fill: 'grey',
strokeWidth: 0
});
lightGreyRect.set('fill', 'rgba(187, 187, 187, 1)')
canvas.add(lightGreyRect);
canvas.renderAll();
});
fabric.util.addListener(document.getElementById('toggle-bgcolor'), 'click', function () {
if (canvas.backgroundColor instanceof fabric.Pattern) {
canvas.setBackgroundColor('rgba(0, 225, 64, 0.6)', canvas.renderAll.bind(canvas));
}
else {
canvas.setBackgroundColor({source: 'http://fabricjs.com/assets/escheresque_ste.png'}, canvas.renderAll.bind(canvas));
}
});
canvas {
border: 1px solid #999;
}
button {
margin-top: 20px;
}
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<canvas id="c" width="400" height="400"></canvas>
<button id="toggle-repeat">Toggle repeat</button>
<button id="toggle-bgcolor">Toggle background</button>
这段代码还有一个问题 - 矩形模糊不清。
来自其他帖子的提示:
笔画宽度:0,
对象缓存:假
完成了,但它们仍然很模糊。
问题存在于模式和自由对象矩形中。
(有点模糊,但应该不是单色直线的情况)
// initialize fabric canvas and assign to global windows object for debug
var canvas = window._canvas = new fabric.Canvas('c', { enableRetinaScaling: false });
const newTransparent = function() {
const chessStatic = new fabric.StaticCanvas(null, { enableRetinaScaling: false });
chessStatic.setHeight(40);
chessStatic.setWidth(40);
chessStatic.renderAll();
chessStatic.setBackgroundColor('lightgrey');
const greyRect = new fabric.Rect({
width: 20,
height: 20,
left: 0,
top: 0,
fill: 'grey',
strokeWidth: 0,
objectCaching: false
});
//greyRect.set('fill', 'rgba(150, 150, 150, 1)')
const lightGreyRect = new fabric.Rect({
width: 20,
height: 20,
left: 20,
top: 20,
fill: 'grey',
strokeWidth: 0,
objectCaching: false
});
//lightGreyRect.set('fill', 'rgba(187, 187, 187, 1)')
chessStatic.add(greyRect);
chessStatic.add(lightGreyRect);
const greyRect2 = greyRect;
chessStatic.add(greyRect);
chessStatic.add(lightGreyRect);
chessStatic.calcOffset();
chessStatic.renderAll();
const transparentPattern = new fabric.Pattern({
source: function() {
return chessStatic.getElement();
},
repeat: 'repeat'
});
return transparentPattern;
}
canvas.setBackgroundColor(newTransparent(), canvas.renderAll.bind(canvas));
const GreyRect = new fabric.Rect({
width: 20,
height: 20,
left: 20,
top: 20,
fill: 'grey',
strokeWidth: 0,
objectCaching: false
});
canvas.add(GreyRect);
canvas.renderAll();
canvas {
border: 1px solid #999;
}
button {
margin-top: 20px;
}
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<canvas id="c" width="400" height="400"></canvas>
作为最终目标,我需要为 canvas 创建经典的国际象棋背景来表示 'transparent' 背景,并可选择将其变为真正的透明并返回(在程序中,此处没有直接的用户交互) - 所以我对其他方法持开放态度。
在当前状态下,我已经或多或少地创建了正确的模式并将其添加到 canvas,但我还有两个问题需要解决:
- 两个 Rects 和 Rects 与背景之间的过渡变得模糊而不是锐利。
- 将图案添加到 canvas 时,它会根据页面加载时的页面视觉效果 size/zoom 进行缩放,而不是图案的编程大小和 canvas。 (要检查缩放然后 运行 再次啜饮)
代码:
// initialize fabric canvas and assign to global windows object for debug
var canvas = window._canvas = new fabric.Canvas('c');
const newTransparent = function() {
const chessStatic = new fabric.StaticCanvas();
chessStatic.setHeight(10);
chessStatic.setWidth(10);
chessStatic.renderAll();
chessStatic.setBackgroundColor('lightgrey');
const greyRect = new fabric.Rect({
width: 5,
height: 5,
left: 0,
top: 0,
// fill: 'grey',
strokeWidth: 0
});
greyRect.set('fill', 'rgba(150, 150, 150, 1)')
const lightGreyRect = new fabric.Rect({
width: 5,
height: 5,
left: 5,
top: 5,
// fill: 'grey',
strokeWidth: 0
});
lightGreyRect.set('fill', 'rgba(187, 187, 187, 1)')
chessStatic.add(greyRect);
chessStatic.add(lightGreyRect);
const greyRect2 = greyRect;
chessStatic.add(greyRect);
chessStatic.add(lightGreyRect);
chessStatic.calcOffset();
chessStatic.renderAll();
const transparentPattern = new fabric.Pattern({
source: function() {
return chessStatic.getElement();
},
repeat: 'repeat'
});
return transparentPattern;
}
canvas.setBackgroundColor(newTransparent(), canvas.renderAll.bind(canvas));
fabric.util.addListener(document.getElementById('toggle-repeat'), 'click', function () {
canvas.setBackgroundColor(newTransparent(), canvas.renderAll.bind(canvas));
const lightGreyRect = new fabric.Rect({
width: 5,
height: 5,
left: 5,
top: 5,
// fill: 'grey',
strokeWidth: 0
});
lightGreyRect.set('fill', 'rgba(187, 187, 187, 1)')
canvas.add(lightGreyRect);
canvas.renderAll();
});
fabric.util.addListener(document.getElementById('toggle-bgcolor'), 'click', function () {
if (canvas.backgroundColor instanceof fabric.Pattern) {
canvas.setBackgroundColor('rgba(0, 225, 64, 0.6)', canvas.renderAll.bind(canvas));
}
else {
canvas.setBackgroundColor({source: 'http://fabricjs.com/assets/escheresque_ste.png'}, canvas.renderAll.bind(canvas));
}
});
canvas {
border: 1px solid #999;
}
button {
margin-top: 20px;
}
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<canvas id="c" width="400" height="400"></canvas>
<button id="toggle-repeat">Toggle repeat</button>
<button id="toggle-bgcolor">Toggle background</button>
页面缩放存储在同一个 window 变量中,其中真实像素和虚拟像素之间的比率是(macbook 的 retina 和手机的 hidpis)。
所以当你想做一些不受页面缩放级别影响的事情时,禁用 retinaScaling 并且 canvas 将停止考虑 devicepixelratio
的值。或者您也可以在初始化 canvas.
fabric.devicePixelRatio = Math.max(Math.floor(fabric.devicePixelRatio), 1);
// initialize fabric canvas and assign to global windows object for debug
var canvas = window._canvas = new fabric.Canvas('c', { enableRetinaScaling: false });
const newTransparent = function() {
const chessStatic = new fabric.StaticCanvas(null, { enableRetinaScaling: false });
chessStatic.setHeight(10);
chessStatic.setWidth(10);
chessStatic.renderAll();
chessStatic.setBackgroundColor('lightgrey');
const greyRect = new fabric.Rect({
width: 5,
height: 5,
left: 0,
top: 0,
// fill: 'grey',
strokeWidth: 0
});
greyRect.set('fill', 'rgba(150, 150, 150, 1)')
const lightGreyRect = new fabric.Rect({
width: 5,
height: 5,
left: 5,
top: 5,
// fill: 'grey',
strokeWidth: 0
});
lightGreyRect.set('fill', 'rgba(187, 187, 187, 1)')
chessStatic.add(greyRect);
chessStatic.add(lightGreyRect);
const greyRect2 = greyRect;
chessStatic.add(greyRect);
chessStatic.add(lightGreyRect);
chessStatic.calcOffset();
chessStatic.renderAll();
const transparentPattern = new fabric.Pattern({
source: function() {
return chessStatic.getElement();
},
repeat: 'repeat'
});
return transparentPattern;
}
canvas.setBackgroundColor(newTransparent(), canvas.renderAll.bind(canvas));
fabric.util.addListener(document.getElementById('toggle-repeat'), 'click', function () {
canvas.setBackgroundColor(newTransparent(), canvas.renderAll.bind(canvas));
const lightGreyRect = new fabric.Rect({
width: 5,
height: 5,
left: 5,
top: 5,
// fill: 'grey',
strokeWidth: 0
});
lightGreyRect.set('fill', 'rgba(187, 187, 187, 1)')
canvas.add(lightGreyRect);
canvas.renderAll();
});
fabric.util.addListener(document.getElementById('toggle-bgcolor'), 'click', function () {
if (canvas.backgroundColor instanceof fabric.Pattern) {
canvas.setBackgroundColor('rgba(0, 225, 64, 0.6)', canvas.renderAll.bind(canvas));
}
else {
canvas.setBackgroundColor({source: 'http://fabricjs.com/assets/escheresque_ste.png'}, canvas.renderAll.bind(canvas));
}
});
canvas {
border: 1px solid #999;
}
button {
margin-top: 20px;
}
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<canvas id="c" width="400" height="400"></canvas>
<button id="toggle-repeat">Toggle repeat</button>
<button id="toggle-bgcolor">Toggle background</button>
这段代码还有一个问题 - 矩形模糊不清。
来自其他帖子的提示: 笔画宽度:0, 对象缓存:假 完成了,但它们仍然很模糊。 问题存在于模式和自由对象矩形中。
(有点模糊,但应该不是单色直线的情况)
// initialize fabric canvas and assign to global windows object for debug
var canvas = window._canvas = new fabric.Canvas('c', { enableRetinaScaling: false });
const newTransparent = function() {
const chessStatic = new fabric.StaticCanvas(null, { enableRetinaScaling: false });
chessStatic.setHeight(40);
chessStatic.setWidth(40);
chessStatic.renderAll();
chessStatic.setBackgroundColor('lightgrey');
const greyRect = new fabric.Rect({
width: 20,
height: 20,
left: 0,
top: 0,
fill: 'grey',
strokeWidth: 0,
objectCaching: false
});
//greyRect.set('fill', 'rgba(150, 150, 150, 1)')
const lightGreyRect = new fabric.Rect({
width: 20,
height: 20,
left: 20,
top: 20,
fill: 'grey',
strokeWidth: 0,
objectCaching: false
});
//lightGreyRect.set('fill', 'rgba(187, 187, 187, 1)')
chessStatic.add(greyRect);
chessStatic.add(lightGreyRect);
const greyRect2 = greyRect;
chessStatic.add(greyRect);
chessStatic.add(lightGreyRect);
chessStatic.calcOffset();
chessStatic.renderAll();
const transparentPattern = new fabric.Pattern({
source: function() {
return chessStatic.getElement();
},
repeat: 'repeat'
});
return transparentPattern;
}
canvas.setBackgroundColor(newTransparent(), canvas.renderAll.bind(canvas));
const GreyRect = new fabric.Rect({
width: 20,
height: 20,
left: 20,
top: 20,
fill: 'grey',
strokeWidth: 0,
objectCaching: false
});
canvas.add(GreyRect);
canvas.renderAll();
canvas {
border: 1px solid #999;
}
button {
margin-top: 20px;
}
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<canvas id="c" width="400" height="400"></canvas>