KineticJS toImage Width and Height issue - javascript

Im running into this strange problem..! I've a kineticJS text element and I'm converting it into image.. Here is the Code
var simpleText = new Kinetic.Text({
x: 50,
y: 50,
text: $("#text").val(),
fontSize: $("#fontSize").val(),
fontFamily: $("#fontName").val(),
fill: $("#fontColor").val(),
});
var twidth = simpleText.getWidth();
var theight = simpleText.getHeight();
simpleText.toImage({
width:twidth,
height:theight,
callback: function(img){
var textImg = new Kinetic.Image({
image: img,
x: 0,
y: 0,
width: twidth,
height: theight,
name: 'image',
stroke: 'red',
strokeWidth: 2,
strokeEnabled: false
});
addElement(textImg, textImg.getWidth(), textImg.getHeight());
}
});
So the problem exist here..!
var twidth = simpleText.getWidth();
var theight = simpleText.getHeight();
If I just put the width and height in numeric form, everything works fine and text is converted, something like this
var twidth = 500;
var theight = 100;
But if I use simpleText.getWidth() and simpleText.getHeight(), nothing happens, the image is created but it doesn't have that TEXT. As I saw in documentation, width and height are optional params for toImage(), so I removed now, but now its show this error..
Uncaught TypeError: Cannot read property 'bufferCanvas' of undefined
kinetic.js:28 Kinetic.Node.toDataURL kinetic.js:28
Kinetic.Node.toImage kinetic.js:28 add_text canvas.js:83 (anonymous
function) canvas.js:352 f.event.dispatch jquery.min.js:3 h.handle.i
any idea whats wrong with my code?

I am not shure is it bug or feature. But problem is: picture are taken from rectangle with this coordinates: {x:0 y:0}; width and height - what you insert as toImage params. (twidth, theight)
But text has coords {x : 50, y : 50}. So it is outside of "picture" rectagle above.
As you say if yor increase width and height:
var twidth = 500;
var theight = 100;
Everything is fine and you will see text, but image will be big with empty space.
So... just insert "x" and "y" params to toImage function:
simpleText.toImage({
width:twidth,
height:theight,
x : 50,
y : 50,
callback: function(img){
$('body').append($(img));
}
});
example: http://jsfiddle.net/lavrton/hgax2/

Related

canvas not rendering shape after adding new shape

I have a problem with fabric.js. I can use fabric.version, but after new fabric.Rect{top : 100,left : 100,width : 120,height : 30, fill : 'red'} and use canvas .add it, the rect not show but mouseEvent is ok.
my fabric.js version is 3.4.0
#angular/core": "~7.2.0","fabric": "^3.4.0"
ngOnInit() {
let canva1 = new fabric.Canvas('myCanvas');
console.log(fabric.version);
let rect = new fabric.Rect({
top : 100,
left : 100,
width : 120,
height : 30,
fill : 'red'
});
canva1.add(rect);
}
I expect a rect show on the canvas but no rect show
You have style="background: white" on your canvas element and it just blends with the background.
https://github.com/zhangManGod/canvas/blob/master/src/app/right/right.component.html#L3
Unless you have created your canvas with renderOnAddRemove = true (http://fabricjs.com/docs/fabric.Canvas.html#renderOnAddRemove) then you will need to call requestRenderAll on your canvas after you have added or removed items(s).
(http://fabricjs.com/docs/fabric.Canvas.html#requestRenderAll)
ngOnInit()
{
let canva1 = new fabric.Canvas('myCanvas');
console.log(fabric.version);
let rect = new fabric.Rect(
{
top : 100,
left : 100,
width : 120,
height : 30,
fill : 'red'
});
canva1.add(rect);
canva1.requestRenderAll()
}

How does `getShift` and transform work on an SVG

I was just going though THIS SVG animation demo , its pritty straightforward , i was jus tgoing through the JS code and came actoss the below lines of code;
var g = Snap();
g.attr({
viewBox: [0, 0, 800, 600]
});
Snap.load("map.svg", function (f) {
function getShift(dot) {
return "t" + (400 - dot.x) + "," + (300 - dot.y);
}
var gr = f.select("g"),
wrd = f.select("#world").attr({fill: "#fff"}),
syd = f.select("#sydney").attr({fill: "red"}),
msk = f.select("#san_francisco").attr({fill: "red"}),
pth = f.select("#flight"),
pln = f.select("#plane"),
top = g.g()
// DIFF above line of code , what is g.g();
top.attr({
mask: g.rect(100, 0, 600, 600).attr({
fill: "r(.5,.5,.25)#fff-#000"
})
});
top.add(gr);
var click = top.text(410, 310, "click!").attr({
font: "20px Source Sans Pro, sans-serif",
fill: "#fff"
});
pth.attr({
display: "none"
});
// DIFF , i am not quite understanding below line of code.
pln = gr.g(pln, pln.clone());
pln.attr({
display: "none"
});
pln[0].attr({
stroke: "#fff",
strokeWidth: 2
});
gr.attr({
transform: getShift({
x: syd.attr("cx"),
y: syd.attr("cy")
})
});
Now my question is about the below lines of code:
gr.attr({
transform: getShift({
x: syd.attr("cx"),
y: syd.attr("cy")
})
});
I beleive the layer gr is being transform , but i don't entirely understand this line of code , What exactly is getShift and ofcourse i do understand that the 'cx' and 'cy' attributes of the syd layer above are being used to transform the elements, but how does this line of code work as a whole and also what is getShift ?
getShift itself has nothing to do specifically with the Snap library. It is defined in the top of the code you included, and simply returns a string based on an object you provide:
function getShift(dot) {
return "t" + (400 - dot.x) + "," + (300 - dot.y);
}
So if you call getShift with a parameter of an object with the following properties, {x: 10, y: 20}, then getShift will return the string "t380,290".
That string, however, can then be used by Snap to transform an element. Specifically, it is being used as follows:
gr.attr({transform: "t380,290"});
(based on my fictitious initial values).
It seems like what it's trying to do is the following: Translate the entire group ("gr") (i.e. the whole world map?) such that the position of Sydney, Australia ("syd") ends up at the coordinates (400, 300), i.e. in a pleasantly-viewable somewhat-central part of the screen/window/div. Without going through the entire code, it seems like this is probably setting up the characteristics for the end of the animation.

Aligning a fabric.js object to the top left corner of the inner text of an IText element

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

Making JS "this" work in prototype function

Being new to Javascript, my understanding of this is a bit shaky. I've read a few articles and SO posts and learned quite a bit, but I'm having issues implementing some code. I'm using the KineticJS library to implement some canvas functions. I was working with a fiddle and was able to get an image to resize with the mouse control, however, when I put the code into a prototype function, resizing no longer works.
Canvas.prototype.addImg = function(){
var self = this;
var image;
var imageObj = new Image();
imageObj.onload = function() {
image = new Kinetic.Image({
x: 200,
y: 50,
image: imageObj,
width: 106,
height: 118,
draggable: false
});
self.backgroundLayer.add(image);
self.stage.add(self.backgroundLayer);
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg';
var circle1 = new Kinetic.Circle({
x: 150,
y: 150,
radius: 10,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
draggable: false
});
circle1.isResizing = false;
circle1.on("click", function (e) {
// toggle resizing true/false
var isResizing = !this.isResizing;
this.setDraggable(isResizing);
self.backgroundLayer.setDraggable(!isResizing);
this.setFill((isResizing ? "green" : "red"));
this.isResizing = isResizing;
self.backgroundLayer.draw();
});
circle1.on("dragmove", function () {
if (this.isResizing) {
var pos = this.getPosition();
var x = pos.x;
var y = pos.y;
var rectX = image.getX();
var rectY = image.getY();
image.setSize(x - rectX, y - rectY);
self.backgroundLayer.draw();
}
});
self.backgroundLayer.add(circle1);
self.backgroundLayer.draw();
}
I am assuming the problem lies within the use of this in the function, but I'm not sure how to fix the problem. Could somebody tell me what the problem is and how I would fix this?
I can see a problem with the line that is setting the size of image:
image.setSize(x - rectX, y - rectY);
For example if x is 100 and rectX is 200, you end up with a width of '-100', which is not legal.
In the fiddle you provided, when I use constant values, the image re-sizes perfectly:
rect.setSize(200, 200);
Modified fiddle.
The solution I've come upon, is that it is not an issue of this, but the setSize() method. For some reason or another, it is not working in my local application. When I replace this for setWidth() and setHeight(), everything works the way that it should.

g.raphael : how to animate bar chart height?

Is there any option to increase bar chart as animation from 0 to ?
bars.animate({'stroke':"#FF0"},1000); this can change attributes. Actually I need to change value of bar chart height and also change label when increase which didn't find yet.
var svgWidth = 400;
var svgHeight = 450;
var r = Raphael('overview');
var barBorder = {stroke: '#000', 'stroke-width':1};
r.setViewBox(0, 0, svgWidth, svgHeight, false);
r.setSize('100%', '100%');
var colors = [ "#999", "#B2B2B2", "#CCC"];
data4 = [[83], [72], [43]];
data2 = [[13], [22], [20]];
var bars = r.barchart(50, 20, 250, 150, data4, {colors: colors, 'gutter': '-1%'}).bars.attr(barBorder);//.hover(fin, fout);
var unicorn = r.path("M350 150 H10 V10").attr({stroke: "#000","stroke-width": 1});
bars.animate({'stroke':"#FF0"},1000);
Demo.
Finally changed barchart() to rect()
here is my solution http://jsfiddle.net/sweetmaanu/sqnXM/
// Create options object that specifies the rectangle
var PatientBar1 = { width: 100,height: 200,x: 0,y: 0}
var PatientBar2 = { width: 100,height: 180,x: 100,y: 20}
var PatientBar3 = { width: 100,height: 120,x: 200,y: 80}
var speed = 2000;
// Create new raphael object
var patient01 = new Raphael('patient02-mobile', 300, 300);
/*
* Create rectangle object with y-position at bottom by setting it to the specified height,
* also give the rectangle a height of '0' to make it invisible before animation starts
*/
var rect1 = patient01.rect(PatientBar1.x, PatientBar1.height, PatientBar1.width, 0).attr({fill: '#999', stroke:'#000'});
var rect2 = patient01.rect(PatientBar2.x, 200, PatientBar2.width, 0).attr({fill: '#B2B2B2', stroke:'#000'});
var rect3 = patient01.rect(PatientBar3.x, 200, PatientBar3.width, 0).attr({fill: '#CCC', stroke:'#000'});
/*
* Animate the rectangle from bottom up by setting the height to the earlier specified
* height and by setting the y-position to the top of the rectangle
*/
var anim1 = rect1.animate({
y:PatientBar1.y,
height:PatientBar1.height
}, speed);
var anim2 = Raphael.animation({
y:PatientBar2.y,
height:PatientBar2.height
}, speed);
var anim3 = Raphael.animation({
y:PatientBar3.y,
height:PatientBar3.height
}, speed);
rect2.animate(anim2.delay(2000));
rect3.animate(anim3.delay(4000));
Please post answer if anybody find solution :)

Categories