editable Text option in kinetic js - javascript

I want to add Textbox or editable element to give the user the option to edit the text.
This is my current code:
var text = new Kinetic.Text({
text: "Sample Text", ---> i want to edit this text
x: 50,
y: 10,
fill: "transparent",
fontSize: 10,
fontFamily: "Helvetica Neue",
textFill: "#000",
align: "center",
verticalAlign: "middle",
name:'TEXT'
});

At the moment there does not seem to be any way to create editable text with Kinetic JS (see several threads about this at stackoverflow), some people suggest using an input field next to the canvas to edit the text, but my solution would be the following:
create a text with your code
on text click [text.on("click", function...], create an input field right at your mouse cursor
Well, that´s the plan. Maybe it´s easier to use a "save" button text to the input field, so you know exactly when to close it and when to store the input field data to the Kinetic text. you would also need a "close" function if you don´t want to edit it.
A very easy solution would also be a simple JavaScript prompt:
var xy = prompt("gimme your text");
So, something like this would be the best Solution imho:
myText.on('click', function(evt) {
this.setText(prompt('New Text:'));
layer.draw(); //redraw the layer containing the textfield
});

I've made an attempt for an actual KinetiJS plugin with editable text functionality.
I know it's reinventing the wheel, when you can just hover a textarea, but why not have it only in canvas too.
Check the plugin out at: https://github.com/nktsitas/kineticjs-editable-text

I did this some days back on my project. Hare are the code snippets. Basically we first draw the rectangle and then put a text area inside it and finally convert it into kinetic.text node.
drawText: function ( color )
{
var layer1=this.model.stage.getLayers()[0];
var $this=this;
console.log('drawText: color: ' + color);
if($this.rectangleDrawn==true)
{
var down = false, oPoint;
layer1.off("mousedown touchstart mousemove touchmove mouseup touchend");
if(group!=undefined && group!='')
{
$this.hideAnchors(group);
}
console.log("textX: "+textX);
//after rectangle is drawn we now have to add the editablesection
$('<textarea id="text" type="text" width='+textWidth +'px height='+textHeight+'px style="font-size: 30px;font-family:Calibri;height:'+textHeight+'px;width:'+textWidth+'px;position:absolute'+';left:'+textX+'px'+';top:'+textY+'px'+';z-index:5'+';background-color:#ffcc00;"></textarea>')
.insertBefore('.kineticjs-content');
$('#text').on('blur',function()
{
console.log("textchange");
text = new Kinetic.Text( {
x: textX,
y: textY,
stroke: color,
strokeWidth: 1,
fontSize: 30,
fontFamily: 'Calibri',
clearBeforeDraw: false,
name: 'image'+layer1.getName(),
draggable: true,
height: textHeight,
width: textWidth,
text: $('#text').val()
} );
text.on( 'mouseleave dbltap', function ()
{
text=this;
} );
$('#text').remove();
layer1.add( text );
layer1.draw();
})
},drawRectangle: function ( opacity, colorFill,stroke,textColor ){rect = new Kinetic.Rect({
x: mousePos.x,
y: mousePos.y,
width: 0,
height: 0,
stroke: stroke,
strokeWidth: 4,
opacity: opacity,
clearBeforeDraw: false,
name: 'image'+layer1.getName()
});
layer1.on( "mouseup touchend", function ( e )
{
console.log("rectangle: mouseup");
console.log("width: "+rect.getWidth( ));
rect.setOpacity(opacity);
rect.setFill(colorFill);
layer1.draw();
down = false;
console.log("textColor: "+textColor)
if(textColor!=undefined)
{
textWidth=rect.getWidth( );
textHeight=rect.getHeight( );
textX = rect.getAbsolutePosition().x;
textY=rect.getAbsolutePosition().y;
$this.rectangleDrawn=true;
$this.drawText(textColor);
console.log("textdrawn ");
$this.group.remove();
}
},

Related

Adding transformer to dynamically generated shapes?

I have the button which add new group which have square, to layer when clicked very simple code I guess no need to post. But my question is that how can I add transformer to it when on clicked?, I have done it with this mouseleave and mouseenter functions.
group.on('mouseenter', () => {
transformer.borderEnabled(true);
transformer.resizeEnabled(true);
layer.draw();
});
group.on('mouseleave', () => {
transformer.borderEnabled(false);
transformer.resizeEnabled(false);
layer.draw();
});
It is in loop which creates new group named "group", It works fine but in circle when I hover it the transformer appears but then when I go to transformer's boxes to resize it consider as it is mouseleave but this is doing only in circle not in line text.
So can I have solution for active transformer on element which is clicked or for considering hover on transformer boxes as a hover on node? Thanks
The mouseleave() will always fire because the pointer must leave the group to use the transformer handles or spinner.
An alternative approach would be
click to enable the transformer,
leave the transformer in place even when the mouse moves away
wait for a click on some other shape to know you can hide the transformer.
That is the standard GUI approach I believe.
If you need to show hover focus then stick a transparent rectangle the size of the groups clientrect into the group and change its stroke from transparent to some colour in the mouseenter and back in the mouseleave. You will also maybe want to set the rect.listening to false so as it coes not interfere with mouse events on the shapes in the group, but then again it might help in dragging.
Demo below.
// Set up the canvas and shapes
let stage = new Konva.Stage({container: 'container1', width: 300, height: 200});
let layer = new Konva.Layer({draggable: false});
stage.add(layer);
// Add a transformer.
let transFormer1 = new Konva.Transformer();
layer.add(transFormer1);
// Create a sample group
let group1 = new Konva.Group();
layer.add(group1);
group1.add(new Konva.Circle({x: 20, y: 30, radius: 15, fill: 'magenta', stroke: 'black'}))
group1.add(new Konva.Circle({x: 60, y: 40, radius: 15, fill: 'magenta', stroke: 'black'}))
group1.add(new Konva.Rect({x: 90, y: 60, width: 25, height: 25, fill: 'magenta', stroke: 'black'}));
let pos = group1.getClientRect();
let boundRect1 = new Konva.Rect({name: 'boundRect', x: pos.x, y: pos.y, width: pos.width, height: pos.height, fill: 'transparent', stroke: 'transparent'});
group1.add(boundRect1);
// When mouse enters the group show a border
group1.on('mouseenter', function(){
let boundRect = this.find('.boundRect');
boundRect[0].stroke('red');
layer.draw();
})
// and remove border when mouse leaves
group1.on('mouseleave', function(){
let boundRect = this.find('.boundRect');
boundRect[0].stroke('transparent');
layer.draw();
})
// If the group is clicked, enable the transformer on that group.
group1.on('click', function(){
transFormer1.attachTo(this)
layer.batchDraw();
})
// For a more pleasing demo let us have 2 groups.
// Make a copy of group1, offset new group, and change fill on its child shapes except the bound rect
let group2 = group1.clone();
layer.add(group2)
group2.position({x: 120, y: 30});
for (let i = 0, shapes = group2.getChildren(); i < shapes.length; i = i + 1){
shapes[i].fill(shapes[i].fill() !== 'transparent' ? 'cyan' : 'transparent');
}
stage.draw();
<script src="https://unpkg.com/konva#^3/konva.min.js"></script>
<p>Move mouse over the shapes to see the group borders, click a group to apply the transformer.
</p>
<div id='container1' style="display: inline-block; width: 300px, height: 200px; background-color: silver; overflow: hidden; position: relative;"></div>
Got the answer!, I just create a public transformer and on stage click I am adding nodes to it no transformer to each group just one public transformer which hold one node at a time.

Change sprite text dynamically on chart

Is there any way to change sprite text dynamically on a chart?
This is not working:
this.lookupReference('chart').setText('Second Text');
Fiddle: https://fiddle.sencha.com/#view/editor&fiddle/1mij
handler: function(){
var chart=this.next();
chart.setSprites({
type: 'text',
reference: 'sprites',
text: 'Second text ',
font: '13px Helvetica bold',
width: 100,
height: 30,
x: 50, // the sprite x position
y: 17 // the sprite y position
});
chart.redraw();
}
here is your forked working fiddle
The chart is made by a canvas, you can't get a specific "piece of the chart" and modify it, so you simply need to redraw the chart with the new text.

Fabric.Js - Making the text that has been added to the canvas editable

I seem to be having problems with making the text that is added to the canvas editable. I expect when you double click on the object for it to then change into an editable field but this doesn't seem to happen.
Below is the code that I am using and have read that you should be using for this to work:
service.addEditableType = function () {
service.canvas.add(new fabric.Text('Double tab here to type', {
fontFamily: 'Delicious_500',
fontSize: 30,
left: 100,
top: 100
}));
};
So this is what I'm using to add the text 'Double tab here to type' to the canvas. But if you then double click on the text it doesn't turn into an editable field.
Let me know your thoughts
Being a complete plonker...
I forgot the 'I' in 'Text'
The working code is as below:
service.addEditableType = function () {
service.canvas.add(new fabric.IText('Double tab here to type', {
fontFamily: 'Delicious_500',
fontSize: 30,
left: 100,
top: 100
}));
};

kinetic js group position is not correct when dragging

I am trying to create group object that include text,image .
I want to get right position(x,y) when dragging the group object.
Now i get minus value {x:-26,y:-18} like that.
var text2=new Kinetic.Text({
x: 40,
y: 125,
text: 'Time:4:20',
fontFamily: 'Calibri',
fontSize: 12,
padding: 5,
fill: 'red',
draggable: false
});
var group = new Kinetic.Group({
width:94,
height:45,
draggable: true
});
group.on('dragend', function() {
alert("X:"+group.getAbsolutePosition().x+"Y:"+group.getAbsolutePosition().y);
});
group.add(text2);
layer.add(group);
stage.add(layer);
Your code is working normally.
You have a non-draggable text on the draggable group.
This causes the text to act as a "handle" to drag whole group.
(the text does not move relative to the group. Instead the whole group is moved by dragging the text).
So if you drag the text up and left a bit the group will be pulled up and left a bit.
Therefore the group reports negative coordinates.

RaphaelJS HTML5 Library : creating a button with text and glow on mouseover

I am trying to create a button with text inside using the Raphael JavaScript library. I would like to have a glow around the button on mouseover. I achieved this by using the set on rectangle and text and applying the glow on the set. I tried two approaches binding the mouseover and mouseout methods to the resulting button set. In the first case the glow stays if the cursor reaches the text, in the second one the glow disappears. Here is the code :
// canvas
var paper = Raphael(0, 0, "100%", "100%");
// background of the first button
var bBox1 = paper.rect(100, 100, 120, 50, 10).attr({
fill: 'darkorange',
stroke: '#3b4449',
'stroke-width': 2
});
// text of the first button
var text1 = paper.text(bBox1.attrs.x + bBox1.attrs.width / 2, bBox1.attrs.y + bBox1.attrs.height / 2, 'Click to expand').attr({
"font-family": "Helvetica",
"font-size": 16
});
// set of rectangle + text = button
var button1 = paper.set().attr({
cursor: 'pointer'
});
button1.push(bBox1);
button1.push(text1);
button1.mouseover(function (event) {
this.oGlow = bBox1.glow({
opacity: 0.85,
color: 'gray',
width: 15
});
}).mouseout(function (event) {
this.oGlow.remove();
});
// ********** now the second button **********
// background of the second button
var bBox2 = paper.rect(100, 200, 120, 50, 10).attr({
fill: 'lightblue',
stroke: '#3b4449',
'stroke-width': 2
});
// text of the first button
var text2 = paper.text(bBox2.attrs.x + bBox2.attrs.width / 2, bBox2.attrs.y + bBox2.attrs.height / 2, 'Click to expand').attr({
"font-family": "Helvetica",
"font-size": 16
});
// set of rectangle + text = button
var button2 = paper.set().attr({
cursor: 'pointer'
});
button2.push(bBox2);
button2.push(text2);
// function for the mousover event for buttons
var buttonMouseoverHandler = function (event) {
this.oGlow = this.glow({
opacity: 0.85,
color: 'gray',
width: 15
});
}
// function for the mouseout event
var buttonMouseoutHandler = function (event) {
this.oGlow.remove();
}
button2.mouseover(buttonMouseoverHandler);
button2.mouseout(buttonMouseoutHandler);
Here is a working jsfiddle example : http://jsfiddle.net/fkNhT/
I absolutely do not understand the difference in the behavior, can anyone please give me a hint?
Simple: In the first mouseover, you're setting the glow on the rect object, regardless of what's being moused over:
this.oGlow = bBox1.glow({...
In the second, you're setting it to "this", which would apply to the text object when you mouse over it:
this.oGlow = this.glow({...
How to prevent the loss of hover on interior elements of an element is one of the most common Raphael-related questions on SO. See this for a simple solution for small projects, and this open thread for an alternative for bigger projects.

Categories

Resources