Draw rectangle between two mouse clicks on canvas using fabric js - html

I am beginner to fabric js. I want to draw a rectangle over an canvas having background image. First time when user mouse down on the canvas get that co-ordinates then user mouse up then again when he mouse down then rectangle should be drawn between these points these points are the upper left point and the bottom right point. I am very much confused how to do that.
I am sharing my code which I have used to draw canvas and set background image and it also draws and line.
<html lang="en" >
<head>
<meta charset="utf-8" />
<title>HTML5 canvas - Image color picker | Script Tutorials</title>
<link href="index.css" rel="stylesheet" type="text/css" />
<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>
</head>
<body>
<div class="container">
<div class="column1">
<canvas id="panel" width="700" height="350"></canvas>
</div>
<div style="clear:both;"></div>
</div>
</body>
<script>
(function() {
var canvas = new fabric.Canvas('panel', { selection: false });
var line, isDown;
canvas.on('mouse:down', function(o){
isDown = true;
var pointer = canvas.getPointer(o.e);
var points = [ pointer.x, pointer.y, pointer.x, pointer.y ];
console.log(points);
line = new fabric.Line(points, {
strokeWidth: 5,
fill: 'red',
stroke: 'red',
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;
});
fabric.Image.fromURL('fedex.jpg', function (img) {
canvas.add(img.set({
width: 700,
height:350,
left: 350,
top: 175,
selectable: false,
}));
});
})();
</script>

Modify your code like this:
(function() {
var canvas = new fabric.Canvas('panel');
var line, isDown, startPosition={}, rect,drawingMode=true;
canvas.on('mouse:down', function(event){
if (!drawingMode) return;
isDown = true;
console.log(event.e.clientX,event.e.clientY);
startPosition.x=event.e.clientX;
startPosition.y=event.e.clientY;
console.log(startPosition);
rect=new fabric.Rect({
left:event.e.clientX,
top:event.e.clientY,
width:0,
height:0,
stroke:'red',
strokeWidth:3,
fill:''
});
canvas.add(rect);
});
canvas.on('mouse:move', function(event){
if (!isDown || !drawingMode) return;
rect.setWidth(Math.abs( event.e.clientX-startPosition.x ));
rect.setHeight(Math.abs( event.e.clientY -startPosition.y ));
canvas.renderAll();
});
canvas.on('mouse:up', function(){
isDown = false;
canvas.add(rect);
});
canvas.on('object:selected', function(){
drawingMode = false;
});
canvas.on('object:selected', function(){
drawingMode = false;
});
canvas.on('selection:cleared', function(){
drawingMode = true;
});
})();
This will draw rectangle with mouse.
See in Fiddle

Related

How to obtain ID of Konva Label from Konva's 'dblclick' event

I'm looking for a way to obtain ID (123 in the code below) of a Konva Label ("Hello World!" in the code below) from Konva's 'dblclick' event.
I could obtain ID (321 in the code below) of a Konva Image (Konva's LOGO "K" in the code below) from both of Konva's 'dblclick' and 'dragmove' events.
Also I could obtain the ID (123 in the code below) of the Konva Label ("Hello World!") from 'dragmove' event; however I couldn't obtain the ID (123 in the code below) of the Konva Label ("Hello World!") from Konva's 'dblclick' event.
My code:
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/konva#5.0.2/konva.min.js"></script>
<meta charset="utf-8" />
</head>
<body>
<span id="container"></span>
</body>
<script>
//Konva Stage
var stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight,
});
//Konva Layer
var layer = new Konva.Layer();
stage.add(layer);
//Konva Image
var imageObj = new Image();
imageObj.src = 'https://raw.githubusercontent.com/konvajs/konvajs.github.io/master/apple-touch-icon-180x180.png';
imageObj.addEventListener('load', function() {
var kImage = new Konva.Image({
x: window.innerWidth*2.5/10,
y: window.innerHeight*1/10,
image: imageObj,
id: 321,
draggable: true,
});
layer.add(kImage);
layer.draw();
});
//Konva Label
WordLabel = new Konva.Label({
x: window.innerWidth*3/10,
y: window.innerHeight*4/10,
opacity: 0.75,
draggable: true,
fill: 'green',
id: 123,
});
//Konva Tag
WordLabel.add(
new Konva.Tag({
fill: 'green',
})
);
//Konva Text
WordLabel.add(
new Konva.Text({
text: 'Hello World!',
fontFamily: 'Calibri',
fontSize: 18,
padding: 5,
fill: 'white',
strokeWidth: 0,
})
);
layer.add(WordLabel);
layer.draw();
//Konva dragstart event
stage.on('dragstart', function(e) {
console.log('ID (dragstart) = ' + parseInt(e.target.id()));
});
//Konva dblclick event
stage.on('dblclick dbltap', function (e) {
console.log('ID (dblclick) = ' +parseInt(e.target.id()));
});
</script>
</html>
If you look at the e.target object you can see that it is the text node rather than the label node that received the click.
Use e.target.findAncestors (see shape API) to get and iterate the shape hierarchy looking for an ancestor shape with the ID attribute you seek.
Working snippet below.
//Konva Stage
var stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight,
});
//Konva Layer
var layer = new Konva.Layer();
stage.add(layer);
//Konva Image
var imageObj = new Image();
imageObj.src = 'https://raw.githubusercontent.com/konvajs/konvajs.github.io/master/apple-touch-icon-180x180.png';
imageObj.addEventListener('load', function() {
var kImage = new Konva.Image({
x: window.innerWidth*2.5/10,
y: window.innerHeight*1/10,
image: imageObj,
id: 321,
draggable: true,
});
layer.add(kImage);
layer.draw();
});
//Konva Label
WordLabel = new Konva.Label({
x: 10,
y: 20,
opacity: 0.75,
draggable: true,
fill: 'green',
id: 123,
});
//Konva Tag
WordLabel.add(
new Konva.Tag({
fill: 'green'
})
);
//Konva Text
WordLabel.add(
new Konva.Text({
text: 'Hello World!',
fontFamily: 'Calibri',
fontSize: 18,
padding: 5,
fill: 'white',
strokeWidth: 0
})
);
layer.add(WordLabel);
layer.draw();
//Konva dragstart event
stage.on('dragstart', function(e) {
console.log('ID (dragstart) = ' + parseInt(e.target.id()));
});
//Konva dblclick event
stage.on('dblclick dbltap', function (e) {
// Looking for a specif attr on a parent shape. In this
// case we know the parent is a Label so search for ancestors of that type
var nodes = e.target.findAncestors('Label', true);
if (nodes.length > 0) {
for (var i = 0; i < nodes.length; i++){
var id = nodes[i].getAttr("id")
console.log('shape ' + i + ' ID (dblclick)', id )
}
}
else {
console.log('ID (dblclick) = ' + parseInt(e.target.id()));
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/konva#5.0.2/konva.min.js"></script>
<meta charset="utf-8" />
</head>
<body>
<span id="container"></span>
</body>
<script>
</script>
</html>

KineticJS and HTML

I have a situation, the images moving left to right and viceversa, after a certain bound area the images have to hide(invisible) from the stage and when they return back it should be visible. My tween is like this :
var tween = new Kinetic.Tween({
node: puzzle,
duration: 22,
x: puzzle.getX()+700,
easing: Kinetic.Easings.Linear,
onFinish : function(){
this.reverse();
}
});
anyone please help me. Thanks in advance.
Use clipping regions
You can put your puzzle object on a group and set a clipping region on that group.
When your puzzle moves out of the group's clipping region it will not be displayed.
Demo: http://jsfiddle.net/m1erickson/hzTM7/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Prototype</title>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.7.2.min.js"></script>
<style>
body{padding:20px;}
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:350px;
height:350px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 350,
height: 350
});
var layer = new Kinetic.Layer();
stage.add(layer);
var group=new Kinetic.Group({
clip:{x:50,y:50,width:100,height:100},
});
layer.add(group);
var bk=new Kinetic.Rect({
x:50,
y:50,
width:100,
height:100,
fill:"blue",
opacity:0.10,
});
group.add(bk);
var circle1 = new Kinetic.Circle({
x:70,
y:70,
radius: 15,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
});
group.add(circle1);
layer.draw();
var tween = new Kinetic.Tween({
node: circle1,
duration: 2,
x: circle1.getX()+120,
easing: Kinetic.Easings.Linear,
onFinish : function(){
this.reverse();
}
});
$("#myButton").click(function(){ tween.play(); });
}); // end $(function(){});
</script>
</head>
<body>
<button id="myButton">Tween</button>
<div id="container"></div>
</body>
</html>

How to insert an image in canvas and after that insert text in this canvas?

I'm trying to insert an image in a canvas and after that I want to insert an input text in the same canvas, but I can't do it. How can I fix this problem?
Now, I want that the user insert a draggable text in the actual canvas. The people say that using Fabric.js is easy, but I can't get it working:
canvas = document.getElementById("canvasThumbResult");
var context = canvas.getContext("2d");
var img = document.getElementById("target");
context.drawImage(img, getX, getY, getWidth, getHeight, 0, 0, 238.11023622,332.598425197);
Here is how to add user-specified text on an image and allow the text to be dragged
This solution uses a canvas library called KineticJS and jQuery to simplify the task.
Here’s how it works:
Create the Kinetic Stage (this activates the HTML canvas)
Create a new image object in JavaScript (this loads your image into an object)
Create a new Kinetic Image object and put your new image in the Kinetic Image object
When the user types text in the input and hits the “Add” button…
Create a new Kinetic Label object using the user’s text
To make the new text label draggable, just set draggable:true when creating the object
Here’s the code that makes it all work…
Create the Kinetic Stage (this activates the HTML canvas)
var stage = new Kinetic.Stage({
container: 'container',
width: 300,
height: 300
});
var layer = new Kinetic.Layer();
stage.add(layer);
Create a new image object in JavaScript (this loads your image into an object)
var image = new Image();
image.onload = function(){
// Your image is fully loaded, so…
// Create your kinetic image object here
layer.add(image1);
layer.draw();
}
image.src="koolaidman.png";
Create a new Kinetic Image object and put your new image in the Kinetic Image object
var image = new Image();
image.onload = function(){
var image1 = new Kinetic.Image({
x: 0,
y: 0,
width: 300,
height: 300,
image: image,
});
layer.add(image1);
layer.draw();
}
image.src = "koolaidman.png";
When the user types text in the input and hits the “Add” button…
<input id="newtext" type="text" value="Hello!">
<button id="addbutton">Add this text</button>
$("#addbutton").click(function(){
// Create your new kinetic text label here
});
Create a new Kinetic Label object using the user’s text
$("#addbutton").click(function(){
// Simple label
var label = new Kinetic.Label({
x: 20,
y: 20,
draggable:true
});
label.add(new Kinetic.Tag({
fill: 'green'
}));
label.add(new Kinetic.Text({
text: $("#newtext").val(),
fontFamily: 'Verdana',
fontSize: 18,
padding: 10,
fill: 'white'
}));
layer.add(label);
layer.draw();
});
To make the new text label draggable, just set draggable:true when creating the object
// Snipped from the kinetic label creation above
var label = new Kinetic.Label({
x: 20,
y: 20,
// Set draggable:true to make the kinetic label draggable
draggable:true
});
You can download the Kinetic library and learn more with examples in HTML5 Canvas KineticJS Label Tutorial. You can download the jQuery library and learn more with examples here at the jQuery home page. jQuery is a great library for eliminating cross-browser inconsistencies.
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/pQYz9/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Prototype</title>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.6.0.min.js"></script>
<style>
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:300px;
height:300px;
}
</style>
<script>
$(function(){
$("#addbutton").click(function(){
// Simple label
var label = new Kinetic.Label({
x: 20,
y: 20,
draggable:true
});
label.add(new Kinetic.Tag({
fill: 'green'
}));
label.add(new Kinetic.Text({
text: $("#newtext").val(),
fontFamily: 'Verdana',
fontSize: 18,
padding: 10,
fill: 'white'
}));
layer.add(label);
layer.draw();
});
}); // End $(function(){});
</script>
</head>
<body>
<input id="newtext" type="text" value="Hello!">
<button id="addbutton">Add this text</button>
<div id="container"></div>
</body>
</html>
Using Scrawl.js:
(Disclaimer: I am the developer of this library)
<!DOCTYPE html>
<html>
<head>
<title>Scrawl.js</title>
<style>
body {margin: 1em;}
img {position: fixed; visibility: hidden;}
</style>
</head>
<body>
<ol>
<li>Display an image in a canvas</li>
<li>Add text to canvas</li>
<li>Drag text around canvas</li>
<li>Change text via an input box</li>
</ol>
<div>Change text by typing in this box: <input type="text" id="changetext" value="Hello world" /></div>
<img src="img/penguin02.jpg" id="penguin" class="demo903" />
<canvas id="mycanvas" width="400" height="400"></canvas>
<script src="js/scrawl.js"></script>
<script>
window.onload = function(){
//import the image and create a sprite to display it
scrawl.getImagesByClass('demo903');
scrawl.newPicture({
source: 'penguin',
width: 400,
height: 400,
});
//construct a sprite to display the text
//and a group for collision detection stuff
var texts = scrawl.newGroup({
name: 'texts',
});
var displayText = scrawl.newPhrase({
font: '24pt bold Arial, sans-serif',
textAlign: 'center',
textBaseline: 'middle',
startX: 200,
startY: 200,
fillStyle: 'yellow',
strokeStyle: 'black',
shadowColor: 'black',
shadowBlur: 8,
method: 'fillDraw',
text: 'Hello world',
group: 'texts',
});
//add event listeners to handle text drag-and-drop
var here, myText;
var getText = function(){
myText = texts.getSpriteAt(here);
if(myText){
myText.pickupSprite(here);
}
};
var dropText = function(){
if(myText){
myText.dropSprite();
myText = false;
}
};
scrawl.canvas.mycanvas.addEventListener('mousedown', getText);
scrawl.canvas.mycanvas.addEventListener('mouseup', dropText);
//add event listener for changing the text
var input = document.getElementById('changetext');
var updateText = function(e){
displayText.set({
text: input.value,
});
};
input.addEventListener('keyup', updateText);
//build an animation loop for updating the canvas
var myPad = scrawl.pad.mycanvas;
var animate = function(){
here = myPad.getMouse();
//drop the text if mouse moves out of the canvas area
if(!here.active && myText){
dropText();
}
scrawl.render()
requestAnimFrame(function(){
animate();
});
};
//start animation
animate();
};
</script>
</body>
</html>
Working demo: over at jsFiddle

How to draw portion of pie image using canvas or Wedge shape in kinetic with touch event on iPad

I use canvas or maybe Wedge shape in kinetic framework to load 2 circle image, 1 for image background, 1 for image percentage of pie. I bind touchstart, touchmove, touchend event for canvas container. Then i face 2 problem : first thing how to use canvas load a portion of circle image. For example : just load 1/4 of image circle. second thing is how to calculate portion of pie based on point of touch, when we touch down and move finger percentage of pie will increase and decrease as well.
please give me some suggestion or example. thanks in advance
How to draw a wedge containing an image which changes based on clicks/taps
For your inner “wedge”, you can use a Kinetic.Group object and use the clipFunc to crop an image into a wedge
Here’s the clipFunc for the image-wedge:
clipFunc: function(canvas) {
var ctx = canvas.getContext();
var w=wedgeWidth;
var h=wedgeHeight;
var r=wedgeRadius;
var angle1=0; // start at vertical
var angle2=angle1+radianAngle;
ctx.moveTo(cx,cy);
ctx.arc(cx,cy,r,angle1,angle2,false);
ctx.closePath();
}
radianAngle is the variable that controls the size of the wedge.
You can set the radianAngle (and the wedge size) like this:
// if the user clicks/taps on the stage
// redraw the image-wedge to the angle of the click/tap
function setRadianAngle(touchX,touchY){
radianAngle=(Math.atan2(touchY-cy,touchX-cx)+Math.PI*2)%(Math.PI*2);
layer.draw();
}
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/DxZLJ/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Prototype</title>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.5.4.min.js"></script>
<style>
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:400px;
height:400px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 400,
height: 400
});
var layer = new Kinetic.Layer();
stage.add(layer);
enableStageClick();
function enableStageClick(){
$(stage.getContent()).on('click tap', function (event) {
var pos=stage.getMousePosition();
var mouseX=parseInt(pos.x);
var mouseY=parseInt(pos.y);
console.log(mouseX+"/"+mouseY);
setRadianAngle(mouseX,mouseY);
});
}
var wedgeWidth=300;
var wedgeHeight=300;
var wedgeRadius=100;
var borderRadius=20;
var radianAngle=135*Math.PI/180;
var cx=wedgeWidth/2;
var cy=wedgeHeight/2;
// create the outside "border" circle
var border = new Kinetic.Circle({
x: wedgeWidth/2,
y: wedgeHeight/2,
radius: wedgeRadius+borderRadius,
fill:"skyblue",
stroke: "blue",
strokeWidth: 5
});
layer.add(border);
// create the inside "image-wedge" group
var wedge=new Kinetic.Group({
x:0,
y:0,
width:wedgeWidth,
height:wedgeHeight,
// clip to a wedge with angle==degreeAngle off vertical
clipFunc: function(canvas) {
var ctx = canvas.getContext();
var w=wedgeWidth;
var h=wedgeHeight;
var r=wedgeRadius;
var angle1=0; // start at vertical
var angle2=angle1+radianAngle;
ctx.moveTo(cx,cy);
ctx.arc(cx,cy,r,angle1,angle2,false);
ctx.closePath();
}
});
layer.add(wedge);
// create the image that will be clipped inside the wedge
var image=new Kinetic.Image({
image:image,
x:0,
y:0,
width:wedgeWidth,
height:wedgeHeight,
});
wedge.add(image);
// load the image for the Kinetic Image object
var img=new Image();
img.onload=function(){
image.setImage(img);
layer.draw();
}
img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/KoolAidMan.png";
// if the user clicks/taps on the stage
// redraw the image-wedge to the angle of the click/tap
function setRadianAngle(touchX,touchY){
radianAngle=(Math.atan2(touchY-cy,touchX-cx)+Math.PI*2)%(Math.PI*2);
layer.draw();
}
}); // end $(function(){});
</script>
</head>
<body>
<p>Click/Touch to change angle of wedge-image</p>
<div id="container"></div>
</body>
</html>

How to make html5 canvas shape resizable

check out: http://jsfiddle.net/aqaP7/4/,
and
http://shedlimited.debrucellc.com/test3/canvaskinclip.html,
I want to make html5 images resizable,
and it needs to be based on the html5 etc because my clipping region is in html5
I think that it will have to do with the mousedown events, but how for example can I tell if the
mouse is on the corner of the shape? Can I just add the code to my circle - mousedown function?
circle.on("mousedown", function(){
draggingShape = this;
var mousePos = stage.getMousePosition();
draggingRectOffsetX = mousePos.x - circle._x;
draggingRectOffsetY = mousePos.y - circle._y;
});
circle.on("mouseover", function(){
document.body.style.cursor = "pointer";
});
circle.on("mouseout", function(){
document.body.style.cursor = "default";
});
layer.add(circle);
stage.on("mouseout", function(){
draggingShape = undefined;
}, false);
stage.on("mousemove", function(){
var mousePos = stage.getMousePosition();
if (draggingShape) {
draggingShape._x = mousePos.x - draggingRectOffsetX;
draggingShape._y = mousePos.y - draggingRectOffsetY;
layer.draw();
}
Take a look at this canvas tutorial:
Take a look at this tutorial
Here is some simple code to get you started:
var anchor;
function addAnchor(group, x, y, name) {
var stage = group.getStage();
var layer = group.getLayer();
anchor = new Kinetic.Circle({
x: x,
y: y,
stroke: "#666",
fill: "#ddd",
strokeWidth: 2,
radius: 8,
name: name,
draggable: true
});
anchor.on("dragmove", function() {
update(group, this);
layer.draw();
});
anchor.on("mousedown touchstart", function() {
group.setDraggable(false);
this.moveToTop();
});
anchor.on("dragend", function() {
group.setDraggable(true);
layer.draw();
});
// add hover styling
anchor.on("mouseover", function() {
var layer = this.getLayer();
document.body.style.cursor = "pointer";
this.setStrokeWidth(4);
layer.draw();
});
anchor.on("mouseout", function() {
var layer = this.getLayer();
document.body.style.cursor = "default";
this.setStrokeWidth(2);
layer.draw();
});
group.add(anchor);
}
Essentially, you want to add anchors to a shape on click, then use those anchors for resizing.