我有一个计数器,可以计算画布上的对象总数,但是我想将其隔离以按对象颜色计数。 canvas.getObjects().length;
可以按颜色获取对象吗?
var canvas = new fabric.Canvas('c');
var iconTriangle = new fabric.Triangle({
width: 62.5,
height: 50,
originX: 'center',
originY: 'center',
fill: "green"
});
icon = iconTriangle;
canvas.add(icon);
//disable icon & hide when hovering over existing icon
canvas.on('mouse:over', function(obj) {
iconTriangle.set('opacity', 0);
icon = null;
canvas.renderAll()
});
//restor icon & unhide
canvas.on('mouse:out', function(obj) {
iconTriangle.set('opacity', 1);
icon = iconTriangle;
canvas.renderAll()
});
canvas.on('mouse:move', function(obj) {
icon.top = obj.e.y - 80;
icon.left = obj.e.x - 10;
canvas.renderAll()
});
canvas.on('mouse:out', function(obj) {
icon.top = -100;
icon.left = -100;
canvas.renderAll()
});
//place icon and count each by type
canvas.on('mouse:up', function(obj) {
var count = canvas.getObjects().length;
document.getElementById("greentally").value = count;
document.getElementById("yellowtally").value = count;
document.getElementById("redtally").value = count;
canvas.add(icon.clone());
canvas.renderAll();
});
//set icon type
function iconSet() {
if (document.getElementById("green").checked == true) {
iconTriangle.setFill("green");
canvas.renderAll();
canvas.trigger('object:modified', {
target: iconTriangle
});
} else if (document.getElementById("yellow").checked == true) {
iconTriangle.setFill("yellow");
canvas.renderAll();
canvas.trigger('object:modified', {
target: iconTriangle
});
} else if (document.getElementById("red").checked == true) {
iconTriangle.setFill("red");
canvas.renderAll();
canvas.trigger('object:modified', {
target: iconTriangle
});
}
}
canvas {
border: 1px solid #ccc;
}
.tally {
position: fixed;
width: 50px;
left: 255px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.3/fabric.js"></script>
<input name="iconType" type="radio" id="green" onclick="iconSet()" />Green  
<input class="tally" disabled id="greentally" type="text" value="0">
<br>
<input name="iconType" type="radio" id="yellow" onclick="iconSet()" /> Yellow  
<input class="tally" disabled id="yellowtally" type="text" value="0">
<br>
<input name="iconType" type="radio" id="red" onclick="iconSet()" /> red  
<input class="tally" disabled id="redtally" type="text" value="0">
<canvas id="c" width="300" height="300"></canvas>
最佳答案
对具有特定颜色(或任何其他属性)的对象进行计数很容易,因为您可以通过canvas.getObjects()
在画布上获得所有对象的数组-然后,您可以通过filter()
过滤出要过滤的对象。为此,我在代码段中引入了getObjectsBy(fn)
辅助函数。
也就是说,您的代码还有其他几个值得解决的问题:
首先,将icon
复制为iconTriangle
的引用看起来很整洁,但实际上是毫无意义且容易出错的,例如您必须编写单独的逻辑来隐藏副本,并且必须在实际需要时注意它是否为null
。这就是获得这些Cannot set property 'top' of null
的原因。在我的代码段中,我正在通过类似于工厂的addIcon()
创建一个新图标,该图标与clone()
一样易于使用,但也易于维护。mouse:up
事件不仅在单击画布时触发,而且在单击对象时触发,因此最终每次移动一些东西时都会创建不必要的图标。在我的代码段中,我正在使用mouse:up
侦听器中的早期返回值来解决此问题。iconSet()
似乎是引入助手功能以使其更简洁的好地方。同样,将颜色存储在单独的变量中有助于将图标创建与iconTriangle
分离。
var canvas = new fabric.Canvas('c');
var currentColor;
var defaultIcon = {
width: 62.5,
height: 50,
originX: 'center',
originY: 'center'
};
var iconTriangle = new fabric.Triangle(defaultIcon);
setColor('green');
canvas.add(iconTriangle);
//disable icon & hide when hovering over existing icon
canvas.on('mouse:over', function(obj) {
iconTriangle.set('opacity', 0);
canvas.renderAll();
});
//restor icon & unhide
canvas.on('mouse:out', function(e) {
// if 'target' is null, means mouse is out of canvas
if (e.target) {
iconTriangle.set('opacity', 1);
} else {
iconTriangle.left = -100;
iconTriangle.top = -100;
}
canvas.renderAll();
});
//move pointer icon
canvas.on('mouse:move', function(obj) {
iconTriangle.top = obj.e.y - 80;
iconTriangle.left = obj.e.x - 10;
canvas.renderAll();
});
//count each by type and place new icon
canvas.on('mouse:up', function(e) {
if (e.target) {
return
}
var red = getObjectsBy((obj) => obj.fill === 'red').length;
var green = getObjectsBy((obj) => obj.fill === 'green').length;
var yellow = getObjectsBy((obj) => obj.fill === 'yellow').length;
document.getElementById("greentally").value = green;
document.getElementById("yellowtally").value = yellow;
document.getElementById("redtally").value = red;
addIcon(e.e.x - 10, e.e.y - 80, currentColor);
});
//set icon type
function iconSet() {
if (document.getElementById("green").checked == true) {
setColor('green');
} else if (document.getElementById("yellow").checked == true) {
setColor('yellow');
} else if (document.getElementById("red").checked == true) {
setColor('red');
}
}
function setColor (color) {
currentColor = color;
iconTriangle.setFill(currentColor);
canvas.renderAll();
}
function getObjectsBy (fn) {
return canvas.getObjects().filter(fn)
}
function addIcon (x, y, color) {
var icon = new fabric.Triangle(defaultIcon);
icon.setFill(color);
icon.left = x;
icon.top = y;
canvas.add(icon);
canvas.renderAll();
}
canvas {
border: 1px solid #ccc;
}
.tally {
position: fixed;
width: 50px;
left: 255px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.3/fabric.js"></script>
<input checked name="iconType" type="radio" id="green" onclick="iconSet()" />Green  
<input class="tally" disabled id="greentally" type="text" value="0">
<br>
<input name="iconType" type="radio" id="yellow" onclick="iconSet()" /> Yellow  
<input class="tally" disabled id="yellowtally" type="text" value="0">
<br>
<input name="iconType" type="radio" id="red" onclick="iconSet()" /> red  
<input class="tally" disabled id="redtally" type="text" value="0">
<canvas id="c" width="300" height="300"></canvas>
关于javascript - FabricJS按颜色隔离对象计数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57509915/