Canvatorium Lab 044
Independent Reactive Texture Cards
Expanding on the work from Lab 043 I wanted to test the idea of creating each 3D card with binding to reactive data.
I explored several ways to do this but settled on a reactive array of objects. I could fetch some data from a server or api, then create a 3D card for each one.
Core concepts
- titles: a reactive array of objects. I used
ref
for now but could be usingreactive
instead - each card gets the title value from the object passed to
generateCard
- each card has a button that can toggle the title value between two values
- during the calle to
generateCard
a watcher is set up to watch for changes to the title value and update the title text
Simplified code
const createLabContent = async (scene) => {
const numberOfCards = 50;
// Create a reactive array of objects: title and index
const titles = ref([]);
for (let i = 0; i < numberOfCards; i++) {
titles.value.push(ref({ title: "I'm Sparticus!", index: i }));
}
// Create a card for each title object
for (let i = 0; i < numberOfCards; i++) {
const titleObject = titles.value[i];
const card = generateCard(scene, titleObject);
...
}
};
const generateCard = (scene, titleObject) => {
// use the index to get the title from the reactive array
const index = titleObject.value.index; // just used for naming for now
const title = titleObject.value.title; // used for the text block
const plane = MeshBuilder.CreatePlane("plane", { width: 0.3, height: 0.3 }, scene);
plane.name = `card-${index}`;
const advancedTexture = AdvancedDynamicTexture.CreateForMesh(plane);
advancedTexture.name = `card-texture-${index}`;
advancedTexture.background = labColors.slate8;
const titleText = new TextBlock("title-text");
titleText.name = `title-text-${index}`;
...
advancedTexture.addControl(titleText);
// Add a button to change the title value
const button = Button.CreateSimpleButton("button", "Change Title");
...
button.onPointerUpObservable.add(() => {
titleObject.value.title = titleObject.value.title === `I'm Sparticus!` ? `I'm not Sparticus!` : `I'm Sparticus!`;
});
advancedTexture.addControl(button);
// Watch the title value for changes and update the text block
watch(titleObject.value, (newValue, oldValue) => {
titleText.text = newValue.title;
});
return plane;
};
As a proof of concept, this satisfies me. In the future I’ll explore using reactive instead of ref. I’d also like to move the watcher to the top-level scope.
Demo
This lab is part of a project called Canvatorium, an experimental design lab for spatial computing. Learn more.