I can't copy the transform matrix from one layer to another in paperjs - paperjs

I need to copy the scale and translate properties from one item to another in paperjs.
I've tried using
itemA.copyAttributes(itemB, false)
but this doesn't seem to do anything?
I've also tried
itemA.transform(itemB.matrix)
Which again doesn't work. I can copy the translate using the lines below
itemA.position.x = itemB.position.x
itemA.position.x = itemB.position.x
But I can't figure out how to copy the scale, any ideas

One trick to be able to copy transformations from one item to another is to set item.applyMatrix to false.
This will have the effect of storing item translation, scaling and rotation into properties instead of applied them to its geometry.
You will then be able to apply them to another item.
Here is a sketch demonstrating the solution.
// Create an orange filled square.
var squareA = new Path.Rectangle({
from: view.center - 200,
to: view.center - 100,
fillColor: 'orange',
// Notice that matrix is not applied, this will allow us to copy scaling and rotation later.
applyMatrix: false
});
// Create a blue stroked square by cloning the orange one.
squareB = squareA.clone();
squareB.strokeColor = 'blue';
squareB.fillColor = null;
// Transform the orange square.
squareA.translate(100, 100);
squareA.scale(2);
squareA.rotate(80);
// Replicate transformations to blue stroked square by copying individual values.
squareB.position = squareA.position;
squareB.scaling = squareA.scaling;
squareB.rotation = squareA.rotation;

Related

How would I make a color relative to images in the background?

For example, if you go to Twitter and click on an image, you can see they have a nice color that is close to what you see on the image. I tried looking up ways to achieve this as well as trying to figure it out on my own but no luck. I'm not sure if there's a color: relative property or not.
if you want to use the a colour that exists in your image and set it as a background colour you need to use the canvas element in the following manner:
HTML (this is your image)
<img src="multicolour.jpg" id="mainImage">
JS
window.onload = function() {
// get the body element to set background (this can change dependending of your needs)
let body = document.getElementsByTagName("body")
// get references to the image element that contains the picture you want to match with background
let referenceImage = document.getElementById("mainImage");
// create a canvas element (but don't add it to the page)
let canvas = document.createElement("canvas");
// make the canvas size the same as your image
canvas.width = referenceImage.offsetWidth
canvas.height = referenceImage.offsetHeight
// create the canvas context
let context = canvas.getContext('2d')
// usage your image reference to draw the image in the canvas
context.drawImage(referenceImage,0,0);
// select a random X and Y coordinates inside the drawn image in the canvas
// (you don't have to do this one, but I did to demonstrate the code)
let randomX = Math.floor(Math.random() * (referenceImage.offsetWidth - 1) + 1)
let randomY = Math.floor(Math.random() * (referenceImage.offsetHeight - 1) + 1)
// THIS IS THE MOST IMPORTANT LINE
// getImageData takes 4 arguments: coord x, coord y, sample size w, and sample size h.
// in our case the sample size is going to be of 1 pixel so it retrieves only 1 color
// the method gives you the data object which constains and array with the r, b, g colour data from the selected pixel
let color = context.getImageData(randomX, randomY, 1, 1).data
// use the data to dynamically add a background color extracted from your image
body[0].style.backgroundColor = `rgb(${color[0]},${color[1]},${color[2]})`
}
here is a gif of the code working... hopefully this helps
UPDATE
Here is the code to select two random points and create a css3 background gradient
window.onload = function() {
// get the body element to set background (this can change dependending of your needs)
let body = document.getElementsByTagName("body")
// get references to the image element that contains the picture you want to match with background
let referenceImage = document.getElementById("mainImage");
// create a canvas element (but don't add it to the page)
let canvas = document.createElement("canvas");
// make the canvas size the same as your image
canvas.width = referenceImage.offsetWidth
canvas.height = referenceImage.offsetHeight
// create the canvas context
let context = canvas.getContext('2d')
// usage your image reference to draw the image in the canvas
context.drawImage(referenceImage,0,0);
// select a random X and Y coordinates inside the drawn image in the canvas
// (you don't have to do this one, but I did to demonstrate the code)
let randomX = Math.floor(Math.random() * (referenceImage.offsetWidth - 1) + 1)
let randomY = Math.floor(Math.random() * (referenceImage.offsetHeight - 1) + 1)
// THIS IS THE MOST IMPORTANT LINE
// getImageData takes 4 arguments: coord x, coord y, sample size w, and sample size h.
// in our case the sample size is going to be of 1 pixel so it retrieves only 1 color
// the method gives you the data object which constains and array with the r, b, g colour data from the selected pixel
let colorOne = context.getImageData(randomX, randomY, 1, 1).data
// THE SAME TO OBTAIN ANOTHER pixel data
let randomX2 = Math.floor(Math.random() * (referenceImage.offsetWidth - 1) + 1)
let randomY2 = Math.floor(Math.random() * (referenceImage.offsetHeight - 1) + 1)
let colorTwo = context.getImageData(randomX2, randomY2, 1, 1).data
// use the data to dynamically add a background color extracted from your image
//body[0].style.backgroundColor = `rgb(${allColors[0]},${allColors[1]},${allColors[2]})`
body[0].style.backgroundImage = `linear-gradient(to right, rgb(${colorOne[0]},${colorOne[1]},${colorOne[2]}),rgb(${colorTwo[0]},${colorTwo[1]},${colorTwo[2]}))`;
}
The following are your options.
1. Use an svg.
As far as I know there's no way to have javascript figure out what color is being used in a png and set it as a background color. But you can work the other way around. You can have javascript set the background color and an svg image to be the same color.
See this stackoverflow answer to learn more about modifying svgs with javascript.
2. Use a custom font.
There are fonts out there that provide a bunch of icons instead of letters, you can also create your own font if you feel so inclined to do so. With css you just have to set the font-color of that icon to be the same as the background-color of your other element.
Font Awesome provides a bunch of useful custom icons. If the image you need to use happens to be similar to one of theirs, you can just go with them.
3. Use canvas
If you really want to spend the time to code it up you can use a html <canvas/> element and put the image into it. From there you can inspect certain details about the image like its color, then apply that color to other elements. I won't go into too much detail about using this method as it seems like it's probably overkill for what you're trying to do, but you can read up more about from this stackoverflow answer.
4. Just live with it.
Not a fun solution, but this is usually the option I go with. You simply have to hard-code the color of the image into your css and live with it. If you ever need to modify the color of the image, you have to remember to update your css also.

Dynamically change plane height in babylonjs

I created a plane by using
this.plane = BABYLON.MeshBuilder.CreatePlane("plane", { width: 0.5, height: 10 }, scene, true);
and then I try to modify the plane height in rendering, but the height is not changed.
I think you are looking for scaling. Here is the link to Babylon.js Scaling. Essentially, you do
objectName.scaling.x = 1.50 //This is a scaling multiplier (you can substitute x, y, and z)
//Or, if you want to scale in more than one direction, you can use a vector3
objectName.scaling = new Babylon.Vector3(1.5,.5, 2)
This should let you dynamically change the dimensions of your object. If you wanted the make the change visibly noticeable (instead of jumping straight to the correct size) you could also add an animation to it.

Why is lookAt not looking at specified vector?

I have this three js scene: http://codepen.io/giorgiomartini/pen/ZWLWgX
The scene contains 5 things:
Camera - Not Visible
origen (3D vector) - At 0,0,0.
objOne - Green
objParent - Red
CenterOfscene - Blue
objOne is a child of objParent. And ObjOne looksAt origen, which is a 3d vector at 0,0,0.
But the objOne instead of looking at the 0,0,0. where the origin vector is, It looks at objParent....?
Got any ideas?
What i want is the objOne to look at the 0,0,0. Which is the origen vector.
Any ideas why this is misbehaving? thanks.
THREE.SceneUtils.detach( objOne, objParent, scene );
THREE.SceneUtils.attach( objOne, scene, objParent );
var origen = new THREE.Vector3( 0, 0, 0 );
var render = function () {
objOne.lookAt(origen);
requestAnimationFrame( render );
xOffset += 0.01;
yOffset += 0.011;
zOffset += 0.012;
xOffsetParent += 0.0011;
yOffsetParent += 0.0013;
zOffsetParent += 0.0012;
camXPos = centeredNoise(-1,1,xOffset);
camYPos = centeredNoise(-1,1,yOffset);
camZPos = centeredNoise(-1,1,zOffset);
objOne.position.x = camXPos*4;
objOne.position.y = camYPos*4;
objOne.position.z = camZPos*4;
camParentXPos = centeredNoise(-1,1,xOffsetParent);
camParentYPos = centeredNoise(-1,1,yOffsetParent);
camParentZPos = centeredNoise(-1,1,zOffsetParent);
objParent.position.x = camParentXPos*10;
objParent.position.y = camParentYPos*10;
objParent.position.z = camParentZPos*10;
renderer.render(scene, camera);
};
render();
Object3D.lookAt() does not support objects with rotated and/or translated parent(s).
Your work-around is to (1) add the child as a child of the scene, instead, and (2) replace the child object with a dummy Object3D, which, as a child of the parent object, will move with the parent.
Then, in your render loop,
child.position.setFromMatrixPosition( dummy.matrixWorld );
child.lookAt( origin );
three.js r.75
Here is the corrected codepen:
http://codepen.io/anon/pen/oxGpPQ?editors=0010
Now the green disk rides around its parent (the red sphere) all while looking at the blue disk (or the 'origen' vector).
Uncomment lines 163 and 164 to make the camera be at the green disk's location and have the camera also look at the blue disk ('origen' vector) while it orbits its parent red sphere.
How I accomplished this is:
1. make parent Red Mesh
2. make dummyChild Object3D (this is an invisible math object)
3. make child Green Mesh
4. make origen centerOfScene Blue Mesh
5. attach parent, child, and centerOfScene mesh to Scene (not dummyChild though)
6. attach dummyChild to parent like so: parent.add(dummyChild);
In render function:
1. Move parent around with noise function (which offsets dummyChild)
2. Move dummyChild with another noise function (which revolves around its parent position, the center of dummyChild's world is its red parent's position)
3. Stick the green child mesh wherever the invisible dummyChild is. But since dummyChild is offset by red parent, we need to get it's world coordinates in relation to Scene, not its coordinates in red's world, so we use
child.setFromMatrixPosition(dummyChild.matrixWorld);
Notice its matrixWorld and not matrix - matrix holds its local system and matrixWorld holds its coordinated relative to the Scene or World coordinate system.
4. Use lookAt to make the green child disk 'lookAt' the blue centerOfScene Mesh which is at the origen vector or the center of the Scene.
Hope this helps! :)

zIndex doesn't change z order for circles with Google Maps API

Pardon my noobishness, but, although I've seen this issue discussed, I haven't found an answer. I am trying to draw concentric circles on a Google Map using the API v3, making each clickable as on a bullseye target, but always the largest one ends up on top, which means it is the only clickable one.
The following uses an array called "subjects" that consists of increasing radii and various fillcolors.
for (i=0;i<subjects.length;i++) {
radi = subjects[i][0];
fillcolr = subjects[i][1];
zindx = subjects.length - i;
newcircle = new google.maps.Circle({
radius: radi,
center: centerPoint,
strokeWidth: 1,
fillOpacity: 1.0,
fillColor: fillcolr,
zIndex: zindx
});
// display it
newcircle.setMap(map);
// make outer circle clickable
google.maps.event.addListener(newcircle, 'click', function() {
circleClickedInfo(i);
});
The circles are there, the zIndex is set, but the biggest circle is always on top. I have tried setting zIndex on a pass afterwards, boosting each zIndex by 10000, reversing the order in which I create the circles, not setting the zIndex explicitly, etc. I'm sure I am missing something obvious (see the aforementioned noobishness), but I can't figure out what it is. TIA for any pointers...
Try this for every shape you need:
selectedShape.setOptions({zIndex:0});

Rotate a drawn rectangle in flex

i wrote the following code for drawing a rotate rectangle
var s:UIComponent = new UIComponent();
s.graphics.lineStyle(1, 0x0000FF);
s.graphics.drawRect(50, 50, 200, 200);
s.rotation = 30;
template.addChild(s);
where template is a canvas. Its rotate nicely but the problem is the position is not in right place. i.e. it is not in (50,50) after rotate. How can i solve this problem?
Thanks in advance.
What you're seeing is the default rotation around the origin in Flex (in your case the X,Y coordinates of 50,50) I am assuming that you want to rotate around the center (as I recently had to do). There is the jury rig way to do it, by adjusting the origin point based on rotation angle. Then there is the rotate effect:
import mx.effects.Rotate;
var s:UIComponent = new UIComponent();
var rotator:Rotate = new Rotate(s);
s.graphics.lineStyle(1, 0x0000FF);
s.graphics.drawRect(50, 50, 200, 200);
rotator.angleFrom = 0;
rotator.angleTo = 30;
rotator.originX = s.width/2;
rotator.originY = s.height/2;
template.addChild(s);
rotator.play();
Now I've noticed some problems with this that required me to set the width and height of the rotated object again after the play() method, but other than that I get the ideal rotation situation.
Another downside to this is that it's an effect, which means it visually rotates the object. I will post back when I correct that, if you don't want to see the object rotate.
The Answer is duration
just by adding rotator.duration = 1 before play it happens so quick the user won't see it. 1 being 1 millisecond. I tried 0, but that resulted in no rotation occurring. Obviously if you want to see the effect in action you can increase that length of time by using any value in milliseconds.

Resources