if I have multiple pairs of objects, say, (A1, A2), (B1, B2), (C1, C2), what I want is that when object A1/B1/C1 is moving, object A2/B2/C2 is moving as well. And when I multi-select objects, say, A1 and B1, and move them around, A2 and B2 don't move at all because the single object event doesn't fire. How can I fix it?
Thanks!
Here's a pen to demonstrate: https://codepen.io/taineleau/pen/PdxRKX
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>Fabric JS playground</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.0.0-rc.3/fabric.js'></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
<style>
canvas {
position:relative;
display:inline-block;
width:100%;
}
</style>
</head>
<body>
<canvas id="fabriccanvas" width="1000px" height="1000px"></canvas>
<script>
function bind(obj1, obj2) {
obj1.on("moving", function () {
obj2.left = this.left + 50;
obj2.top = this.top;
});
}
var canvas = new fabric.Canvas("fabriccanvas");
var A1 = new fabric.Rect({
width: 200, height: 100, left: 0, top: 50, angle: 30,
fill: 'rgb(255,0,0)'
});
var A2 = new fabric.Rect({
width: 200, height: 100, left: 50, top: 50, angle: 30,
fill: 'rgba(255,0,0,0.5)',
selectable: false,
});
var B1 = new fabric.Rect({
width: 100, height: 100, left: 35, top: 25, angle: -10,
fill: 'rgb(0,200,0)'
});
var B2 = new fabric.Rect({
width: 100, height: 100, left: 85, top: 25, angle: -10,
fill: 'rgba(0,200,0,0.5)',
selectable: false,
});
bind(A1, A2);
bind(B1, B2);
canvas.add(A1, A2, B1, B2);
</script>
</body>
</html>
if I multi-select A1 and B1 and moving them, A2 and B2 don't move at all
You can use on.("object:moving")
, check if it matches an object you want to bind to, or if it contains one, and then update appropriately. If it contains an object you want to bind to, you have to offset it by the position and size of the container itself.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Fabric JS playground</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.0.0-rc.3/fabric.js'></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
<style>
canvas {
position: relative;
display: inline-block;
width: 100%;
}
</style>
</head>
<body>
<canvas id="fabriccanvas" width="1000px" height="1000px"></canvas>
<script>
function bind(obj1, obj2) {
canvas.on('object:moving', function(event) {
if (obj1 == event.target) {
obj2.left = obj1.left + 50;
obj2.top = obj1.top;
} else if ("_objects" in event.target) {
if (event.target["_objects"].includes(obj1)) {
obj2.left = obj1.left + event.target.left + event.target.width / 2 + 50;
obj2.top = obj1.top + event.target.top + event.target.height / 2;
}
}
});
}
var canvas = new fabric.Canvas("fabriccanvas");
var A1 = new fabric.Rect({
width: 200,
height: 100,
left: 0,
top: 50,
angle: 30,
fill: 'rgb(255,0,0)'
});
var A2 = new fabric.Rect({
width: 200,
height: 100,
left: 50,
top: 50,
angle: 30,
fill: 'rgba(255,0,0,0.5)',
selectable: false,
});
var B1 = new fabric.Rect({
width: 100,
height: 100,
left: 35,
top: 25,
angle: -10,
fill: 'rgb(0,200,0)'
});
var B2 = new fabric.Rect({
width: 100,
height: 100,
left: 85,
top: 25,
angle: -10,
fill: 'rgba(0,200,0,0.5)',
selectable: false,
});
bind(A1, A2);
bind(B1, B2);
canvas.add(A1, A2, B1, B2);
</script>
</body>
</html>