Check if rotation of model has changed? - javascript

How would you check if the rotation of a model has changed?
tried:
var oldRotate = this._target.quaternion;
console.log('works returns vector3 quaternion: ', oldRotate);
var newRotate = oldRotate;
if (oldRotate != newRotate) {
console.log('this isnt triggering');
}
this doesn't work and yes it's in a 'loop'
also tried:
var oldRotation = new THREE.Vector3();
oldRotation.copy(controlObject.quaternion);
controlObject.position.copy(pos);
this._position.copy(pos);
this._parent.SetPosition(this._position);
this._parent.SetQuaternion(this._target.quaternion);
var newRotation = new THREE.Vector3();
newRotation.copy(controlObject.quaternion);
console.log(oldRotation.equals(newRotation));
any ideas?

You can't compare objects for equality using the ==/!= operator. This will merely compare the references to the objects, not their values. You will need to compare using the .equals method.
Also, in your example, you're assigning oldR to newRotate directly. I'm not sure if you've not included some intervening code. Either way, you should also be using .clone otherwise the != will never happen.
See: https://threejs.org/docs/#api/en/math/Quaternion for information about the clone and equals methods.

Related

Pass object and properties by reference in Javascript

I've seen lots of questions about passing objects by reference in Javascript, but not the object and properties by reference. Is it possible?
Right now I only found a way to do it by going through some type of logic like this, which is terribly inconvenient:
let multipliers = {
none:1,
sin:2,
cos:3,
tan:4,
atan:5,
}
incMultiplier(shapesMovements[index], "rotation", "x", "sin")
function incMultiplier(shapeMovement, kind, dimension, multiplier){
var numOfKeys = Object.keys(multipliers).length;
if(kind === "rotation"){
if(dimension === "x"){
if(multiplier === "sin"){
if(shapeMovement.rotation.x.multiplier !== numOfKeys){
shapeMovement.rotation.x.multiplier += 1
}else{
shapeMovement.rotation.x.multiplier = 1
}
}
}
}
}
I'd just like to increase the property value by one with whatever object and property I've thrown into that function.
I've seen another post where you can pass parameters, but this looks to assemble a new object, and is not by reference. I need to actually edit the values on the object's properties.
Originally, this is what I was trying, and it did not seem to alter the object on a global level. Only locally to the function:
incMultiplier(shapesMovements[index].rotation.x.multiplier)
function incMultiplier(multiplier){
var numOfKeys = Object.keys(multipliers).length;
if(multiplier !== numOfKeys){
multiplier = multiplier + 1
}else{
multiplier = 1
}
// always results in the same number.
// Does not keep increasing every time the function is called.
console.log(multiplier);
}
Originally, this is what I was trying
You're not passing an object with its properties there. You're passing the value of a single property, and assignments to multiplier do indeed just overwrite the local variable in the function. You need to pass an object and explicitly assign to its property:
function incMultiplier(valueObj) {
var numOfKeys = Object.keys(multipliers).length;
if (valueObj.multiplier !== numOfKeys) {
valueObj.multiplier++;
} else {
valueObj.multiplier = 1
}
}
incMultiplier(shapesMovements[index].rotation.x)
incMultiplier(shapesMovements[index].position.x)
incMultiplier(shapesMovements[index].rotation.y)
incMultiplier(shapesMovements[index].rotation.z)
It's not necessary to pass the whole shapesMovements objects and everything nested within them, passing a single mutable object is enough.

How can I compare a string to an object key and get that key's value?

I want to do something relatively simple, I think anyways.
I need to compare the pathname of page with an object's kv pairs. For example:
if("pathname" === "key"){return value;}
That's pretty much it. I'm not sure how to do it in either regular Javascript or jQuery. Either are acceptable.
You can see my fiddle here: http://jsfiddle.net/lz430/2rhds1x3/
JavaScript:
var pageID = "/electrical-electronic-tape/c/864";
var pageList = [{
"/electrical-electronic-tape/c/864": "ElectronicTape",
"/industrial-tape/c/889": "IndustrialTape",
"/sandblasting-tape/c/900": "SandblastingTape",
"/Foam-Tape/c/875": "FoamTape",
"/double-coated-d-c-dhesive-tape/c/872": "DCTape",
"/Adhesive-Transfer-Tape/c/919": "ATTape",
"/Reflective-Tape/c/884": "ReflectiveTape",
"/custom-moulding": "CustomMoulding",
"/request-a-quote": "RequestQuote"
}];
var label = pageID in pageList;
$('.el').html(label);
First, your "pageList" should just be a plain object, not an object in an array:
var pageList = {
"/electrical-electronic-tape/c/864": "ElectronicTape",
"/industrial-tape/c/889": "IndustrialTape",
"/sandblasting-tape/c/900": "SandblastingTape",
"/Foam-Tape/c/875": "FoamTape",
"/double-coated-d-c-dhesive-tape/c/872": "DCTape",
"/Adhesive-Transfer-Tape/c/919": "ATTape",
"/Reflective-Tape/c/884": "ReflectiveTape",
"/custom-moulding": "CustomMoulding",
"/request-a-quote": "RequestQuote"
};
Then you can set "label" to the value from the mapping:
var label = pageList[pageID] || "(not found)";
That last bit of the statement above will set the label to "(not found)" if the lookup fails, which may or may not be applicable to your situation.
It depends kinda on the logic you want to implement. If you want to say "if object has the key, then do X, and if not, then do Y", then you handle that differently than "set label to the object's key's value if the key is there, or else set it to undefined or something else".
For the first case you do:
if (pageList.hasOwnProperty(pageID) ) {
label = pageList[pageID];
}
else {
// do whatever, maybe some error?
}
For the second case, you can just say
var label = pageList[pageID] || 'notFound';
As indicated by #Pointy, either get rid of the array or subsiture pageList[0] for pageList and pageList[0][pageID] for pageList[pageID] above, if you need to keep the array.

Raphael: Chaining ".data" to a raphael.js element

I'm having trouble chaining ".data" to a raphael.js element.
When I try to retrieve the data later, I get "undefined".
Here's my fiddle: http://jsfiddle.net/HkNgT/9/
//Draw:
paper.circle(circleCenterX, circleCenterY, circleCenterRadius)
.attr({'fill':'blue', 'stroke':'red', 'stroke-width':2, 'opacity': 0.8})
.data({"circleCenterX":circleCenterX,
"circleCenterY":circleCenterY,
"boxYPosition":boxYPosition,
"boxXPosition":boxXPosition})
.id = name+"-circle";
//Output:
console.log("data is = ", paper.getById(name+"-circle").data("circleCenterX"));
With this code, the ".data(...)" part just doesn't work.
When I try to retrieve it (with paper.getById), it displays "data is = undefined".
Other ways that I have tried:
//Doesn't work
paper.circle....
.data("circleCenterX",circleCenterX)
.data("circleCenterY",circleCenterY)
.data("boxYPosition",boxYPosition)
.data("boxXPosition",boxXPosition);
And another:
//Doesn't work
var c = paper.circle....;
c.data("circleCenterX",circleCenterX);
c.data("circleCenterY",circleCenterY);
c.data("boxYPosition",boxYPosition);
c.data("boxXPosition",boxXPosition);
And another:
//DOES work, but gives me huge performance losses
paper.circle....;
paper.getById(name+"-circle").data("circleCenterX",circleCenterX);
paper.getById(name+"-circle").data("circleCenterY",circleCenterY);
paper.getById(name+"-circle").data("boxYPosition",boxYPosition);
paper.getById(name+"-circle").data("boxXPosition",boxXPosition);
Any help?
So, just trying to help, I've never used raphael before. I assume you're trying to retrieve the circleCenterX value?
Inspecting the data function, it looks as though it's only used for setting the value. (It only returns a value, if you're setting a value).
function (b,c){
var d = bb[this.id] = bb[this.id] || {};
if(arguments.length==1){
if(a.is(b,"object")){
for(var e in b)b[g](e)&&this.data(e,b[e]);
return this
}
eve("raphael.data.get."+this.id,this,d[b],b);
return d[b]
}
d[b]=c,eve("raphael.data.set."+this.id,this,c,b);
return this
}
(Afaict, eve is an Event framework, bundled with Raphael. Anyone know where the data goes from here?)
So this isn't going to help.
Inspecting the circle object, I was able to see/pull out a cx value, which I assume is the circleCenterX value that you're looking for...
var circ = paper.getById(name+"-circle");
console.log("baseVal is = ", circ[0].cx.baseVal.value);
console.log("animVal is = ", circ[0].cx.animVal.value);
Gives
baseVal is = 100
animVal is = 100
Is this what you're looking for?

Add another value to nested javascript object?

I have the following JavaScript object, with a property called rates, which contains another object with the actual rates. Now I want to add a new rate "CAD":0.972254 to the rates. How can I add this one value to the list?
var Currency = {
rates: {"USD":1.0,"EUR":1.3497,"GBP":1.60403},
convert: function(amount, from, to) {
return (amount * this.rates[from]) / this.rates[to];
}
};
You can do it either way
Currency['rates']['CAD'] = 0.972254;
Or,
Currency.rates.CAD = 0.972254
Fiddle Here
You can assign a new property to existing object like:
Currency.rates.CAD = 0.972254
Currency.rates.CAD = 0.972254;

How to translate prototype's $A() function into jquery?

I'm trying to translate Brandon Kelly's AC.VR class (Prototype) into a jQuery plugin.
Here is a link to his example (unfortunately just working in Safari).
I managed to get the basics working. The problem I'm having is the mouse event history for the velocity, acceleration and friction part of the script.
Here is a shorten extract of his Prototype code:
.
.
.
makeInteractive: function(){
this.bindGrabStart = this.onGrabStart.bind(this);
this.bindGrabChange = this.onGrabChange.bind(this);
this.bindGrabEnd = this.onGrabEnd.bind(this);
},
onGrabStart: function(event){
this.grabHistory = $A([ event ]);
this.grabHistoryInterval = setInterval(this.updateGrabHistory.bind(this), 10);
},
onGrabChange: function(event){
this.onGrabChange.clientX = event.clientX;
this.onGrabChange.clientY = event.clientY;
},
updateGrabHistory: function(){
var func = this.onGrabChange.clientX ? this.onGrabChange : this.onGrabStart;
this.grabHistory.unshift({ clientX: func.clientX, clientY: func.clientY });
if (this.grabHistory.length > 3) {
this.grabHistory.splice(3);
}
},
.
.
.
and here is my jQuery translation:
.
.
.
var makeInteractive = function(){
$(document).bind("mousedown", function(event) { obj.onGrabStart(event) }, false);
$(document).bind("mousemove", function(event) { obj.onGrabChange(event) }, false);
$(document).bind("mouseup", function(event) { obj.onGrabEnd(event) }, false);
}
this.onGrabStart = function(event){
???
}
this.onGrabChange = function(event){
this.onGrabChange.clientX = event.clientX;
this.onGrabChange.clientY = event.clientY;
};
this.updateGrabHistory = function(event){
var func = this.onGrabChange.clientX ? this.onGrabChange : this.onGrabStart;
this.grabHistory.filter({ clientX: func.clientX, clientY: func.clientY });
if (this.grabHistory.length > 3) {
this.grabHistory.splice(3);
}
};
.
.
.
Basically the question is: How can I deal with the grabHistory (array object ?) in jQuery?
This line confuses me most:
this.grabHistory = $A([ event ]);
I just found this page which explains a bit about the $A function:
http://www.learn-javascript-tutorial.com/PrototypeJS.cfm#Dollar_A_Function
I'm grateful for every advice.
The line that confuses you more, is actually using $A where isn't needed, it can be removed safely:
this.grabHistory = [event];
$A is a helper function to produce a real array from an array-like object such a DOMCollection, or an arguments object for example.
The expression $A([event]) is simply redundant, since you are actually constructing a real array, which has one element, the event object -the literal [event] does that-.
The term array-like means an object that contains numeric properties and a length property, but is not really an array - it doesn't inherit the methods from Array.prototype -.
Anyway, the implementation of the $A function is quite simple (you can see the actual PrototypeJS implementation here):
function toArray(obj) {
var array = [];
// iterate backwards ensuring that length is an UInt32
for (var i = obj.length >>> 0; i--;) {
array[i] = obj[i];
}
return array;
}
The official documentation says:
$A
$A(iterable) → actualArray
Accepts an array-like collection (anything with numeric indices) and returns its equivalent as an actual Array object. This method is a convenience alias of Array.from, but is the preferred way of casting to an Array.
The primary use of $A is to obtain an actual Array object based on anything that could pass as an array (e.g. the NodeList or HTMLCollection objects returned by numerous DOM methods, or the predefined arguments reference within your functions).
The reason you would want an actual Array is simple: Prototype extends Array to equip it with numerous extra methods, and also mixes in the Enumerable module, which brings in another boatload of nifty methods. Therefore, in Prototype, actual Arrays trump any other collection type you might otherwise get.
This sounds like a very Prototype specific usage, which is probably unnecessary to translate 1:1 to jQuery. In jQuery the jQuery object itself holds all the powerful methods and the difference between array-like collections and Array-instances is usually not important.

Categories

Resources