snap.svg save element and paste it to another - javascript

I create some lines in my Paper:
var svg = Snap("#svg_container");
var linesContainer = {};
var line = svg.line( 0, 0, 200, 200).attr(...);
linesContainer[someID] = line;
then i clear the Snap / create a new. I want to have the stored object also in my new snap:
svg = Snap("#svg_container");
svg.clear();
//something like:
//svg.append(linesContainer[someID]);
is this possible?

Here script with using SnapSVG.
var linesContainer = []; // not {}
lineContainer[linesContainer.length] = svg.line( 0, 0, 200, 200).attr(...);
// or 2nd way .. u can definitely make objects with value x,y, attrs and store them, but it helps reducing a storage of using memory.
U can put line to svg like that.
svg = Snap("#svg_container");
svg.clear();
for(i=0;i<lineContainer.length;i++)
svg.add(lineContainer[i]);

Related

creating array of paragraph in javascript

I'm drawing data in a JS canvas. I need to enter the veritcal and horizontal axis values at fix intervals.
I would ask how to create an array of paragraph or text to assign an absolute coordinate and the right axis value to draw them around the canvas.
currently I created and edited line by line:
document.getElementById('percent0').innerHTML =
a.toFixed(5-Math.round(Math.log10(a)));
a = minVal+(maxVal-minVal)*0.25;
document.getElementById('percent25').innerHTML =
a.toFixed(5-Math.round(Math.log10(a)));
a = minVal+(maxVal-minVal)*0.5;
document.getElementById('percent50').innerHTML =
a.toFixed(5-Math.round(Math.log10(a)));
a = minVal+(maxVal-minVal)*0.75;
document.getElementById('percent75').innerHTML =
a.toFixed(5-Math.round(Math.log10(a)));
a = minVal+(maxVal-minVal)*1;
document.getElementById('percent100').innerHTML =
a.toFixed(5-Math.round(Math.log10(a)));
but I would like to use a smart way to do it with array if possible.
thks.
Just add mark values to array and use it where it changes:
const marks = [0, 25, 50, 75, 100};
marks.forEach(mark => {
const a = minVal+(maxVal-minVal)*mark / 100.0;
document.getElementById('percent' + mark).innerHTML =
a.toFixed(5-Math.round(Math.log10(a)));
});
If you want to create those html elements with code too you can simple have something like <div id="marks-container;></div> in your HTML and then add all paragraps with JS too -
const p = document.createElement('p');
p.id = "percent" + mark;
document.querySelector("#marks-container").appendChild(p);

Combine several imageData structures into one canvas

I'm using Konvajs framework to work with canvas. I need to create three shapes (slots) and make some manipulations. It works but also I need to work with pixels, I get image via getImageData, store it in internal structure then use for manipulation.
var c = this.layer.getCanvas();
var ctx = c.getContext();
this.slots[name].data = ctx.getImageData(0, 0, this.stage.getWidth(), this.stage.getHeight());
when the job is done, I want to combine those imageData structures into one but I can't. Using this answer I try to do it, but always get:
konva.min.js:29 Uncaught TypeError: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The provided value is not of type '(HTMLImageElement or HTMLVideoElement or HTMLCanvasElement or ImageBitmap)'
This is my snippet of code:
var c = layer.getCanvas();
var ctx = c.getContext();
for (var slot_name in this.slots) {
console.log('Slot', slot_name);
var slot_data = this.slots[slot_name].data;
var c2 = layer.getCanvas();
var ctx2 = c2.getContext();
ctx2.putImageData(slot_data, 0, 0);
ctx.drawImage(c2, 0, 0);
}
var imageData3 = c.toDataURL({pixelRatio: 1});
zip.file('scene.png', imageData3.substr(imageData3.indexOf(',') + 1), {base64: true});
Where is my mistake?
UPDATE:
changed line:
ctx.drawImage(c2, 0, 0);
to:
ctx.drawImage(c2._canvas, 0, 0);
and canvas saves but I see only the last saved picture. Why?
var c2 = layer.getCanvas(); - canvas here is not native canvas, it is Konva wrapper. So you have an error why you are trying to draw it.
To get reference to native canvas you can use: var c2 = layer.getCanvas()._canvas;.

How to connect objects with Bezier-like curves using Paper.js

I have a web app prototype where nodes similar to Blender shader editor are connected to each other. I am using Paper.js framework
I want them to be connected using those smooth Bezier-like curves. So I have 2 shapes and I can connect them by making a straight line, but now I want to have handles at the endpoints that smooth these objects out, kinda like this:
So 2 handles on endpoints, pointing horizontally for half the bounding box of the path.
The problem is I can't figure out how to add and edit those handles using Paper.js
The code I have is this:
function makeRectangle(topLeft, size, cornerSize, colour){
var rectangle = new Rectangle(topLeft, size);
var cornerSize = cornerSize;
var path = new Path.RoundRectangle(rectangle, cornerSize);
path.fillColor = colour;
return path;
}
var xy1 = new Point(50,50); //Position of 1st rectangle.
var size = new Size(100, 80); //Size
var c = new Size(8,8); //Corner radius
var col = "#167ee5"; //Colour
var r1 = makeRectangle(xy1, size, c, col); //Make first rectangle
var xy2 = new Point(467,310); //Position of second rectangle
var size2 = new Size(115, 70); //Size of second rectangle
var r2 = makeRectangle(xy2, size2, c, col); //Make secont rectangle
var r1cent = r1.bounds.center; //Get the center points, they will be used as endpoints for the curve.
var r2cent = r2.bounds.center;
var connector = new Path(r1cent, r2cent); //Ok so I made this path... Now what? How do access and edit the handlers at endpoints like in the image?
connector.strokeColor = 'black'; //Give it some colour so we can see it.
You can paste all this code here without any setup, it's a good way to test the framework.
You can use Segment objects when defining the connector rather than using Points (or you can set the handleIn and handleOut properties after creating the path).
The doc is here: Segment
And here is a sketch showing how to use handleIn and handleOut with your code:
sketch.paperjs.org solution

unable to applyMatrix in three.js

I am trying to run an animation from a JSON file. I am using a custom JSON loader, (i.e. not the one included with three.js).
So I have an object named frames, which contain many frames, all of them have shape information, and a simulation_matrix, which contains data required for animation in the form of a 4by4 transformation matrix(generated from a python script).
So I am using this code for animation ..
and this is a sample JSON script to load.
// This method is for adding static shapes
// This works perfectly fine ..
parent.add_shape = function(frame)
{
var material = new THREE.MeshLambertMaterial({
color: frame.shape.color,
wireframe: true,
wireframeLinewidth: 0.1,
opacity: 0.5
})
var geometry = new THREE.CylinderGeometry(frame.shape.radius,frame.shape.radius,frame.shape.height,50,50);
// mesh_dict dictionary maps a mesh(shape) to its frame
parent.mesh_dict[frame] = new THREE.Mesh(geometry,material);
var init_orientation = frame.simulation_matrix[0];
var orienter = new THREE.Matrix4();
orienter.elements = [];
//Since simulation_matrix is generated from python, it is a
// list of lists, We need to push it to the elemens of Matrix4 manually ..
for(var i in init_orientation)
{
for(var j in init_orientation[i])
{
orienter.elements.push(init_orientation[i][j]) ;
}
}
parent.mesh_dict[frame].applyMatrix(new THREE.Matrix4());
parent.mesh_dict[frame].applyMatrix(orienter);
parent.scene.add(parent.mesh_dict[frame]);
parent.renderer.render(parent.scene,parent.camera);
}
// This method basically takes the meshes defined in add_shape, and
// applies simulation matrix to it, and requests animation frame for
// animation.
parent.animate = function()
{
for(var frame in JSONObj.frames)
{
// defining simulation_matrix in a var.
var matrix = JSONObj.frames[frame].simulation_matrix[parent.animation_counter];
var animation_matrix = new THREE.Matrix4();
animation_matrix.elements = [];
// pushing it to a Matrix4
for(var i in matrix)
{
for(var j in matrix[i])
{
animation_matrix.elements.push(matrix[i][j]) ;
}
}
console.log(animation_matrix);
console.log(animation_matrix.elements);
// Making sure we are not applying matrix to the earlier transform
//mesh_dict is a dictionary of meshes, used in creating shapes,mapped to the
//frame which contains them
parent.mesh_dict[JSONObj.frames[frame]].applyMatrix(new THREE.Matrix4());
// now applying transform, after setting to identity matrix ...
parent.mesh_dict[JSONObj.frames[frame]].applyMatrix(animation_matrix);
}
console.log(parent.animation_counter);
//update timestep ...
parent.animation_counter++;
// This is to loop over again and again ...
// assuming 10 animations frames
if(parent.animation_counter == 10){ parent.animation_counter = 0; }
requestAnimationFrame(parent.animate);
}
The problem is that I am able to create the multiple shapes, but when I apply simulation matrix to them in the loop, only one of them is animating, that too in very unexpected manner.
Well I have figured out what was wrong. Somehow, all the dictionary parent.mesh_dict[] keys were mapped to a same single object, instead of all objects as required. Now I debugged it, and it is working like a charm. Also your point is valid #WestLangley, as I now use mesh.matrix.identity() to get things done. Thanks, I will close this question now.

Raphael.js newbie question: how to create a rectangular and lines as ONE object?

In raphael, if I want to render the following shape:
I have to do something like:
var paper = Raphael("notepad", 320, 200);
var rect = paper.rect(...);
var line1 = paper.path(...);
var line2 = paper.path(...);
which create three elements: rect, line1, line2.
BUT, I would like to treat the rendered shape as one object in other js code insteand of three. In Raphael, how can I create this shape which returns me just one object not three?
You want to create a set.
Creates array-like object to keep and operate couple of elements at once. Warning: it doesn't create any elements for itself in the page.
var st = paper.set();
st.push(
paper.circle(10, 10, 5),
paper.circle(30, 10, 5)
);
st.attr({fill: "red"});
Your code would look something like this:
var paper = Raphael("notepad", 320, 200),
st = paper.set();
st.push(
paper.rect(...),
paper.path(...),
paper.path(...)
);
// use st elsewhere
Edit
How can I access individual element in the set then?
You can grab references to the objects before you add them to the set:
var paper = Raphael("notepad", 320, 200),
st = paper.set(),
rect1 = paper.rect(...),
path1 = paper.path(...),
path2 = paper.path(...);
st.push(rect1, path1, path2);
I'm not 100% sure, but since the docs say that a set is "array-like," then you should also be able to access elements in the set using array index notation:
var i, elt;
for (i=0; i<st.length; i++)
{
elt = st[i];
// do stuff with elt
}

Categories

Resources