Why doesn't my custom component update when I change properties with setAttribute? - aframe

I think I don't quite understand how components and entities work.
I'm using the box component that appears in the a-frame help (https://aframe.io/docs/1.3.0/introduction/writing-a-component.html#example-box-component), and I want to modify a property. When doing so, I thought that the update would be activated but it does nothing. In fact the oldData is always empty and never enters in the update option (except for the first time):
<script>
AFRAME.registerComponent("box", {
...
}
</script>
<a-scene> </a-scene>
<script>
const gScene = document.querySelector("a-scene");
var camara = document.querySelector("[camera]");
camara.setAttribute("position", { x: 0, y: 0, z: 10 });
var p00 = document.createElement("a-entity");
p00.setAttribute("box", { width: 1, height: 1, depth: 1, color: "#f00" });
gScene.appendChild(p00);
p00.setAttribute("height", 3);
p00.setAttribute("color", "#00f");
</script>
First part of the code plot a red box with 1x1x1 dimension. But when I change the height or color attribute, don't do anything. What I have to do to fire the update?
Thanks in advance

You need to update the box attribute - setAttribute("height", XXX) will trigger an update in the height component.
If color is in the box schema, then:
// this updates the color property of the box attribute,
// triggering "update" in the "box" component
p00.setAttribute("box", "color", "red")
// this update the height attribute,
// triggering "update" in the "height" component
p00.setAttribute("height", "10");

Related

Is there a way to prevent a Shape for being transformed?

That is the thing, i'm creating a shape that covers all canvas to act like a white background, i have a transformer and im listening to canvas clicks, inside it im adding objects into transformer nodes, but i don't like to transform the white shape that im using as a background.
Canvas white Shape
Just don't add transformer into it. I see several solutions:
Set listening = false on that background shape. In that case, it will not trigger any mouse/touch/pointer events
Or set a special name for it in just ignore in click callback
const background = new Konva.Rect({
fill: 'white',
width: stage.width(),
height: stage.height(),
name: 'nonSelectable'
});
stage.on('click', (e) => {
// ignore such shape
if (e.target.hasName('nonSelectable')) {
return;
}
// else attach transformer
});

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.

Affecting KineticJs.Image by css

Hello i'm working on a project that requires canvas manipulation. I need to draw an image and have to move it within the canvas. Which was not so hard to accomplish.. However i need to change my cursor into "move" when hovering the image like
img{
cursor:move;
}
I couldn't find any way to do this. Any suggestion??
Thanks in advance..
When you drag an Kinetic.Image, you get dragstart and dragend events.
You can change the cursor type in those event handlers:
// starting to drag -- display the move cursor
image1.on('dragstart', function () {
document.body.style.cursor = 'move';
});
// done dragging -- display the regular cursor
image1.on('dragend', function () {
document.body.style.cursor = 'default';
});
Basically you need an element which you can style on the page but with display: none, then put that element onto the canvas like this:
var image = document.getElementById('image');
context.drawImage(image, 0, 0);

Changing three.js background to transparent or other color

I've been trying to change what seems to be the default background color of my canvas from black to transparent / any other color - but no luck.
My HTML:
<canvas id="canvasColor">
My CSS:
<style type="text/css">
#canvasColor {
z-index: 998;
opacity:1;
background: red;
}
</style>
As you can see in the following online example I have some animation appended to the canvas, so cant just do a opacity: 0; on the id.
Live preview:
http://devsgs.com/preview/test/particle/
Any ideas how to overwrite the default black?
I came across this when I started using three.js as well. It's actually a javascript issue. You currently have:
renderer.setClearColorHex( 0x000000, 1 );
in your threejs init function. Change it to:
renderer.setClearColorHex( 0xffffff, 1 );
Update: Thanks to HdN8 for the updated solution:
renderer.setClearColor( 0xffffff, 0);
Update #2: As pointed out by WestLangley in another, similar question - you must now use the below code when creating a new WebGLRenderer instance in conjunction with the setClearColor() function:
var renderer = new THREE.WebGLRenderer({ alpha: true });
Update #3: Mr.doob points out that since r78 you can alternatively use the code below to set your scene's background colour:
var scene = new THREE.Scene(); // initialising the scene
scene.background = new THREE.Color( 0xff0000 );
A full answer: (Tested with r71)
To set a background color use:
renderer.setClearColor( 0xffffff ); // white background - replace ffffff with any hex color
If you want a transparent background you will have to enable alpha in your renderer first:
renderer = new THREE.WebGLRenderer( { alpha: true } ); // init like this
renderer.setClearColor( 0xffffff, 0 ); // second param is opacity, 0 => transparent
View the docs for more info.
For transparency, this is also mandatory: renderer = new THREE.WebGLRenderer( { alpha: true } ) via Transparent background with three.js
In 2020 using r115 it works very good with this:
const renderer = new THREE.WebGLRenderer({ alpha: true });
const scene = new THREE.Scene();
scene.background = null;
I found that when I created a scene via the three.js editor, I not only had to use the correct answer's code (above), to set up the renderer with an alpha value and the clear color, I had to go into the app.json file and find the "Scene" Object's "background" attribute and set it to:
"background: null".
The export from Three.js editor had it originally set to "background": 0
Set renderer clear colour
With the below code
renderer.setClearColor( 0x000000, 1 );
I'd also like to add that if using the three.js editor don't forget to set the background colour to clear as well in the index.html.
background-color:#00000000

Using Jcrop ,could not refresh preview pane correctly when changing image

I am trying to use Jcrop with preview pane in the page of changing avatar. However, after uploading new image file, when I call setImage to set the new image(with different width/height) and also set the attr of the preview image, the preview pane show up incorrectly. I use firebug the trace, it seems the img is still using the height, width of previous image. I modify the tutorial3 in the download package, simply adding a botton to change the image to see if the preview pane is correct or not. I seem to be the same error. Here below is the code for button click function.
Any solutions?
$('#img1').click(function(e) {
$('#preview').attr('src','demo_files/img50d5753eb067c.jpg');
jcrop_api.setImage('demo_files/img50d5753eb067c.jpg');
$('#target').Jcrop({
onChange: updatePreview,
onSelect: updatePreview,
aspectRatio: 1,
boxWidth: 450
},function(){
// Use the API to get the real image size
var bounds = this.getBounds();
boundx = bounds[0];
boundy = bounds[1];
// Store the API in the jcrop_api variable
jcrop_api = this;
});
});
I see the same problem with yours in this topic Change an Image while using JCrop and the answer of AdmSteck in which is the best one.
Hope this help!
within the unminified version of the plugin "boundx and boundy" are declared as local variables that do not get updated outside of the setImage function. All you need to do is remove the 'var' for these two variables and make them global.
from line 328,
var boundx = $img.width(),
boundy = $img.height(),
$div = $('<div />').width(boundx).height(boundy).addClass(cssClass('holder')).css({
position: 'relative',
backgroundColor: options.bgColor
}).insertAfter($origimg).append($img);
change to
boundx = $img.width();
boundy = $img.height();
var $div = $('<div />').width(boundx).height(boundy).addClass(cssClass('holder')).css({
position: 'relative',
backgroundColor: options.bgColor
}).insertAfter($origimg).append($img);

Resources