gpt4 book ai didi

javascript - Fabricjs 按颜色隔离对象计数

转载 作者:行者123 更新时间:2023-11-30 13:54:50 26 4
gpt4 key购买 nike

我有一个计数器来计算 Canvas 上的对象总数,但我想将它隔离以按对象颜色计数。 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 &emsp;
<input class="tally" disabled id="greentally" type="text" value="0">
<br>
<input name="iconType" type="radio" id="yellow" onclick="iconSet()" /> Yellow &emsp;
<input class="tally" disabled id="yellowtally" type="text" value="0">
<br>
<input name="iconType" type="radio" id="red" onclick="iconSet()" /> red &emsp;
<input class="tally" disabled id="redtally" type="text" value="0">
<canvas id="c" width="300" height="300"></canvas>

最佳答案

计算具有特定颜色(或任何其他属性)的对象很容易,因为您可以通过 canvas.getObjects() 获取 Canvas 上所有对象的数组 - 然后您只需过滤那些您想要的对象在通过 filter() 之后。为此,我在我的代码片段中引入了一个 getObjectsBy(fn) 辅助函数。

也就是说,您的代码还有其他几个值得解决的问题:

  • 使 icon 成为对 iconTriangle 的复制引用,起初看起来很整洁,但实际上毫无意义且容易出错,例如您必须编写单独的逻辑来隐藏副本,并且在实际需要时必须注意它是否为 null。这就是您收到 Cannot set property 'top' of null 的原因。在我的代码片段中,我通过类似工厂的 addIcon() 创建了一个新图标,它与 clone() 一样易于使用,但也更容易维护。
  • mouse:up 事件不仅会在您单击 Canvas 时触发,还会在您单击对象时触发,因此每次移动时都会创建不必要的图标。在我的代码片段中,我在 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 &emsp;
<input class="tally" disabled id="greentally" type="text" value="0">
<br>
<input name="iconType" type="radio" id="yellow" onclick="iconSet()" /> Yellow &emsp;
<input class="tally" disabled id="yellowtally" type="text" value="0">
<br>
<input name="iconType" type="radio" id="red" onclick="iconSet()" /> red &emsp;
<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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com