I have made a Fabricjs canvas where the user can move around images and so on... I use JSON.stringify(canvas) to get all the data in text. The problem is that i get ALL the data when i just want certain ones like scaleX, ScaleY,Angle ect. How can i do this?
HTml
<div id="CanvasContainer">
<canvas id="Canvas" width="270" height="519"></canvas>
</div>
Javascript
function exportData(){
JSON.stringify(canvas);
console.log(JSON.stringify(canvas));
}
JSON without additional properties
var json = canvas.toJSON();
JSON with additional properties included
var json = canvas.toJSON(['lockMovementX', 'lockMovementY', 'lockRotation', 'lockScalingX', 'lockScalingY', 'lockUniScaling']);
JSON without default values
canvas.includeDefaultValues = false;
var json = canvas.toJSON();
You can pass a replacer function as a second argument to the JSON.stringify function.
var wantedKeys = ['scaleX', 'scaleY', 'angle'];
JSON.stringify({ scaleX: 0, scaleY: 1, angle: 3, notThisOne: 4}, function (key, value) {
if (!key || wantedKeys.indexOf(key) !== -1) return value;
}); //{"scaleX":0,"scaleY":1,"angle":3}
The replacer can also simply be an array of keys to keep:
JSON.stringify({ scaleX: 0, scaleY: 1, angle: 3, notThisOne: 4}, wantedKeys);
Related
I am trying to re-write this code in javascript only without the jquery part.
var imgs = $.makeArray($("#images img"));
imgs.reverse();
function crossfade() {
TweenMax.to(imgs[0], 1, { autoAlpha: 0, scale: 1 });
TweenMax.to(imgs[1], 1, { autoAlpha: 1, scale: 1.2 });
imgs.push(imgs.shift());
}
var cycle = setInterval(crossfade, 3000);
Most especially the below part.
var imgs = $.makeArray($("#images img"));
imgs.reverse();
Get the Images with document.querySelectorAll, then put them in an array (as #rojo said in his comment) and reverse the order of that array.
var images = document.querySelectorAll("#images img"), //get the images as nodelist
images = Array.from(images), //transform the nodelist to an array
images = images.reverse() //reverse the array
// proceed with images...
This might help you
Array.from(document.querySelectorAll('#images img')).reverse()
To implement a undo/redo functionality, I have constructed an array "history" that gets filled with the latest changes based on canvas.on() events.
console.log dump:
History:
(3) […]
0: Object { target: {…} } //first object added
1: Object { e: mouseup, target: {…}, transform: {…}, … } //first object modified
2: Object { target: {…} } //another object added
length: 3
To walk back the stack of changes, I wanted to use history[step].target which contains the modified object at this stage (step).
I now look for a method to overwrite an object in the object array of fabric.
The function canvas.item(0) gives the object at position 0 on the current canvas but how can I overwrite that object with a different object (from the history[].target array)?
Note: Solutions I found for a undo/redo are seemingly based on serializing the whole canvas into JSON and saving this into an array of JSONs. I didn't want to do this since it seems a bit unsophisticated to always serialize/unserialize the whole canvas with x objects in it just to undo a small change and the history contains many usefull informations about what was changed and on which object ect.
Note2: Of course I probably could just canvas.remove(canvas.item(0)) and then canvas.add(history[x].target), however this unfortunately messes up my object stack when there's more than one objects, as canvas.item(1) becomes canvas.item(0) and the reverted change now becomes canvas.item(1) (or 2, 3... ect depending on how many items on the canvas). When I then have like a list of objects displayed depending on their position in the object stack, this get's rearranged and could confuse the user.
This is a simple example.
Given 2 rect on on a canvas, a function will add one back in the middle of those 2, and another will replace the one at position 0.
canvas#insertAt does work as suggested from #gabriele-petroli
var c = new fabric.Canvas('c');
c.add(new fabric.Rect({ fill: 'blue', width: 100, height: 100 }));
c.add(new fabric.Rect({ fill: 'green', left: 150, width: 100, height: 100 }));
var redRect = new fabric.Rect({ fill: 'red', left: 75, width: 100, height: 100 });
var purpleRect = new fabric.Rect({ fill: 'purple', left: 0,
width: 100, height: 100 });
setTimeout(function() {
c.insertAt(purpleRect, 0, true);
c.insertAt(redRect, 1);
}, 1000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.5.0/fabric.min.js"></script>
<canvas id="c" width="500" height="500" ></canvas>
As far as I know it is not possible to overwrite an object.
But this might help for your Note2:
In addition to Gabriele Petriolis comment, you can position the object in the stack after inserting:
Canvas.moveTo()
Canvas.bringToFront()
Canvas.bringForward()
Canvas.sendBackwards()
Canvas.sendToBack()
See: http://fabricjs.com/docs/fabric.Canvas.html
I want to create a class Pixel that will store the position and colors of a given pixel.
Here is my code so far:
<canvas id="kartina" width="500" height="500"></canvas>
<input type="text" id="textField" size="80">
<script>
//pass in coordinates and Canvas context
function Pixel(x,y,ctx){
//assign coordinate properties
this.x=x;
this.y=y;
//get an array with the color data for the pixel
this.pixelData=function(){
return ctx.getImageData(x,y,1,1).data;
};
//assign color properties
this.r=this.pixelData[0];
this.g=this.pixelData[1];
this.b=this.pixelData[2];
//define toString method
this.toString=function(){
var pixelToString= "x: "+this.x+
", y: "+this.y+
", R: "+this.r+
", G: "+this.g+
", B: "+this.b;
return pixelToString;
};
}
//test the class
var canvas=document.getElementById("kartina");
var ctx=canvas.getContext("2d");
var pixel=new Pixel(100,100,ctx);
textField.value=pixel.toString();
</script>
The output from toString() is:
x: 100, y: 100, R: undefined, G: undefined, B: undefined
So I know that the coordinate properties are being assigned correctly, but the pixelData initialization function is not being executed when new Pixel() constructs the instance. I want the object's constructor to call this initialization function; I thought this was the way to do it. How do I set up the constructor here?
Since pixelData is a function, you need to invoke it to get your desired results:
//assign color properties
this.r=this.pixelData()[0];
this.g=this.pixelData()[1];
this.b=this.pixelData()[2];
Or better yet:
var pData = this.pixelData();
this.r=pData[0];
this.g=pData[1];
this.b=pData[2];
You are referencing your this.pixelData() function as if it were an array using [] square brackets.
The function never gets called at all because you are treating it as an array instead of calling the function and then treating the result as an array.
Change this:
this.r=this.pixelData[0];
this.g=this.pixelData[1];
this.b=this.pixelData[2];
To this:
this.r=this.pixelData()[0];
this.g=this.pixelData()[1];
this.b=this.pixelData()[2];
Or to avoid calling it three times:
//assign color properties
var pixelData = this.pixelData()
this.r = pixelData[0];
this.g = pixelData[1];
this.b = pixelData[2];
If I set a variable like this:
var coords = jcrop_api.tellSelect();
It returns my current Jcrop selections coordinates in an x,y,x2,y2,h,w format.
Now if I want to set my coordinates back to that, I could go:
jcrop_api.animateTo(coords)
But the animateTo function only takes an array of 4, [x, y, w, h]
When I try to do the above way, it eventually breaks the code.
So how do I change my variable coords to fit this format?
Thanks
The API functions you mention at least at the 0.9.12 version of the plugin..
jcrop_api.tellSelect() returns an object like this:
{
x: 0,
y: 0,
x2: 10,
y2: 10,
w: 10,
h:10
}
and jcrop_api.animateTo needs one array like [x,y,x2,y2], so, try this:
var c = jcrop_api.tellSelect();
jcrop_api.animateTo([c.x,c.y, c.x2, c.y2]);
in my user.data.crop_position value is "[ 100, 100, 200, 200 ]";
var crop_position=user.data.crop_position.slice(1,user.data.crop_position.length-2);
$('#cropbox').Jcrop({
setSelect: crop_position,
onChange: showPreview,
onSelect: showPreview,
aspectRatio: 1
});
doing this my jcrop is not select at set postion what can i do
it is due to the string i am passing in how can i remove this ,
i know this is silly question but i got these kind of problem many time also please suggest me that in future these kind of problem dont came.
regards
rahul
The Jcrop Manual says that setSelect takes an array, not a string.
[100, 100, 200, 200] // rather than
'[100, 100, 200, 200]'
If you can't change the input format, at least you can parse it using $.parseJSON before passing it to Jcrop:
var crop_position = $.parseJSON(user.data.crop_position);
Edit: If necessary (double quotes are actually present in the string value), you can use $.parseJSON twice, first to decode the encoded string value and second to decode the array within the encoded string:
var crop_position = $.parseJSON($.parseJSON(user.data.crop_position));
Or just strip off the surrounding double quotes before $.parseJSON:
var crop_position = $.parseJSON(user.data.crop_position.slice(1, -1));
setSelect - array [ x, y, x2, y2 ] Set an initial selection area
So you need an array not a string for setSelect. Why don't you make user.data.crop_position an array itself? If there is no way to change the representation you can do the conversion with a simple algorithm:
var pos = '"[ 100, 100, 200, 200 ]"'; // user.data.crop_position
var crop_position = pos.replace(/["\[\] ]/g, '').split(',');
for (var i = crop_position.length; i--;) {
crop_position[i] = +crop_position[i];
}
Now you've got an array of values instead of a string.