I am creating a editor in which I have used kinetic js. In my editor there is dynamic text which are draggable, but in case of editing text I need to get the click element for individual text over the canvas so that when user click on a text I can track that and edit that text .
Here is the script
var stage = new Kinetic.Stage({
container: 'editor',
width: 600,
height: 600
});
var boxLayer = new Kinetic.Layer();
var rectX = 0;
var rectY = 0;
stage.add(boxLayer);
function add_text() {
alert('test');
var complexText1 = new Kinetic.Text({
x: 25,
y: 25,
text: 'Designer',
fontSize: 18,
fontFamily: 'Calibri',
fill: '#555',
width: 150,
padding: 20,
align: 'center',
draggable: true
});
boxLayer.add(complexText1);
boxLayer.draw();
complexText1.destroy();
complexText1.on('mouseover', function() {
this.fill('orange');
});
}
also I have user complexText1.destroy(); and after this draggable function is not working . I am new in canvas editor so need help to create it, any help regarding this will be appreciable.
Related
I am trying to set a background color for a group without affecting its contained objects.
So far my code looks like this:
var canvas = new fabric.Canvas('canvas');
var helloText = new fabric.Text('hello', {
fontSize: 30,
top: 10, left: 10,
originX: 0, originY: 0
});
var worldText = new fabric.Text('world!', {
fontSize: 40,
top: 50, left: 100,
originX: 0, originY: 0
});
var group = new fabric.Group([helloText, worldText], {
selectionBackgroundColor: 'red',
backgroundColor: 'blue'
});
canvas.add(group);
A jsFiddle version can be found here.
As you can see from my code, I already tried the attribute backgroundColor yet it only affects contained objects. I would like to achieve an effect similar to selectionBackgroundColor.
Slight tweak, but this should do it for you (relevant code):
var text = new fabric.Group([helloText, worldText], {});
var textBoundingRect = text.getBoundingRect();
var background = new fabric.Rect({
top: textBoundingRect.top,
left: textBoundingRect.left,
width: textBoundingRect.width,
height: textBoundingRect.height,
fill: 'blue'
});
var group = new fabric.Group([background, text], {});
Your JSFiddle updated, https://jsfiddle.net/rekrah/92ss3d86/.
http://jsfiddle.net/541ev5nh/15/
I'm attempting to align the red Text object to the upper-left corner of the black IText object. When the Itext object is not rotated (at angle 0), you can see that the text is correctly aligned. However, rotating the IText throws the alignment off.
Resizing or changing the text of the IText also throws off the alignment, but don't worry about that for now. The rotation is the only thing that needs to work right now.
The problem is obviously coming from the fact that I'm using magic numbers to align the two items. I need a formulaic way derive these numbers that will keep the alignment consistent when the IText is rotated. Any ideas?
HTML:
<canvas id="canvas" width="800" height="600" style=""></canvas>
Javascript:
var w = 800;
var h = 600;
var cx = w/2;
var cy = h/2;
var auto = false; // auto/manual rotation
// Main "Text"
var txt = "Text";
var canvas = new fabric.Canvas('canvas');
var text = new fabric.IText(txt, {
left: 20,
top: 30,
fontFamily: 'sans-serif',
fontSize: 80
});
canvas.add(text);
var pt = new fabric.Point(cx,cy);
text.setPositionByOrigin(pt, 'center', 'center');
canvas.setActiveObject(text);
// decorator
var txt = "Top left";
var deco = new fabric.Text(txt, {
left: 20,
top: 30,
fontFamily: 'sans-serif',
fontSize: 14,
stroke: '#DD0000',
fill: '#DD0000'
});
canvas.add(deco);
canvas.on('object:modified', onModified);
function onModified(data){
var rotatedPoint = data.target.getPointByOrigin("left", "top");
deco.rotate(data.target.angle);
deco.setPositionByOrigin(new fabric.Point(rotatedPoint.x + 1, rotatedPoint.y + 11), 'left', 'top');
canvas.renderAll();
}
var angle = -2;
if (auto){
setInterval(onInterval, 30);
}
else{
onInterval();
text.setCoords();
}
function onInterval(){
angle += 2;
text.rotate(angle);
var data = {
target: text
};
onModified (data);
}
You can achieve this by making objects group. Fabric has a nice support for object group.
See here:
// Main "Text"
var txt = "Text";
var canvas = new fabric.Canvas('canvas');
canvas.clear();
var text = new fabric.IText(txt, {
fontFamily: 'sans-serif',
fontSize: 80
});
// decorator
var txt = "Top left";
var deco = new fabric.Text(txt, {
top:10,
fontFamily: 'sans-serif',
fontSize: 14,
stroke: '#DD0000',
fill: '#DD0000'
});
var group = new fabric.Group([ text, deco ], {
angle: 0
});
var lefts=canvas.getWidth()/2-group.getWidth()/2;
var tops=canvas.getHeight()/2-group.getHeight()/2;
group.set({
'left':lefts,
'top':tops
});
canvas.add(group);
canvas.renderAll();
See in Fiddler
I double click on a canvas to create an element, and the user can do this n times. Each element is draggable.
For each element, if I drag it to within a certain rectangle of x/y coordinates, I want to then clearRect() within that rectangle, effectively deleting the dragged element.
How implement this?
Current:
var stage = new Kinetic.Stage({
container: 'container',
width: 662,
height: 983
});
var layer = new Kinetic.Layer();
stage.add(layer);
$(stage.getContent()).on('dblclick', function (event) {
var pos = stage.getMousePosition();
var mouseX = parseInt(pos.x);
var mouseY = parseInt(pos.y);
var text = new Kinetic.Text({
x: mouseX,
y: mouseY,
text: cc,
fill: "blue",
draggable: true,
});
layer.add(text);
layer.draw();
}
You can use yourElement.on("dragend",handler) to test if the element is inside the deletion rectangle.
If it is inside you can use yourElement.destroy() to destroy that element.
Example code and a Demo: http://jsfiddle.net/m1erickson/jqPhe/
var stage = new Kinetic.Stage({
container: 'container',
width: 350,
height: 350
});
var layer = new Kinetic.Layer();
stage.add(layer);
// define the boundaries of the deletion box
var dx=200;
var dy=40;
var dw=100;
var dh=100;
// create the deletion box
var deleteMe=new Kinetic.Rect({
x:dx,
y:dy,
width:dw,
height:dh,
stroke:"red"
});
layer.add(deleteMe);
var label=new Kinetic.Text({
x:dx,
y:10,
text:"Drag here to delete\n(Must be fully inside)",
fill:"black"
});
layer.add(label);
// create a circle element for testing purposes
var circle1 = new Kinetic.Circle({
x:100,
y:100,
radius: 30,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
draggable: true
});
// on dragend: test if this circle is inside the deletion rectangle. If yes, delete this circle.
circle1.on("dragend",function(){
var x=this.getX();
var y=this.getY();
if(x>=dx && x<=dx+dw && y>=dy && y<=dy+dh){
this.destroy();
layer.draw();
}
});
layer.add(circle1);
layer.draw();
I want to change the text in my container for kinetic js using keyup event in jquery but it doesn't display. I tried getting the value then display it on a span element and it works fine.
Here's my code:
var stage = new Kinetic.Stage({
container: 'canvasContainer',
width: 800,
height: 800
});
var layer = new Kinetic.Layer();
var message = '';
$(function(){
$('#txtArea').change(function(){
message = $(this).val();
$('.output').text(message);
var simpleText = new Kinetic.Text({
x: 0,
y: 10,
text: message,
fontSize: 30,
fontFamily: 'Calibri',
fill: 'blue'
});
layer.add(simpleText);
}).keyup(function(){
$(this).change();
});
});
stage.add(layer);
After you add or change a Kinetic object, be sure you call layer.draw() to cause the drawing to be visible.
BTW, instead of adding a new simpleText with each change, you might want to just change the text in the existing text object
// declare simpleText before .change()
var simpleText = new Kinetic.Text({
x: 0,
y: 10,
text: "",
fontSize: 30,
fontFamily: 'Calibri',
fill: 'blue'
});
layer.add(simpleText);
// then inside .change()
simpleText.setText(message);
layer.draw();
I'm trying to get kineticjs down and worked out a little app which makes my images draggable and resizable. So far so good;
However: I want an overlay with a variable height/width block in the center which should show the image underneath(With the draggable/resizable intact) with a semi-transparent overlay.
I want to be able to still resize/drag behind the overlay while the overlay is still intact(Like this, but with kineticjs: http://envyum.nl/pointer/)
Is there a way to do so? By cutting a block out of an overlaying rectangle perhaps? And can the mouse ignore the overlay such as pointer-events: none can in css3?
Thanks in advance,
I have a sample of what I was talking about in the comments above: http://jsfiddle.net/KwQBB/
This did not require a new layer, but might be good practice to do so.
You can tailor the logic to be whatever you want, especially to simulate a 'cut-out'
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 500
});
var layer = new Kinetic.Layer();
var pentagon = new Kinetic.RegularPolygon({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
sides: 5,
radius: 70,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
draggable: true,
dragOnTop: false
});
var rect1 = new Kinetic.Rect({ // overlay
x: 0,
y: 0,
width: stage.getWidth(),
height: 100,
fill: 'gray',
opacity: 0.5,
listening: false // <------ Extremely important
});
var rect2 = new Kinetic.Rect({ // overlay
x: 0,
y: stage.getHeight()/2,
width: stage.getWidth(),
height: 100,
fill: 'gray',
opacity: 0.5,
listening: false // <------ Extremely important
});
// add the shape to the layer
layer.add(pentagon);
layer.add(rect1);
layer.add(rect2); // add more rectangles to complete overlay
// add the layer to the stage
stage.add(layer);