I'm trying to bind an event to a background image:
var imgInstance = fabric.Image.fromURL(path, function(oImg) {
oImg.on("selected", function() {
alert();
});
canvas.setBackgroundImage(oImg, canvas.renderAll.bind(canvas), {
top: 0,
left: 0
});
oImg.on("selected", function() {
alert();
});
});
I can get it work. I'm trying to bind mouse events to handle drag, so i can move the image when it's bigger than the canvas, like background-cover css property.
Thoughts?
Thanks guys!
SOLUTION:
var DragStart = false;
canvas.on('mouse:down', function(options) {
if (!options.target) {
DragStart = true;
}else {
DragStart = false;
}
});
canvas.on('mouse:move', function(options) {
if (DragStart) {
var bounds = getBounds(options.e); // validate boundaries between image and canvas
canvas.backgroundImage.top = bounds.y;
canvas.backgroundImage.left = bounds.x;
canvas.renderAll();
}
});
It doesn't seem like you can add events to the background image... but the canvas does emit events and if you click the canvas and no target is set then they must be clicking the background. Background image are not forced to take up the whole background but I'm not sure reasons to not make it take up the whole background.
You do get the mouse event passed in though so if the background image does not take up the whole background you could do that math and figure out where they clicked.
window.canvas = new fabric.Canvas('c', { selection: false, preserveObjectStacking:true });
fabric.Image.fromURL('http://fabricjs.com/assets/pug_small.jpg', function(o) {
canvas.setBackgroundImage(o, canvas.renderAll.bind(canvas), {
top: 0,
left: 0
});
});
canvas.on('mouse:down', function(options) {
if (!options.target) {
console.log('target is null')
}
});
canvas.add(new fabric.Rect({
left: 100,
top: 100,
width: 50,
height: 50,
fill: '#faa',
originX: 'left',
originY: 'top',
centeredRotation: true
}));
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.4/fabric.min.js"></script>
<canvas id="c" width="600" height="600"></canvas>
Related
I have a Konva stage defined as the following code describes, and the stage is not responding to click, even though it is responding to drag and is automatically dragged.
Is there a way to debug the click problem??
The stage has a layer over it with some objects which don't fully cover it.
this.stage = new Konva.Stage({
container: divName,
width: this.width,
height: this.height,
draggable: true
});
this.stage.on("click mousedown", function() {
console.log("click");
});
this.stage.on("dragstart", function() {
console.log("dragstart");
});
this.nodeLayer = new Konva.Layer();
this.stage.add(this.nodeLayer);
The snippet below is built from your code. Click seems to work in this simple example. Could you post more of your code ?
var divName = 'container1';
var width = 300;
var height = 200;
this.stage = new Konva.Stage({
container: divName,
width: width,
height: height,
draggable: true
});
this.stage.on("click mousedown", function() {
console.log("click - stage");
});
this.stage.on("dragstart", function() {
console.log("dragstart - stage");
});
this.nodeLayer = new Konva.Layer();
this.nodeLayer.on("click mousedown", function() {
console.log("click - layer");
});
this.nodeLayer.on("dragstart", function() {
console.log("dragstart - layer");
});
this.stage.add(this.nodeLayer);
var layer = nodeLayer;
$('#addshape').on('click', function(){
var rect = new Konva.Rect({ x: 10, y: 10, width: 50, height: 50, fill: 'cyan'});
layer.add(rect)
layer.draw();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/konva/2.5.1/konva.min.js"></script>
<p>Click the canvas first - note the 'click - stage' event fires but no 'click - layer'. Now add a shape and click it - note the layer click occurs before the stage click.</p>
<button style='position: absolute; z-index: 10;' id='addshape'>Add shape</button>
<div id='container1' style="width: 300px, height: 200px; background-color: silver;"></div>
<div id='img'></div>
I am using this function to define my fabricJS canvas background image:
$scope.bgImage = function () {
const {
ipcRenderer
} = require('electron')
ipcRenderer.send('openFile', () => {
})
ipcRenderer.once('fileData', (event, filepath) => {
fabric.Image.fromURL(filepath, function (image) {
var hCent = canvas.getHeight / 2;
var wCent = canvas.getWidth / 2;
canvas.setBackgroundColor({
source: filepath,
top: hCent,
left: wCent,
originX: 'center',
originY: 'middle',
repeat: 'no-repeat',
scaleX: 10,
scaleY: 10
}, canvas.renderAll.bind(canvas));
})
})
};
All the parameters shoulkd be change on the fly with some html inputs. Setting the repeat is working fine and i can change it dynamically.
But I am simply not able to change the scale of my background image. Using the above function I would expect that my background image would be:
would be not repeated (ok. is working)
positioned in the middle/center of my canvas (it is not)
would be scaled by a factor of 10 (it is not)
I am making again a newbish mistake? Or ist this realted to some changes in image handling in FabricJS v.2
canvas.setBackgroundImage() Use this function to add Image as a background.
To get Height/Width of canvas use canvas.getHeight()/canvas.getWidth(),these are functions. Or else you can use the properties > canvas.height/canvas.width respectively.
DEMO
// initialize fabric canvas and assign to global windows object for debug
var canvas = window._canvas = new fabric.Canvas('c');
var hCent = canvas.getHeight() / 2;
var wCent = canvas.getWidth() / 2;
canvas.setBackgroundImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {
originX: 'center',
originY: 'center',
left: wCent,
top: hCent,
scaleX: 1,
scaleY: 1
});
fabric.util.addListener(document.getElementById('toggle-scaleX'), 'click', function () {
if (!canvas.backgroundImage) return;
canvas.backgroundImage.scaleX = canvas.backgroundImage.scaleX < 1 ? 1 : fabric.util.toFixed(Math.random(), 2);
canvas.renderAll();
});
fabric.util.addListener(document.getElementById('toggle-scaleY'), 'click', function () {
if (!canvas.backgroundImage) return;
canvas.backgroundImage.scaleY = canvas.backgroundImage.scaleY < 1 ? 1 : fabric.util.toFixed(Math.random(), 2);
canvas.renderAll();
});
canvas {
border: 1px solid #999;
}
button {
margin-top: 20px;
}
<script src="https://rawgithub.com/kangax/fabric.js/master/dist/fabric.js"></script>
<canvas id="c" width="600" height="600"></canvas>
<button id="toggle-scaleX">Toggle scaleX</button>
<button id="toggle-scaleY">Toggle scaleY</button>
I am designing business card designer application with fabric.js canvas in this application i need a system for managing objects z-index and for that i created two buttons for sending selected object in back and front its working fine but in all my designs i have a background image on which all text and objects placed when i send a object back it send back under that BG image how can stop that i mean i want that BG image to always in last position
preview of application
Code i am using now to send object in front and back
var selectedObject;
canvas.on('object:selected', function(event) {
selectedObject = event.target;
});
var sendSelectedObjectBack = function() {
canvas.sendToBack(selectedObject);
}
var sendSelectedObjectToFront = function() {
canvas.bringToFront(selectedObject);
}
var canvas = new fabric.Canvas('c');
fabric.Image.fromURL('https://images2.alphacoders.com/147/147320.png', function(img) {
var oImg = img.set({
left: 0,
top: 0,
angle: 00,
width: canvas.width,
height: canvas.height
});
canvas.setBackgroundImage(oImg).renderAll();
});
canvas.add(new fabric.Circle({
left: 50,
top: 50,
radius: 50,
stroke: 'red',
fill: 'yellow'
}))
canvas.add(new fabric.Rect({
left: 50,
top: 50,
height: 150,
width:150,
stroke: 'red',
fill: 'green'
}))
var sendSelectedObjectBack = function() {
selectedObject = canvas.getActiveObject();
if(selectedObject)
canvas.sendToBack(selectedObject);
canvas.deactivateAll();
canvas.renderAll();
}
var sendSelectedObjectToFront = function() {
selectedObject = canvas.getActiveObject();
if(selectedObject)
canvas.bringToFront(selectedObject);
canvas.deactivateAll();
canvas.renderAll();
}
canvas{
border:2px dotted blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.16/fabric.min.js"></script>
<button onclick='sendSelectedObjectBack();'>Send back</button>
<button onclick='sendSelectedObjectToFront();'>Bring Front</button>
<canvas id='c' width='400' height='400'></canvas>
Set your background using canvas.setBackgroundImage(obj), then it will stay ion back all the time.
First Option
Use canvas.setBackgroundImage(obj)
Second Option
If you don't want to set backgroundImage
You can do it after you send back your selected object, you need to again send your BG object to back.
Try this.
var sendSelectedObjectBack = function() {
canvas.sendToBack(selectedObject); //this will send selected object to back.
// Now loop through all your obj
canvas.forEachObject(function (obj) {
// get your background with id or any other property
if (obj && obj.id.indexOf('BG_') > -1) {
canvas.bringToBack(obj, true); // this will send your BG always at back
}
});
}
I am having issues getting drag, drop and delete to work on a FabricJS using JQuery.
Select an object and click delete is working with no issues.
Here's a demo of my code Fiddle
I can get drag, drop and delete to work outside of FabricJS (Just dragging unrelated elements to delete) but I'm having difficulty combing the two.
Maybe I need to incorporate the delete button inside the canvas in order for the 'drop' to work? When I try this the #delete element disappears.
JS
var canvas = new fabric.Canvas('canvas');
$("#delete").click(function() {
deleteObjects();
});
//Test objects on the canvas
//Circle
var circle = new fabric.Circle({
left: 200,
top: 150,
radius: 30,
fill: "#ff0072"
});
circle.hasRotatingPoint = true;
canvas.add(circle);
// adding triangle
var triangle = new fabric.Triangle({
left: 130,
top: 150,
strokeWidth: 1,
width: 70,
height: 60,
fill: '#00b4ff',
selectable: true,
originX: 'center'
});
triangle.hasRotatingPoint = true;
canvas.add(triangle);
//Select all objects
function deleteObjects() {
var activeObject = canvas.getActiveObject(),
activeGroup = canvas.getActiveGroup();
if (activeObject) {
canvas.remove(activeObject);
}
}
//Drag and drop delete
$(function() {
$('#delete').droppable({
drop: function(event, ui) {
deleteObjects();
}
});
});
HTML
<section class="canvas__container">
<canvas id="canvas" width="400" height="400"></canvas>
<div id="delete">♻</div>
</section>
(I didn't paste my CSS as that's not particularly relevant)
This should get you close:
var bin;
var selectedObject;
fabric.Image.fromURL('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADUAAAA1CAIAAABuhDQnAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAPPSURBVGhDzZd9U+IwEIfv+3+2Gxln9PAEcYRBURQVkVeFe9rdC2laIFsK+Pzh2Cab/ZF9Sfpr9bMpr+/r6+v5+fn+/v5vyuXl5e8U/uGx2Wwy9Pr6yjQ1KIVZ32w2e3x8xL2oiYHJmGCoS1gw6MPB7e2t+iwF5laVUfqIEcGq1WrqZw9YhKXig75bHzlUiTIfFmRZdbCVHfrIG13yALC4utnMRn2EYM9siwEX22NdrA8b1y8ODY62SCzWd4Sd88GdOs5RoO+gObeJTbkY6qOs1OLoFFZ0Rh95UHkriQfX+UTM6Ot2uzr3RCBApfxnrY+T54SbJyAgOADX+krX7NnZGTeAm5ub8/NzfbUHQS2rPlTruJFOp7NYLGQR+P7+5vHz8/Pl5eX6+lonGfG3UPWV6ykPDw/L5VJWyIPQcjHxe43qM93nBEz8nSvk4+OD6KtBNKys9qKPqtYRC3d3d/P5XFYRptMpBei/ZGXyUg0suEaT6OOarq/toHI8HrPIZDLhWn91dTUajdKVE4g+tz2dasH16kSfte1Rp29vb71e7+LiQt78SeFRtPqQ7ExmVGZG4hphoo8fra+jQRx7A5QqJeySjJoNgs5jueQW8zL6Wq0WqSb2wnA41LG0gbm6YRqKUW+9rSFJVkj0mYxJsqDFs4s0Gh1OISlJcGJdr9cRR3ytvQZJsniiT9/FQeMVSwe+86240WiQjuDKxXozEiuzPupULB00OR3Lgmg/DTA09UKxMsfX10fuE8cguA6izHGnU9PJ5IaO7SITX1N9uPjijx1CXKFXCpDR4MfEO8rUh6n+3a5QFqQUGSbvaYrtdnswGBBThqghioO6Tr0kUCUyM4ZMfzH1Z3IoSEGksFVPT0/6nELcqQz2TB4R7X5JDJn+bD3fAilsJx0xyDYftDKqxnFkzjfs9XUcHPmYiD0QTQ5ZttDtVkC/31fLaNz6iT6wHkFsuRgKoiB/+ML7+7uprYBLPlB91vspLjFxv1J6L3/JRU5kV0C0RlPaCQX3U9bVQSOcEySftBguCpSwvN8H//xUfVDuLl45yFBBKWt9qP4J35d+5cFaH1gvqpXj2p4jow/tJ9zC/OZBRh9Yb0EV4nqyT6gPyn0L74nfU3wK9MGRazmoWZ9ifeSB9YuhNDjKp52jWB9gc4RdxMUWcbBRn3DQXNyUcz479AFlVXnTYcHCas2zWx8QAjpnJSpZhKW2x9QnSp/AAbhnRmLun/0xGPQJOCBvTPdFJmNiVSaY9TmIETlEsHDP55brR/zDIy8ZYkJ8KAspr+84/Gx9q9U/+FfCZwDz5ogAAAAASUVORK5CYII=', function(img) {
img.set({
left: 174,
top: 329,
selectable: false
});
bin = img;
canvas.add(img, circle, triangle);
});
canvas.on('object:selected', function(evn) {
selectedObject = evn.target;
})
canvas.on('mouse:up', function(evn) {
var x = evn.e.offsetX;
var y = evn.e.offsetY;
if (x > bin.left && x < (bin.left + bin.width) &&
y > bin.top && y < (bin.top + bin.height)) {
canvas.remove(selectedObject);
}
});
Here's your JSFiddle updated, https://jsfiddle.net/rekrah/jgruwse0/.
Let me know if you have any further questions.
I am using Fabric.js and jQuery UI for a drag and drop scene creator. When I drag and drop an image into the canvas the image becomes blurry/pixelated and appears to be zoomed in. I've been searching Stackoverflow and Google forever and can't find any solutions. I'd appreciate any suggestions on how to fix it!
Here is my code:
// HTML
<canvas id="scene"></canvas>
// Draggable setup
$('.scene-item').draggable({
helper: 'clone',
appendTo: 'body',
containment: 'window',
scroll: false,
zIndex: 9999
});
// Drop Setup
var canvas = new fabric.Canvas('scene');
canvas.setDimensions({
width: '800px',
height: '500px'
}, {
cssOnly: true
});
document.getElementById("scene").fabric = canvas;
canvas.on({
'object:moving': function(e) {
e.target.opacity = 0.5;
},
"object:modified": function(e) {
e.target.opacity = 1;
}
});
$('#scene').droppable({
drop: function(e, ui) {
if ($(e.target).attr('id') === 'scene') {
var pointer = canvas.getPointer();
fabric.Image.fromURL(ui.draggable[0].currentSrc, function (img) {
console.log(img);
img.set({
left: pointer.x - 20,
top: pointer.y - 20,
width: 52,
height: 52,
scale: 0.1
});
//canvas.clear();
canvas.add(img);
canvas.renderAll();
});
}
}
});
This is what the images look like on and off the canvas:
Here is a demo jsfiddle.net/dmLr6cgx/1
I figured out the problem. I had to replace:
canvas.setDimensions({
width: '800px',
height: '500px'
}, {
cssOnly: true
});
with
canvas.setHeight(500);
canvas.setWidth(800);
canvas.renderAll();
And now it works fine.