Fabric js : fabric js drawing mode and selection mode options - javascript

I'm using fabric js to develop a application to draw a line, Rectangle and circle in one canvas.And there is a other function to drag and drop a image on to canvas.
But when i added drag and drop function to the application other three function are not working.
I have found this article. But i was unable to integrate it with my one.
function initCanvas() {
$('.canvas-container').each(function (index) {
var canvasContainer = $(this)[0];
var canvasObject = $("canvas", this)[0];
var url = $(this).data('floorplan');
var canvas = window._canvas = new fabric.Canvas(canvasObject);
canvas.setHeight(400);
canvas.setWidth(500);
canvas.setBackgroundImage(url, canvas.renderAll.bind(canvas));
var imageOffsetX, imageOffsetY;
function handleDragStart(e) {
[].forEach.call(images, function (img) {
img.classList.remove('img_dragging');
});
this.classList.add('img_dragging');
var imageOffset = $(this).offset();
imageOffsetX = e.clientX - imageOffset.left;
imageOffsetY = e.clientY - imageOffset.top;
}
function handleDragOver(e) {
if (e.preventDefault) {
e.preventDefault();
}
e.dataTransfer.dropEffect = 'copy';
return false;
}
function handleDragEnter(e) {
this.classList.add('over');
}
function handleDragLeave(e) {
this.classList.remove('over');
}
function handleDrop(e) {
e = e || window.event;
if (e.preventDefault) {
e.preventDefault();
}
if (e.stopPropagation) {
e.stopPropagation();
}
var img = document.querySelector('.furniture img.img_dragging');
console.log('event: ', e);
var offset = $(canvasObject).offset();
var y = e.clientY - (offset.top + imageOffsetY);
var x = e.clientX - (offset.left + imageOffsetX);
var newImage = new fabric.Image(img, {
width: img.width,
height: img.height,
left: x,
top: y
});
canvas.add(newImage);
return false;
}
function handleDragEnd(e) {
[].forEach.call(images, function (img) {
img.classList.remove('img_dragging');
});
}
var images = document.querySelectorAll('.furniture img');
[].forEach.call(images, function (img) {
img.addEventListener('dragstart', handleDragStart, false);
img.addEventListener('dragend', handleDragEnd, false);
});
canvasContainer.addEventListener('dragenter', handleDragEnter, false);
canvasContainer.addEventListener('dragover', handleDragOver, false);
canvasContainer.addEventListener('dragleave', handleDragLeave, false);
canvasContainer.addEventListener('drop', handleDrop, false);
});
}
initCanvas();
var canvas = new fabric.Canvas('canvas1', { selection: false });
var line, isDown;
function myFun() {
removeEvents();
canvas.on('mouse:down', function (o) {
isDown = true;
var pointer = canvas.getPointer(o.e);
var points = [pointer.x, pointer.y, pointer.x, pointer.y];
line = new fabric.Line(points, {
strokeWidth: 5,
fill: '#07ff11a3',
stroke: '#07ff11a3',
originX: 'center',
originY: 'center'
});
canvas.add(line);
});
canvas.on('mouse:move', function (o) {
if (!isDown) return;
var pointer = canvas.getPointer(o.e);
line.set({ x2: pointer.x, y2: pointer.y });
canvas.renderAll();
});
canvas.on('mouse:up', function (o) {
isDown = false;
});
canvas.selection = false;
}
function drawrec() {
var line, isDown, origX, origY;
removeEvents();
canvas.on('mouse:down', function (o) {
isDown = true;
var pointer = canvas.getPointer(o.e);
origX = pointer.x;
origY = pointer.y;
var pointer = canvas.getPointer(o.e);
line = new fabric.Rect({
left: origX,
top: origY,
originX: 'left',
originY: 'top',
width: pointer.x - origX,
height: pointer.y - origY,
angle: 0,
fill: '#07ff11a3',
stroke: 'black',
transparentCorners: false
});
canvas.add(line);
});
canvas.on('mouse:move', function (o) {
if (!isDown) return;
var pointer = canvas.getPointer(o.e);
if (origX > pointer.x) {
line.set({ left: Math.abs(pointer.x) });
}
if (origY > pointer.y) {
line.set({ top: Math.abs(pointer.y) });
}
line.set({ width: Math.abs(origX - pointer.x) });
line.set({ height: Math.abs(origY - pointer.y) });
canvas.renderAll();
});
canvas.on('mouse:up', function (o) {
isDown = false;
});
}
function drawcle() {
var circle, isDown, origX, origY;
removeEvents();
canvas.on('mouse:down', function (o) {
isDown = true;
var pointer = canvas.getPointer(o.e);
origX = pointer.x;
origY = pointer.y;
circle = new fabric.Circle({
left: pointer.x,
top: pointer.y,
radius: 1,
strokeWidth: 1,
fill: '#07ff11a3',
stroke: 'black',
selectable: false,
originX: 'center', originY: 'center'
});
canvas.add(circle);
});
canvas.on('mouse:move', function (o) {
if (!isDown) return;
var pointer = canvas.getPointer(o.e);
circle.set({ radius: Math.abs(origX - pointer.x) });
canvas.renderAll();
});
canvas.on('mouse:up', function (o) {
isDown = false;
});
}
function removeEvents() {
canvas.off('mouse:down');
canvas.off('mouse:up');
canvas.off('mouse:move');
}
<div class="fullpage">
<div class="section">
<a class="thmb" href="#" onclick="myFun()" style="padding: 0px 10px;margin:5px;border: 2px solid;">line</a>
<a class="thmb" href="#" onclick="drawrec()" style="padding: 0px 10px;margin:5px;border: 2px solid;">Rectangle</a>
<a class="thmb" href="#" onclick="drawcle()" style="padding: 0px 10px;margin:5px;border: 2px solid;">Circle</a>
<div class="canvas-container">
<canvas id="canvas1" style="border: 1px solid;width: 500px;height: 500px"></canvas>
</div>
<div class="furniture" style="padding: 20px;border: 1px solid;width: 460px">
<h3>Drag the image to canvas</h3>
<img draggable="true" src="https://www.mve.com/media/Move_logo_-01.png" width="60">
</div>
</div>
</div>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.6/fabric.min.js'></script>

var canvas = window._canvas = new fabric.Canvas(canvasObject);
inside initCanvas() you are again creating fabric canvas, so remove it. And to enable free drawing you need to do canvas.isDrawingMode = true
function initCanvas() {
$('.canvas-container').each(function(index) {
var canvasContainer = $(this)[0];
var canvasObject = $("canvas", this)[0];
var imageOffsetX, imageOffsetY;
function handleDragStart(e) {
[].forEach.call(images, function(img) {
img.classList.remove('img_dragging');
});
this.classList.add('img_dragging');
var imageOffset = $(this).offset();
imageOffsetX = e.clientX - imageOffset.left;
imageOffsetY = e.clientY - imageOffset.top;
}
function handleDragOver(e) {
if (e.preventDefault) {
e.preventDefault();
}
e.dataTransfer.dropEffect = 'copy';
return false;
}
function handleDragEnter(e) {
this.classList.add('over');
}
function handleDragLeave(e) {
this.classList.remove('over');
}
function handleDrop(e) {
e = e || window.event;
if (e.preventDefault) {
e.preventDefault();
}
if (e.stopPropagation) {
e.stopPropagation();
}
var img = document.querySelector('.furniture img.img_dragging');
console.log('event: ', e);
var offset = $(canvasObject).offset();
var y = e.clientY - (offset.top + imageOffsetY);
var x = e.clientX - (offset.left + imageOffsetX);
var newImage = new fabric.Image(img, {
width: img.width,
height: img.height,
left: x,
top: y
});
canvas.add(newImage);
return false;
}
function handleDragEnd(e) {
[].forEach.call(images, function(img) {
img.classList.remove('img_dragging');
});
}
var images = document.querySelectorAll('.furniture img');
[].forEach.call(images, function(img) {
img.addEventListener('dragstart', handleDragStart, false);
img.addEventListener('dragend', handleDragEnd, false);
});
canvasContainer.addEventListener('dragenter', handleDragEnter, false);
canvasContainer.addEventListener('dragover', handleDragOver, false);
canvasContainer.addEventListener('dragleave', handleDragLeave, false);
canvasContainer.addEventListener('drop', handleDrop, false);
});
}
initCanvas();
var canvas = new fabric.Canvas('canvas1', {
selection: false
});
var line, isDown;
function drawLine() {
removeEvents();
changeObjectSelection(false);
canvas.on('mouse:down', function(o) {
isDown = true;
var pointer = canvas.getPointer(o.e);
var points = [pointer.x, pointer.y, pointer.x, pointer.y];
line = new fabric.Line(points, {
strokeWidth: 5,
fill: '#07ff11a3',
stroke: '#07ff11a3',
originX: 'center',
originY: 'center',
selectable: false
});
canvas.add(line);
});
canvas.on('mouse:move', function(o) {
if (!isDown) return;
var pointer = canvas.getPointer(o.e);
line.set({
x2: pointer.x,
y2: pointer.y
});
canvas.renderAll();
});
canvas.on('mouse:up', function(o) {
isDown = false;
line.setCoords();
});
}
function drawrec() {
var rect, isDown, origX, origY;
removeEvents();
changeObjectSelection(false);
canvas.on('mouse:down', function(o) {
isDown = true;
var pointer = canvas.getPointer(o.e);
origX = pointer.x;
origY = pointer.y;
var pointer = canvas.getPointer(o.e);
rect = new fabric.Rect({
left: origX,
top: origY,
originX: 'left',
originY: 'top',
width: pointer.x - origX,
height: pointer.y - origY,
angle: 0,
selectable:false,
fill: '#07ff11a3',
stroke: 'black',
transparentCorners: false
});
canvas.add(rect);
});
canvas.on('mouse:move', function(o) {
if (!isDown) return;
var pointer = canvas.getPointer(o.e);
if (origX > pointer.x) {
rect.set({
left: Math.abs(pointer.x)
});
}
if (origY > pointer.y) {
rect.set({
top: Math.abs(pointer.y)
});
}
rect.set({
width: Math.abs(origX - pointer.x)
});
rect.set({
height: Math.abs(origY - pointer.y)
});
canvas.renderAll();
});
canvas.on('mouse:up', function(o) {
isDown = false;
rect.setCoords();
});
}
function drawcle() {
var circle, isDown, origX, origY;
removeEvents();
changeObjectSelection(false);
canvas.on('mouse:down', function(o) {
isDown = true;
var pointer = canvas.getPointer(o.e);
origX = pointer.x;
origY = pointer.y;
circle = new fabric.Circle({
left: pointer.x,
top: pointer.y,
radius: 1,
strokeWidth: 1,
fill: '#07ff11a3',
stroke: 'black',
selectable: false,
originX: 'center',
originY: 'center'
});
canvas.add(circle);
});
canvas.on('mouse:move', function(o) {
if (!isDown) return;
var pointer = canvas.getPointer(o.e);
circle.set({
radius: Math.abs(origX - pointer.x)
});
canvas.renderAll();
});
canvas.on('mouse:up', function(o) {
isDown = false;
circle.setCoords();
});
}
function enableFreeDrawing(){
removeEvents();
canvas.isDrawingMode = true;
}
function enableSelection() {
removeEvents();
changeObjectSelection(true);
canvas.selection = true;
}
function changeObjectSelection(value) {
canvas.forEachObject(function (obj) {
obj.selectable = value;
});
canvas.renderAll();
}
function removeEvents() {
canvas.isDrawingMode = false;
canvas.selection = false;
canvas.off('mouse:down');
canvas.off('mouse:up');
canvas.off('mouse:move');
}
<div class="fullpage">
<div class="section">
<a class="thmb" href="#" onclick="drawLine()" style="padding: 0px 10px;margin:5px;border: 2px solid;">line</a>
<a class="thmb" href="#" onclick="drawrec()" style="padding: 0px 10px;margin:5px;border: 2px solid;">Rectangle</a>
<a class="thmb" href="#" onclick="drawcle()" style="padding: 0px 10px;margin:5px;border: 2px solid;">Circle</a>
<a class="thmb" href="#" onclick="enableFreeDrawing()" style="padding: 0px 10px;margin:5px;border: 2px solid;">Drawing</a>
<a class="thmb" href="#" onclick="enableSelection()" style="padding: 0px 10px;margin:5px;border: 2px solid;">Selection</a>
<div class="canvas-container">
<canvas id="canvas1" style="border: 1px solid;width: 500px;height: 500px"></canvas>
</div>
<div class="furniture" style="padding: 20px;border: 1px solid;width: 460px">
<h3>Drag the image to canvas</h3>
<img draggable="true" src="https://www.mve.com/media/Move_logo_-01.png" width="60">
</div>
</div>
</div>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.6/fabric.min.js'></script>

Perfect solution for this is here :
var canvas = this.__canvas = new fabric.Canvas('c', {
isDrawingMode: true
});
For more just visit this fabricjs page...
Fabric js : fabric js drawing mode and selection mode options

Related

Draw only inside drawn polygon

I would like to freedraw but only inside object i drawn before. Eg. i need to draw triangle using my code below, and then free draw lines but only inside this triangle, how to clip it so color wouldn't be outside of it?
var min = 99;
var max = 999999;
var polygonMode = true;
var pointArray = new Array();
var lineArray = new Array();
var activeLine;
var activeShape = false;
var canvas;
$(window).load(function() {
prototypefabric.initCanvas();
$('#create-polygon').click(function() {
prototypefabric.polygon.drawPolygon();
});
});
var prototypefabric = new function() {
this.initCanvas = function() {
canvas = window._canvas = new fabric.Canvas('c');
canvas.setWidth(800);
canvas.setHeight(800);
canvas.setBackgroundImage('https://i.imgur.com/tsnGll2.jpg', canvas.renderAll.bind(canvas));
//canvas.selection = false;
canvas.on('mouse:down', function(options) {
if (options.target && options.target.id == pointArray[0].id) {
prototypefabric.polygon.generatePolygon(pointArray);
}
if (polygonMode) {
prototypefabric.polygon.addPoint(options);
}
});
canvas.on('mouse:up', function(options) {
});
canvas.on('mouse:move', function(options) {
if (activeLine && activeLine.class == "line") {
var pointer = canvas.getPointer(options.e);
activeLine.set({
x2: pointer.x,
y2: pointer.y
});
var points = activeShape.get("points");
points[pointArray.length] = {
x: pointer.x,
y: pointer.y
};
activeShape.set({
points: points
});
canvas.renderAll();
}
canvas.renderAll();
});
};
};
prototypefabric.polygon = {
drawPolygon: function() {
polygonMode = true;
pointArray = new Array();
lineArray = new Array();
activeLine;
},
addPoint: function(options) {
var random = Math.floor(Math.random() * (max - min + 1)) + min;
var id = new Date().getTime() + random;
var circle = new fabric.Circle({
radius: 5,
fill: '#ffffff',
stroke: '#333333',
strokeWidth: 0.5,
left: (options.e.layerX / canvas.getZoom()),
top: (options.e.layerY / canvas.getZoom()),
selectable: false,
hasBorders: false,
hasControls: false,
originX: 'center',
originY: 'center',
id: id
});
if (pointArray.length == 0) {
circle.set({
fill: 'red'
})
}
var points = [(options.e.layerX / canvas.getZoom()), (options.e.layerY / canvas.getZoom()), (options.e.layerX / canvas.getZoom()), (options.e.layerY / canvas.getZoom())];
line = new fabric.Line(points, {
strokeWidth: 2,
fill: '#999999',
stroke: 'green',
class: 'line',
originX: 'center',
originY: 'center',
selectable: false,
hasBorders: false,
hasControls: false,
evented: false
});
if (activeShape) {
var pos = canvas.getPointer(options.e);
var points = activeShape.get("points");
points.push({
x: pos.x,
y: pos.y
});
var polygon = new fabric.Polygon(points, {
stroke: '#333333',
strokeWidth: 1,
fill: '#cccccc',
opacity: 0.3,
selectable: false,
hasBorders: false,
hasControls: false,
evented: false
});
canvas.remove(activeShape);
canvas.add(polygon);
activeShape = polygon;
canvas.renderAll();
console.log(points);
} else {
var polyPoint = [{
x: (options.e.layerX / canvas.getZoom()),
y: (options.e.layerY / canvas.getZoom())
}];
var polygon = new fabric.Polygon(polyPoint, {
stroke: '#333333',
strokeWidth: 1,
fill: '#cccccc',
opacity: 0.3,
selectable: false,
hasBorders: false,
hasControls: false,
evented: false
});
activeShape = polygon;
canvas.add(polygon);
}
activeLine = line;
pointArray.push(circle);
lineArray.push(line);
canvas.add(line);
canvas.add(circle);
canvas.selection = false;
},
generatePolygon: function(pointArray) {
var points = new Array();
$.each(pointArray, function(index, point) {
points.push({
x: point.left,
y: point.top,
});
canvas.remove(point);
});
$.each(lineArray, function(index, line) {
canvas.remove(line);
});
canvas.remove(activeShape).remove(activeLine);
var polygon = new fabric.Polygon(points, {
stroke: '#333333',
strokeWidth: 0.5,
fill: 'rgba(255, 255, 255, 0.5)',
opacity: 1,
hasBorders: false,
hasControls: false
});
canvas.add(polygon);
activeLine = null;
activeShape = null;
polygonMode = false;
canvas.selection = true;
}
};
// Removing active object on backspace
$(document).keydown(function(event) {
if (event.which == 8) {
if (canvas.getActiveObject()) {
canvas.getActiveObject().remove();
}
}
});
// end of Removing active object on backspace
// Freedrawing
function enableFreeDrawing() {
removeEvents();
canvas.isDrawingMode = true;
canvas.freeDrawingBrush.color = e.target.value;
}
document.getElementById('colorpicker').addEventListener('click', function(e) {
canvas.freeDrawingBrush.color = e.target.value;
canvas.freeDrawingBrush.width = 2;
});
function removeEvents() {
canvas.isDrawingMode = false;
canvas.selection = false;
canvas.off('mouse:down');
canvas.off('mouse:up');
canvas.off('mouse:move');
}
// Manipulate canvas
$(function() {
$('#zoomIn').click(function() {
canvas.setZoom(canvas.getZoom() * 1.1);
});
$('#zoomOut').click(function() {
canvas.setZoom(canvas.getZoom() / 1.1);
});
$('#goRight').click(function() {
var units = 10;
var delta = new fabric.Point(units, 0);
canvas.relativePan(delta);
});
$('#goLeft').click(function() {
var units = 10;
var delta = new fabric.Point(-units, 0);
canvas.relativePan(delta);
});
$('#goUp').click(function() {
var units = 10;
var delta = new fabric.Point(0, -units);
canvas.relativePan(delta);
});
$('#goDown').click(function() {
var units = 10;
var delta = new fabric.Point(0, units);
canvas.relativePan(delta);
});
$('#zoomIn').click(function() {
canvas.setZoom(canvas.getZoom() * 1.1);
});
$('#zoomOut').click(function() {
canvas.setZoom(canvas.getZoom() / 1.1);
});
});
// End of manipulate canvas
canvas {
border: 1px solid black;
border-radius: 27px;
}
* {
font-family: "Roboto", sans-serif;
font-weight: 100;
}
body {
overflow: hidden;
}
/*#c {*/
/* border: 1px solid black;*/
/* background: url(assets/geoportal.JPG);*/
/* background-size: cover;*/
/* border-radius: 27px;*/
/*}*/
.canvas-container {
margin: 0 auto;
margin-top: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<canvas id="c" width="800" height="800"></canvas>
<ul class="action-list">
<li>
<button class="thmb" href="#" id="create-polygon">Narysuj polygon</button>
</li>
<li>
<div id="colorpicker">
<button class="thmb" href="#" onclick="enableFreeDrawing()" value="#FFFF00">Yellow</button>
<button class="thmb" href="#" onclick="enableFreeDrawing()" value="#00FF00">Green</button>
<button class="thmb" href="#" onclick="enableFreeDrawing()" value="#F00000">Red</button>
<button class="thmb" href="#" onclick="removeEvents()">Stop Drawing</button>
</div>
</li>
<li>
<button id="goLeft" class="thmb"><</button>
<button id="goRight" class="thmb">></button>
<button id="goUp" class="thmb">Up</button>
<button id="goDown" class="thmb">Down</button>
<button id="zoomIn" class="thmb">+</button>
<button id="zoomOut" class="thmb">-</button>
</li>
</ul>
</div>
Link: https://codepen.io/Basstalion/pen/gOpKOjP

How to identify fabric js image objects inserted to canvas?

In here there are two images with two different id's.Is there a way to identify the image which are inserted(drag and drop) images to the canvas.(I want to get the id's images that are inserted to the canvas).
I'm trying to sent image details(x,y, width,height) to the database with unique image id. Is there a way to this in fabric js.
function initCanvas() {
$('.canvas-container').each(function(index) {
var canvasContainer = $(this)[0];
var canvasObject = $("canvas", this)[0];
var imageOffsetX, imageOffsetY;
function handleDragStart(e) {
[].forEach.call(images, function(img) {
img.classList.remove('img_dragging');
});
this.classList.add('img_dragging');
var imageOffset = $(this).offset();
imageOffsetX = e.clientX - imageOffset.left;
imageOffsetY = e.clientY - imageOffset.top;
}
function handleDragOver(e) {
if (e.preventDefault) {
e.preventDefault();
}
e.dataTransfer.dropEffect = 'copy';
return false;
}
function handleDragEnter(e) {
this.classList.add('over');
}
function handleDragLeave(e) {
this.classList.remove('over');
}
function handleDrop(e) {
e = e || window.event;
if (e.preventDefault) {
e.preventDefault();
}
if (e.stopPropagation) {
e.stopPropagation();
}
var img = document.querySelector('.furniture img.img_dragging');
console.log('event: ', e);
var offset = $(canvasObject).offset();
var y = e.clientY - (offset.top + imageOffsetY);
var x = e.clientX - (offset.left + imageOffsetX);
var newImage = new fabric.Image(img, {
width: img.width,
height: img.height,
left: x,
top: y
});
canvas.add(newImage);
return false;
}
function handleDragEnd(e) {
[].forEach.call(images, function(img) {
img.classList.remove('img_dragging');
});
}
var images = document.querySelectorAll('.furniture img');
[].forEach.call(images, function(img) {
img.addEventListener('dragstart', handleDragStart, false);
img.addEventListener('dragend', handleDragEnd, false);
});
canvasContainer.addEventListener('dragenter', handleDragEnter, false);
canvasContainer.addEventListener('dragover', handleDragOver, false);
canvasContainer.addEventListener('dragleave', handleDragLeave, false);
canvasContainer.addEventListener('drop', handleDrop, false);
});
}
initCanvas();
var canvas = new fabric.Canvas('canvas1', {
selection: false
});
<div class="fullpage">
<div class="section">
<div class="canvas-container">
<canvas id="canvas1" style="border: 1px solid;width: 500px;height: 500px"></canvas>
</div>
<div class="furniture" style="padding: 20px;border: 1px solid;width: 460px">
<h3>Drag the image to canvas</h3>
<img id="pic1" draggable="true" src="https://www.mve.com/media/Move_logo_-01.png" width="60">
<img id="pic2" draggable="true" src="https://young.scot/media/8787/second-chances-logo-802x644.png" width="60">
</div>
</div>
</div>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.6/fabric.min.js'></script>
You can get the id from dragged element, and add as a proerty of image object.
function initCanvas() {
$('.canvas-container').each(function(index) {
var canvasContainer = $(this)[0];
var canvasObject = $("canvas", this)[0];
var imageOffsetX, imageOffsetY;
function handleDragStart(e) {
[].forEach.call(images, function(img) {
img.classList.remove('img_dragging');
});
this.classList.add('img_dragging');
var imageOffset = $(this).offset();
imageOffsetX = e.clientX - imageOffset.left;
imageOffsetY = e.clientY - imageOffset.top;
}
function handleDragOver(e) {
if (e.preventDefault) {
e.preventDefault();
}
e.dataTransfer.dropEffect = 'copy';
return false;
}
function handleDragEnter(e) {
this.classList.add('over');
}
function handleDragLeave(e) {
this.classList.remove('over');
}
function handleDrop(e) {
e = e || window.event;
if (e.preventDefault) {
e.preventDefault();
}
if (e.stopPropagation) {
e.stopPropagation();
}
var img = document.querySelector('.furniture img.img_dragging');
//console.log('event: ', e);
var offset = $(canvasObject).offset();
var y = e.clientY - (offset.top + imageOffsetY);
var x = e.clientX - (offset.left + imageOffsetX);
var newImage = new fabric.Image(img, {
width: img.width,
height: img.height,
left: x,
top: y,
id: img.id
});
canvas.add(newImage);
console.log(newImage.id)
return false;
}
function handleDragEnd(e) {
[].forEach.call(images, function(img) {
img.classList.remove('img_dragging');
});
}
var images = document.querySelectorAll('.furniture img');
[].forEach.call(images, function(img) {
img.addEventListener('dragstart', handleDragStart, false);
img.addEventListener('dragend', handleDragEnd, false);
});
canvasContainer.addEventListener('dragenter', handleDragEnter, false);
canvasContainer.addEventListener('dragover', handleDragOver, false);
canvasContainer.addEventListener('dragleave', handleDragLeave, false);
canvasContainer.addEventListener('drop', handleDrop, false);
});
}
initCanvas();
var canvas = new fabric.Canvas('canvas1', {
selection: false
});
<div class="fullpage">
<div class="section">
<div class="canvas-container">
<canvas id="canvas1" style="border: 1px solid;width: 500px;height: 500px"></canvas>
</div>
<div class="furniture" style="padding: 20px;border: 1px solid;width: 460px">
<h3>Drag the image to canvas</h3>
<img id="pic1" draggable="true" src="https://www.mve.com/media/Move_logo_-01.png" width="60">
<img id="pic2" draggable="true" src="https://young.scot/media/8787/second-chances-logo-802x644.png" width="60">
</div>
</div>
</div>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.6/fabric.min.js'></script>
Use canvas.on('object:modified') function or get active object and perform your action on it
function initCanvas() {
$('.canvas-container').each(function(index) {
var canvasContainer = $(this)[0];
var canvasObject = $("canvas", this)[0];
var imageOffsetX, imageOffsetY;
function handleDragStart(e) {
[].forEach.call(images, function(img) {
img.classList.remove('img_dragging');
});
this.classList.add('img_dragging');
var imageOffset = $(this).offset();
imageOffsetX = e.clientX - imageOffset.left;
imageOffsetY = e.clientY - imageOffset.top;
}
function handleDragOver(e) {
if (e.preventDefault) {
e.preventDefault();
}
e.dataTransfer.dropEffect = 'copy';
return false;
}
function handleDragEnter(e) {
this.classList.add('over');
}
function handleDragLeave(e) {
this.classList.remove('over');
}
function handleDrop(e) {
e = e || window.event;
if (e.preventDefault) {
e.preventDefault();
}
if (e.stopPropagation) {
e.stopPropagation();
}
var img = document.querySelector('.furniture img.img_dragging');
console.log('event: ', e);
var offset = $(canvasObject).offset();
var y = e.clientY - (offset.top + imageOffsetY);
var x = e.clientX - (offset.left + imageOffsetX);
var newImage = new fabric.Image(img, {
width: img.width,
height: img.height,
left: x,
top: y,
id:'SomeID'
//Object id for identify
});
canvas.add(newImage);
return false;
}
function handleDragEnd(e) {
[].forEach.call(images, function(img) {
img.classList.remove('img_dragging');
});
}
var images = document.querySelectorAll('.furniture img');
[].forEach.call(images, function(img) {
img.addEventListener('dragstart', handleDragStart, false);
img.addEventListener('dragend', handleDragEnd, false);
});
canvasContainer.addEventListener('dragenter', handleDragEnter, false);
canvasContainer.addEventListener('dragover', handleDragOver, false);
canvasContainer.addEventListener('dragleave', handleDragLeave, false);
canvasContainer.addEventListener('drop', handleDrop, false);
});
}
initCanvas();
var canvas = new fabric.Canvas('canvas1', {
selection: false
});
canvas.on('object:modified', function (e) {
var activeobject = e.target;
//Do as need
console.log(activeobject);
alert(activeobject.get('id'));
});

fabric.js free drawing after shape error

I have a problem with fabric.js. I can draw a square in the canvas, but if I then switch to free drawing the line starts in the middle of the shape.
have a look here:
jsfiddle
var functouse = "pencil";
var pensize = 5;
var pencolour = "#000000";
var fillcolour = "#ffffff";
var canvas = new fabric.Canvas('sketchpad', {
isDrawingMode: true
});
fabric.Object.prototype.transparentCorners = false;
canvas.selection = false;
canvas.observe('mouse:down', function(e) {
mousedown(e);
});
canvas.observe('mouse:move', function(e) {
mousemove(e);
});
canvas.observe('mouse:up', function(e) {
mouseup(e);
});
canvas.observe('object:selected ', function(e) {
console.log('selected something');
});
//fabric.Object.prototype.transparentCorners = false;
var line;
var isDown;
var initX = 0;
var initY = 0;
$(".top_butt").click(function() {
functouse = $(this).attr('data-id');
});
function mousedown(o) {
isDown = true;
var pointer = canvas.getPointer(o.e);
if (functouse == "pencil") {
canvas.isDrawingMode = true;
canvas.freeDrawingColor = pencolour;
canvas.freeDrawingLineWidth = pensize;
canvas.freeDrawingMode = 'Pencil';
} else if (functouse == "square") {
initX = pointer.x;
initY = pointer.y;
canvas.isDrawingMode = false;
var square = new fabric.Rect({
width: 0.1,
height: 0.1,
left: initX,
top: initY,
fill: fillcolour,
stroke: pencolour,
strokeWidth: pensize,
selectable: false,
hasBorders: false,
hasControls: false
});
canvas.add(square);
canvas.setActiveObject(square);
}
}
function mousemove(o) {
if (!isDown) return;
var pointer = canvas.getPointer(o.e);
if (functouse == "square") {
var ww = Math.abs(pointer.x - initX);
var hh = Math.abs(pointer.y - initY);
if (!ww || !hh) {
return false;
}
var square = canvas.getActiveObject();
square.set('width', ww).set('height', hh);
canvas.renderAll();
} else if (functouse == "pencil") {
if (initX == -1 || initY == -1) {
initX = pointer.x;
initY = pointer.y;
}
}
}
function mouseup(o) {
isDown = false;
if (functouse == "square") {
initX = -1;
initY = -1;
var square = canvas.getActiveObject();
square.setCoords();
//canvas.add(square);
canvas.renderAll();
//canvas.pointer
$('canvas').css('cursor', 'nw-resize');
} else if (functouse == "pencil") {
canvas.forEachObject(function(o) {
o.selectable = false,
o.lockMovementX = true,
o.lockMovementY = true,
o.lockScaling = true
});
}
}
p span{
cursor: pointer;
}
canvas{
border: solid thin #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.1.0/fabric.all.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<p><span class="top_butt" data-id='square'>Square</span> | <span class="top_butt" data-id='pencil'>Pencil</span></p>
<canvas id="sketchpad" width="400" height="600"></canvas>
<p>
Uno y dos
</p>
draw a square, then a line and you will see what I mean.
extra point for: I don't understand why it starts drawing with a very thin line and only when the line is finished it adopts the line size I set.
and on a third bonus point: is it possible to draw the squares from the top left corners, instead of the center.
You need to remove the event handler using off() , and I have updated your fabric version . Have a look.
DEMO
var functouse = "pencil";
var pensize = 5;
var pencolour = "#000000";
var fillcolour = "#ffffff";
var canvas = new fabric.Canvas('sketchpad', {
isDrawingMode: true
});
fabric.Object.prototype.transparentCorners = false;
canvas.selection = false;
canvas.on('object:selected ', function(e) {
console.log('selected something');
});
//fabric.Object.prototype.transparentCorners = false;
var line;
var isDown;
var square;
var initX = 0;
var initY = 0;
$(".top_butt").click(function() {
functouse = $(this).attr('data-id');
removeEvents();
if (functouse == "pencil") {
setObjectSelectable(false);
canvas.isDrawingMode = true;
canvas.freeDrawingColor = pencolour;
canvas.freeDrawingLineWidth = pensize;
canvas.freeDrawingMode = 'Pencil';
} else if (functouse == "square") {
canvas.isDrawingMode = false;
setObjectSelectable(false);
addEvent();
} else {
canvas.isDrawingMode = false;
setObjectSelectable(true);
}
});
function setObjectSelectable(val) {
canvas.forEachObject(function(obj) {
obj.selectable = val;
})
canvas.renderAll();
}
function removeEvents() {
canvas.off('mouse:down');
canvas.off('mouse:move');
canvas.off('mouse:up');
}
function addEvent() {
canvas.on('mouse:down', mousedown);
canvas.on('mouse:move', mousemove);
canvas.on('mouse:up', mouseup);
}
function mousedown(o) {
isDown = true;
var pointer = canvas.getPointer(o.e);
initX = pointer.x;
initY = pointer.y;
canvas.isDrawingMode = false;
square = new fabric.Rect({
width: 0.1,
height: 0.1,
left: initX,
top: initY,
fill: fillcolour,
stroke: pencolour,
strokeWidth: pensize,
selectable: false,
hasBorders: false,
hasControls: false
});
canvas.add(square);
canvas.setActiveObject(square);
}
function mousemove(o) {
if (!isDown) return;
var pointer = canvas.getPointer(o.e);
var ww = Math.abs(pointer.x - initX);
var hh = Math.abs(pointer.y - initY);
if (!ww || !hh) {
return false;
}
square.set('width', ww).set('height', hh);
canvas.renderAll();
}
function mouseup(o) {
isDown = false;
initX = -1;
initY = -1;
square.setCoords();
square = null;
//canvas.add(square);
canvas.renderAll();
}
p span{
cursor: pointer;
}
canvas{
border: solid thin #ccc;
}
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p><span class="top_butt" data-id='square'>Square</span> | <span class="top_butt" data-id='pencil'>Pencil</span>| <span class="top_butt" data-id='selection'>Selection</span></p>
<canvas id="sketchpad" width="400" height="600"></canvas>
<p>
Uno y dos
</p>

How to restrict freedrawing a circle in Fabricjs?

I am working on Fabricjs where I have to allow the user to freedraw some area on the image.
Now the fiddle contains code that is able to draw throughout the canvas.
I want it to be only restricted to draw within the image.
Here's the code :
`
var canvas = new fabric.Canvas("canvas2");
var circle, isDown, origX, origY;
fabric.Image.fromURL('http://www.beatnyama.com/wp-content/uploads/2015/05/assets.jpg', function(img){
img.evented=false;
img.selectable=false;
canvas.add(img);
minX = img.oCoords.tl.x;
maxX = img.oCoords.br.x;
minY = img.oCoords.tl.y;
maxY = img.oCoords.br.y;
canvas.sendToBack(img);
canvas.on('mouse:down', function(o){
isDown = true;
var pointer = canvas.getPointer(o.e);
origX = pointer.x;
origY = pointer.y;
circle = new fabric.Circle({
left: origX,
top: origY,
originX: 'left',
originY: 'top',
radius: pointer.x-origX,
angle: 0,
fill: '',
stroke:'red',
strokeWidth:3,
});
canvas.add(circle);
});
canvas.on('mouse:move', function(o){
if (!isDown) return;
var pointer = canvas.getPointer(o.e);
var radius = Math.max(Math.abs(origY - pointer.y),Math.abs(origX - pointer.x))/2;
if (radius > circle.strokeWidth) {
radius -= circle.strokeWidth/2;
}
circle.set({ radius: radius});
if(origX>pointer.x){
circle.set({originX: 'right' });
} else {
circle.set({originX: 'left' });
}
if(origY>pointer.y){
circle.set({originY: 'bottom' });
} else {
circle.set({originY: 'top' });
}
canvas.renderAll();
});
canvas.on('mouse:up', function(o){
isDown = false;
});
});
`
Adapating the logic of your previous questions, one to each other, you should try this:
var canvas = new fabric.Canvas('canvas');
var minX, minY, maxX, maxY;
var circle, isDown, origX, origY, lastGoodRadius;
fabric.Image.fromURL('http://www.beatnyama.com/wp-content/uploads/2015/05/assets.jpg', function(img){
img.evented=false;
img.selectable=false;
canvas.add(img);
minX = img.oCoords.tl.x;
maxX = img.oCoords.br.x;
minY = img.oCoords.tl.y;
maxY = img.oCoords.br.y;
canvas.sendToBack(img);
});
canvas.on('mouse:down', function(o){
isDown = true;
var pointer = canvas.getPointer(o.e);
origX = pointer.x;
origY = pointer.y;
circle = new fabric.Circle({
left: origX,
top: origY,
originX: 'left',
originY: 'top',
radius: pointer.x-origX,
angle: 0,
fill: '',
stroke:'red',
strokeWidth:3,
});
lastGoodRadius = 0;
canvas.add(circle);
});
canvas.on('mouse:move', function(o){
if (!isDown) return;
var restore = false;
var pointer = canvas.getPointer(o.e);
var radius = Math.max(Math.abs(origY - pointer.y),Math.abs(origX - pointer.x))/2;
if (radius > circle.strokeWidth) {
radius -= circle.strokeWidth/2;
}
var diam = radius * 2;
if(origX>pointer.x){
circle.set({originX: 'right' });
if (origX - diam < minX) {
restore = (origX-minX)/2;
}
} else {
circle.set({originX: 'left' });
if (origX + diam > maxX) {
restore = (maxX-origX)/2;
}
}
if(origY>pointer.y){
circle.set({originY: 'bottom' });
if (origY - diam < minY) {
restore = (origY-minY)/2;
}
} else {
circle.set({originY: 'top' });
if (origY + diam > maxY) {
restore = (maxY-origY)/2;
}
}
if(!restore) {
circle.set({ radius: radius});
} else {
circle.set({ radius: restore});
}
canvas.renderAll();
});
<script src="http://fabricjs.com/lib/fabric.js"></script>
<canvas id='canvas' width="550" height="550" style="border:#000 1px solid;"></canvas>

Fabric.js - Free draw a rectangle

I have the following which doesn't work correctly:
var canvas = new fabric.Canvas('canvas');
canvas.observe('mouse:down', function(e) { mousedown(e); });
canvas.observe('mouse:move', function(e) { mousemove(e); });
canvas.observe('mouse:up', function(e) { mouseup(e); });
var started = false;
var x = 0;
var y = 0;
/* Mousedown */
function mousedown(e) {
var mouse = canvas.getPointer(e.memo.e);
started = true;
x = mouse.x;
y = mouse.y;
var square = new fabric.Rect({
width: 1,
height: 1,
left: mouse.x,
top: mouse.y,
fill: '#000'
});
canvas.add(square);
canvas.renderAll();
canvas.setActiveObject(square);
}
/* Mousemove */
function mousemove(e) {
if(!started) {
return false;
}
var mouse = canvas.getPointer(e.memo.e);
var x = Math.min(mouse.x, x),
y = Math.min(mouse.y, y),
w = Math.abs(mouse.x - x),
h = Math.abs(mouse.y - y);
if (!w || !h) {
return false;
}
var square = canvas.getActiveObject();
square.set('top', y).set('left', x).set('width', w).set('height', h);
canvas.renderAll();
}
/* Mouseup */
function mouseup(e) {
if(started) {
started = false;
}
}
The above logic is from a simple rectangle drawing system I used without fabric.js so I know it works, just not with fabric.js.
It seems the maths is off or I'm setting the incorrect params with the width/height/x/y values, as when you draw the rectangle does not follow the cursor correctly.
Any help is much appreciated, thanks in advance :)
I have written an example for you. Please follow the link below:
http://jsfiddle.net/a7mad24/aPLq5/
var canvas = new fabric.Canvas('canvas', { selection: false });
var rect, isDown, origX, origY;
canvas.on('mouse:down', function(o){
isDown = true;
var pointer = canvas.getPointer(o.e);
origX = pointer.x;
origY = pointer.y;
var pointer = canvas.getPointer(o.e);
rect = new fabric.Rect({
left: origX,
top: origY,
originX: 'left',
originY: 'top',
width: pointer.x-origX,
height: pointer.y-origY,
angle: 0,
fill: 'rgba(255,0,0,0.5)',
transparentCorners: false
});
canvas.add(rect);
});
canvas.on('mouse:move', function(o){
if (!isDown) return;
var pointer = canvas.getPointer(o.e);
if(origX>pointer.x){
rect.set({ left: Math.abs(pointer.x) });
}
if(origY>pointer.y){
rect.set({ top: Math.abs(pointer.y) });
}
rect.set({ width: Math.abs(origX - pointer.x) });
rect.set({ height: Math.abs(origY - pointer.y) });
canvas.renderAll();
});
canvas.on('mouse:up', function(o){
isDown = false;
});
Looks like Fabric.js calculates everything from the origin. So, 'Top' and 'Left' are a bit misleading. Check the following link: Canvas Coordinates Have Offset. Also, I've changed a bit of your code:
var canvas = new fabric.Canvas('canvas');
canvas.observe('mouse:down', function(e) { mousedown(e); });
canvas.observe('mouse:move', function(e) { mousemove(e); });
canvas.observe('mouse:up', function(e) { mouseup(e); });
var started = false;
var x = 0;
var y = 0;
/* Mousedown */
function mousedown(e) {
var mouse = canvas.getPointer(e.memo.e);
started = true;
x = mouse.x;
y = mouse.y;
var square = new fabric.Rect({
width: 0,
height: 0,
left: x,
top: y,
fill: '#000'
});
canvas.add(square);
canvas.renderAll();
canvas.setActiveObject(square);
}
/* Mousemove */
function mousemove(e) {
if(!started) {
return false;
}
var mouse = canvas.getPointer(e.memo.e);
var w = Math.abs(mouse.x - x),
h = Math.abs(mouse.y - y);
if (!w || !h) {
return false;
}
var square = canvas.getActiveObject();
square.set('width', w).set('height', h);
canvas.renderAll();
}
/* Mouseup */
function mouseup(e) {
if(started) {
started = false;
}
var square = canvas.getActiveObject();
canvas.add(square);
canvas.renderAll();
}
Here is the detail blog with jsfiddle - https://blog.thirdrocktechkno.com/drawing-a-square-or-rectangle-over-html5-canvas-using-fabricjs-f48beeedb4d3
var Rectangle = (function () {
function Rectangle(canvas) {
var inst=this;
this.canvas = canvas;
this.className= 'Rectangle';
this.isDrawing = false;
this.bindEvents();
}
Rectangle.prototype.bindEvents = function() {
var inst = this;
inst.canvas.on('mouse:down', function(o) {
inst.onMouseDown(o);
});
inst.canvas.on('mouse:move', function(o) {
inst.onMouseMove(o);
});
inst.canvas.on('mouse:up', function(o) {
inst.onMouseUp(o);
});
inst.canvas.on('object:moving', function(o) {
inst.disable();
})
}
Rectangle.prototype.onMouseUp = function (o) {
var inst = this;
inst.disable();
};
Rectangle.prototype.onMouseMove = function (o) {
var inst = this;
if(!inst.isEnable()){ return; }
var pointer = inst.canvas.getPointer(o.e);
var activeObj = inst.canvas.getActiveObject();
activeObj.stroke= 'red',
activeObj.strokeWidth= 5;
activeObj.fill = 'transparent';
if(origX > pointer.x){
activeObj.set({ left: Math.abs(pointer.x) });
}
if(origY > pointer.y){
activeObj.set({ top: Math.abs(pointer.y) });
}
activeObj.set({ width: Math.abs(origX - pointer.x) });
activeObj.set({ height: Math.abs(origY - pointer.y) });
activeObj.setCoords();
inst.canvas.renderAll();
};
Rectangle.prototype.onMouseDown = function (o) {
var inst = this;
inst.enable();
var pointer = inst.canvas.getPointer(o.e);
origX = pointer.x;
origY = pointer.y;
var rect = new fabric.Rect({
left: origX,
top: origY,
originX: 'left',
originY: 'top',
width: pointer.x-origX,
height: pointer.y-origY,
angle: 0,
transparentCorners: false,
hasBorders: false,
hasControls: false
});
inst.canvas.add(rect).setActiveObject(rect);
};
Rectangle.prototype.isEnable = function(){
return this.isDrawing;
}
Rectangle.prototype.enable = function(){
this.isDrawing = true;
}
Rectangle.prototype.disable = function(){
this.isDrawing = false;
}
return Rectangle;
}());
var canvas = new fabric.Canvas('canvas');
var rect = new Rectangle(canvas);
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.17/fabric.min.js"></script>
Please draw rectangle here
<div id="canvasContainer">
<canvas id="canvas" width="400" height="400" style="border: solid 1px"></canvas>
</div>
The answer above seems to be deprecated. I changed some things on the code below to fix that. And on the mousedown function I add the if to detect the active object to avoid creating a new rectangle when the user's move a selected object.
var canvas = new fabric.Canvas('canvas');
canvas.on('mouse:down', function(options) {
if(canvas.getActiveObject()){
return false;
}
started = true;
x = options.e.clientX;
y = options.e.clientY;
var square = new fabric.Rect({
width: 0,
height: 0,
left: x,
top: y,
fill: '#000'
});
canvas.add(square);
canvas.setActiveObject(square);
});
canvas.on('mouse:move', function(options) {
if(!started) {
return false;
}
var w = Math.abs(options.e.clientX - x),
h = Math.abs(options.e.clientY - y);
if (!w || !h) {
return false;
}
var square = canvas.getActiveObject();
square.set('width', w).set('height', h);
});
canvas.on('mouse:up', function(options) {
if(started) {
started = false;
}
var square = canvas.getActiveObject();
canvas.add(square);
});
Slight modification on the mouse up event to allow the object to be selectable and moveable.
Note: adding the object to canvas again on the mouse:up even will add it twice to the canvase and it is the wrong thing to do.
canvas.on('mouse:up', function(o){
isDown = false;
var square = canvas.getActiveObject();
square.setCoords(); //allows object to be selectable and moveable
});
you can use this simple code
canvas.add(new fabric.Rect({ left: 110, top: 110, fill: '#f0f', width: 50, height: 50 }));

Categories