get class from circle element - meteor

I'm using d3 to render circles that represent each of the elements in my database. Each circle ends up looking something like this:
<circle r="8" fill="#585858" stroke="#008db7" stroke-width="3" id="Node;R6AnePqKecNNe7dkr" class="R6AnePqKecNNe7dkr"></circle>
I can use the following to return "success" when any of the circles are clicked:
Template.tree.events({
'click circle': function(){
console.log("success")
}
});
but instead of "success" I'd like to return the class of the circle that was clicked.
If I console.log(this) I get 'Object {}' so my instinct tells me to use this.class but that doesn't return anything.

found in the answers here the following code solves the problem
Template.tree.events({
'click circle': function(e){
console.log(e.currentTarget.getAttribute('class'))
}
});

Related

animating a custom attribute in a custom component

I am attempting to animate a material property that is buried inside of a gltf-model (that has many objects). I can find the parameter and animate it with a tick event, and it looks like this
https://glitch.com/~uv-reveal-wave
It almost works, but animating with formulas is a nightmare. Instead I want to control it with the animation component. Unfortunately, exposing the parameter directly seems impossible, as I have to use getObject3D.traverse() just to locate the object, and then get the parameter.
Instead I have made a custom attribute (in schema) and and animating that attribute. And in the update function, I'm using that attribute to drive the buried parameter. It should work, but I can't seem to get a response in the update function. Iow, my custom attribute is not animating.
AFRAME.registerComponent('matclipplane', { // attached to gltf-model tree
schema:{
clipHeightA:{type: 'number', default: 0}
},
init: function () {
let el = this.el;
let comp = this;
comp.treeModels = [];
el.addEventListener('model-loaded', function(ev){
let mesh = el.getObject3D('mesh');
mesh.traverse(function(node){
if (node.isMesh){
comp.treeModels.push(node);
}
comp.modelLoaded = true;
});
...
update: function(){
console.log("update"); // returns nothing. no update from
animating attributes clipHeightA
let comp = this;
if (comp.modelLoaded){
comp.treeModels[1].material.map.offset.y =
this.data.clipHeightA;
}
}
...
AFRAME.registerComponent("click-listener", { // attached to box button
schema:{
dir:{type:"boolean", default: false}
},
init: function(){
let el=this.el;
let data = this.data;
el.addEventListener("click", function(evt){
let tree = document.querySelector('#tree');
data.dir = !data.dir;
if(data.dir){
el.setAttribute("material",'color', 'orange');
tree.emit("grow");
} else {
el.setAttribute('material','color','#332211');
tree.emit('shrink');
}
});
}
});
<a-entity id="tree" gltf-model="#tree" scale="5 5 5"
animation__grow="property: clipHeightA; from: 0; to: 1;
startEvents: grow; dur: 500"
matclipplane></a-entity>
<a-entity id="button" geometry="primitive: box" material="color:orange;
metalness: 0.5" scale="0.2 0.2 0.2" class="clickable" click-listener></a-
entity>
<a-entity id="mouseCursor" cursor="rayOrigin: mouse" raycaster="objects:
.clickable"></a-entity>
here is the glitch in progress
https://glitch.com/~uv-reveal
Clicking on the orange cube should launch the uv reveal animation. I expect that calling a custom component attribute should trigger an update event, but the update does not log in the console.
Not sure how to animate a parameter inside a gltf.
Do I have to implement the animejs component directly inside my custom component?
Or can this be done with the animate component?
According to the docs you can animate properties through
object3D like animation="property: object3D.x"
components like animation="property: components.myComp.myProp"
I don't see it mentioned (although it's used in the docs) but it also works when you provide the property as the components attribute:
animation__grow="property: matclipplane.clipHeightA;"
glitch here. You can see update is being called.
Also tree was an id of both the asset and the component, therefore grow was emitted on the asset item.

In created:, my method doesn't work perfectly

I'm trying to make a simple vue.js & d3.js code. In the code, I want to plot some charts. For that, I'm trying to make some spaces for charts, by defining a method('add_svg') and run the method in created.
But, the method('add_svg') doesn't work what i intended. I had checked that the method was working, by inserting console.log('Running') for the first part of the method.
I could saw the message, 'Running', but the svg_space, i wanted to insert, wasn't inserted.
But when I UPDATE charts with same method in computed: part, it works.
In the computed: part, it generates some spaces several times, which means that it's working and the method has no problem.
Why is that?
Below is my code:
// GIVES CONSOLE.LOG MESSAGE('RUNNING') BUT DOES NOT APPEND SVG
created () {
console.log("")
this.add_svg() // append svg for chart
this.plot([0, 0]) // basic plot with value = [0, 0]
},
...
// SAME METHOD, BUT IN HERE, IT GIVES ME WHAT I WANTED.
// BUT TO INITIALIZE, I WANT TO RUN THE METHOD IN created: part, not in computed
computed () {
this.add_svg()
this.plot( datum )
}
...
methods: {
add_svg: function () {
console.log("Adding some space for chart")
d3.select('.chart_test2')
.append('svg')
.attr('class', 'svg_chart_test2')
.attr('width', '10px')
.attr('height', '10px')
},
other methods...
}
In Vue, you have to draw d3 charts on the mounted hook, rather than the created hook. You can't draw the chart if the page is not rendered - which is what happens when you use the created hook.
mounted () {
this.add_svg() // append svg for chart
this.plot([0, 0]) // basic plot with value = [0, 0]
}

reference to normalMap in material returning undefined

I am attempting to make a simple demo, using dat.GUI to manipulate a material on an Aframe primitive . On the entity tag, I create a material, an assign a texture to the normal slot.
<a-entity id="circle" geometry="primitive:circle; radius: 2; segments: 96"
rotation="-90 0 0"
material="color: #335500; transparent: true; opacity: 0.9;
normalMap: #watertex; side: double"
water ></a-entity>
Then, in a custom component, I access its THREEjs mesh and material.
I am able to get a reference to the material, but when I try to access the normalMap, it returns undefined.
I added a listener, to wait for the "loaded" event. I am not using gltf, so "model-loaded" is unnecessary.
I used getObject3D("mesh"), and traversed the mesh, but still, the normal map still returns undefined. The puzzling part is that in the console, I log the material, and can clearly see the normalMap. But when log it, it returns undefined.
AFRAME.registerComponent("water",{
init: function(){
let el = this.el;
//console.log(el);
let comp = this;
this.counter=0;
el.addEventListener("loaded", function(ev){
console.log('model loaded');
let mesh = el.getObject3D('mesh');
if (!mesh){return;}
mesh.traverse(function(node){
if (node.isMesh){
console.log(node);
console.log(node.material);
console.log(node.material.normalMap); <-- returns
undefined
}
});
});
},
});
<a-entity id="circle" geometry="primitive:circle; radius: 2; segments: 96"
rotation="-90 0 0"
material="color: #335500; transparent: true; opacity: 0.9;
normalMap: #watertex; side: double"
water ></a-entity>
I am surprised that a reference to a material shows the normal map
console.log(node.material);
but a direct reference to the normal map fails
console.log(node.material.normalMap);
I suspect that perhaps something is strange with texture maps made with aframe not being accessible from Threejs, but I don't know why or how to test this.
Ultimately I want to use datGUI to control params in the materials.
I notice that AFrame material component does not expose all the parameters of threejs materials. Also accessing some aframe material parameters with datGUI seem a bit buggy. So this is why I want to access threejs directly.
Here is a link to the project on my server, where you can see the console logs.
http://sensorium.love/experiments/demos/water/waterDemo1.html
and here is a glitch if you want to play with the code
https://glitch.com/~water-demo
It seems to be a race, where you try to access the normalMap just before it's applied.
There is a materialtextureloaded event (docs) which seems to do the trick:
el.addEventListener('materialtextureloaded', e => {
// nomalMap is accessible here
})
Otherwise you can also use a timeout or interval to determine when the normalMap isn't null.
I've seen ar.js do:
let timer = setInterval(e => {
if (!someVal) return;
clearInterval(timer);
// here someVal isn't null or undefined
}, 500)
Glitch here.
I'm pretty sure you could see the normalMap in the console, because the expression gets evaluated once you click the arrow in the browser console. On chrome there's a blue "i" which says "value below was evaluated just now".

How does one link an image to a VR URL using a-frame?

I have seen several examples that fall short of a simple linked image using aframe. The closest I found was a link-traversal example at https://github.com/aframevr/aframe/blob/master/examples/showcase/link-traversal/index.html, however that does not work on the Oculus Go (guessing because it is more complex than needed) and images are not being used to link. I would settle for the non-image links, but even then images are not showing in the circle and when clicked in VR I am taken out of VR mode. I am surprise something as simple as a image-based weblink is so difficult using a-frame. Perhaps I am missing something simple? Thank you.
You can check out the link's source code, utilizing the "link" part
window.location = this.data.url;
and throw it into an a-frame component:
AFRAME.registerComponent("weblink", {
schema: {
url: {
default: ""
}
},
init: function() {
this.el.addEventListener("click", (e) => {
window.location = this.data.url;
})
}
})
on click - change the window location to the desired url. Throw it on any aframe entity:
<a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9"
weblink="url: https://google.com"></a-box>
Fiddle here, although you need to copy the code elsewhere since jsfiddle won't allow changing the window.location to another origin.

How to tween entrance/exit with Meteor?

With the Meteor library, it handles the "reactive"/"two way binding" interaction styles quite well, if using their (Spacebars) template to generate HTML. However, I'm wanting to do some animated entrances/exits when data changes, and having difficulty getting that to work.
The use case is I have a dashboard gauge widget rendered as an SVG element. When the data driving the gauge updates, I want the needle to animate to its new position, not just snap there.
To have the needle just snap to the new position, I can do something like:
template.html
<template name="gauge">
<svg>
<path id="needle" {{ needleAttrs }} d="..." />
</svg>
</template>
client.js
Template.gauge.helpers({
needleAttrs: function() {
return {
x: 50,
y: MyCollection.findOne().needleValue
};
}
});
This is effectively the same technique used by the SVG clock example that comes with Meteor.
But how can I transition that animation? I was thinking about pushing the new value from the collection into the Session collection such that a separate animate() method could find it, and some use of Tracker.autorun() to make it Reactive, but I haven't been able to get it to trigger properly.

Resources