AFrame 为每个对象更新 material.offset
AFrame updating material.offset for each object
我制作了一个用于创建热点的 AFrame 组件,我想在光标悬停时更改热点的 material.offset.y。
所以我首先尝试使用 AFrame animaiton 属性,但显然,我们无法使用动画访问此 属性。
所以我向热点JS对象添加了一个eventListener并更改了getObject3D('mesh').material.map.offset.y,但是当我悬停一个热点时它会更新所有热点纹理,不知道为什么......我检查了这是否指向特定热点,它是!所以我不明白为什么所有的纹理都在更新...
代码如下:
<a-scene light="defaultLightsEnabled: false">
<a-assets>
<!-- Loading Scenes -->
<img src="./assets/scene/scene.jpg" id="scene_spherical" />
<!-- Loading Icons -->
<img src="./assets/icons/close.png" id="icon_close" />
<img src="./assets/icons/hotspot_sprite.png" id="icon_hotspot" />
<img src="./assets/icons/powered.png" id="icon_powered" />
<img src="./assets/icons/store.png" id="icon_store" />
<!-- Loading Mixins -->
<a-mixin id="mixin_hotspot"
geometry="primitive: circle; radius: 0.25"
material="shader: flat; src: #icon_hotspot; transparent: true; repeat: 1 0.5; offset: 0 0.5;"
></a-mixin>
</a-assets>
<a-hotspot position="-6.33 0.30 -1.46" product="terrazzo_kaza_d" class="" id="hotspot_terrazzo_kaza_d"></a-hotspot>
<a-hotspot position="5.43 -0.03 -6.21" product="meuble_tv" class="" id="hotspot_meuble_tv"></a-hotspot>
<a-hotspot position="3.34 -0.81 -7.77" product="tapis_lake" class="" id="hotspot_tapis_lake"></a-hotspot>
<a-hotspot position="5.30 1.22 -0.81" product="isole_escalier" class="" id="hotspot_isole_escalier"></a-hotspot>
<a-hotspot position="-3.74 1.10 7.27" product="papier_peint" class="" id="hotspot_papier_peint"></a-hotspot>
<a-hotspot position="3.09 -0.69 7.35" product="shooting_sol" class="" id="hotspot_shooting_sol"></a-hotspot>
<a-hotspot position="-6.98 1.86 0.60" product="isole_cuisine" class="" id="hotspot_isole_cuisine"></a-hotspot>
<a-hotspot position="-0.38 -0.32 5.98" product="isole_table_rectangulaire" class="" id="hotspot_isole_table_rectangulaire"></a-hotspot>
<a-hotspot position="2.66 1.76 -8.15" product="isole_voilage" class="" id="hotspot_isole_voilage"></a-hotspot>
<a-hotspot position="-1.13 -0.34 -7.41" product="isole_canape2" class="" id="hotspot_isole_canape2"></a-hotspot>
<a-sky src="#scene_spherical"></a-sky>
<a-camera wasd-controls="enabled: false;" cursor="rayOrigin: mouse"></a-camera>
</a-scene>
import loadProduct from '../libs/shop'
AFRAME.registerPrimitive('a-hotspot', {
defaultComponents: {
'hotspot-popup': {}
},
mappings: {
product: 'hotspot-popup.product',
}
})
AFRAME.registerComponent('hotspot-popup', {
schema: {
// variables
product: {type: 'string'}
},
init: function() {
this.el.setAttribute('mixin', 'mixin_hotspot')
this.setHover()
this.setClick()
},
setHover() {
this.el.addEventListener('mouseenter', () => {
let material = this.el.getObject3D('mesh').material
if (material.map) {
material.map.offset.y = 0
material.map.offset.x = 0
}
})
this.el.addEventListener('mouseleave', () => {
let material = this.el.getObject3D('mesh').material
if (material.map) {
material.map.offset.y = 0.5
material.map.offset.x = 0
}
})
},
tick: function () {
let cursorRotation = document.querySelector('a-camera').getAttribute('rotation')
this.el.setAttribute('rotation', cursorRotation)
},
setClick: function () {
this.el.addEventListener('click', () => {
console.log('load', this.data.product)
loadProduct(this.data.product)
});
}
})
因此,如果有人知道如何防止这种行为,请不要犹豫,对此 post 发表评论。
谢谢,
纳瓦莱克斯
所有图像都被赋予相同偏移量的原因是因为 a-frame
出于性能原因重新使用纹理。
使用这样的设置:
<a-box material="src: #image"></a-box>
<a-sphere material="src: #image"></a-sphere >
如果您记录两者 element.getObject3D("mesh").material.map.uuid
- 它们将是相同的 (fiddle)。更新一个会影响另一个。
如果您在 material
中给它们一个初始偏移量(但每个对象的初始偏移量不同):
<a-box material="src: #image; offset: 0 0.5"></a-box>
<a-sphere material="src: #image"></a-sphere >
a-frame
将创建 THREE.Texture()
它们的另一个实例 (fiddle)。
否则,您可以创建一个 component
用副本替换纹理:
this.el.addEventListener("materialtextureloaded", e => {
// grab the object
let obj = this.el.getObject3D("mesh")
// grab the texture
let map = obj.material.map
// create a new one
const texture = new THREE.TextureLoader().load(map.image.src);
// without wrapping, it will just "stretch" instead of "repeating"
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
// assign the new texture
obj.material.map = texture;
// update the material
obj.material.needsUpdate = true
})
这让我们想到 this(包括动画、环绕等)
我制作了一个用于创建热点的 AFrame 组件,我想在光标悬停时更改热点的 material.offset.y。 所以我首先尝试使用 AFrame animaiton 属性,但显然,我们无法使用动画访问此 属性。
所以我向热点JS对象添加了一个eventListener并更改了getObject3D('mesh').material.map.offset.y,但是当我悬停一个热点时它会更新所有热点纹理,不知道为什么......我检查了这是否指向特定热点,它是!所以我不明白为什么所有的纹理都在更新...
代码如下:
<a-scene light="defaultLightsEnabled: false">
<a-assets>
<!-- Loading Scenes -->
<img src="./assets/scene/scene.jpg" id="scene_spherical" />
<!-- Loading Icons -->
<img src="./assets/icons/close.png" id="icon_close" />
<img src="./assets/icons/hotspot_sprite.png" id="icon_hotspot" />
<img src="./assets/icons/powered.png" id="icon_powered" />
<img src="./assets/icons/store.png" id="icon_store" />
<!-- Loading Mixins -->
<a-mixin id="mixin_hotspot"
geometry="primitive: circle; radius: 0.25"
material="shader: flat; src: #icon_hotspot; transparent: true; repeat: 1 0.5; offset: 0 0.5;"
></a-mixin>
</a-assets>
<a-hotspot position="-6.33 0.30 -1.46" product="terrazzo_kaza_d" class="" id="hotspot_terrazzo_kaza_d"></a-hotspot>
<a-hotspot position="5.43 -0.03 -6.21" product="meuble_tv" class="" id="hotspot_meuble_tv"></a-hotspot>
<a-hotspot position="3.34 -0.81 -7.77" product="tapis_lake" class="" id="hotspot_tapis_lake"></a-hotspot>
<a-hotspot position="5.30 1.22 -0.81" product="isole_escalier" class="" id="hotspot_isole_escalier"></a-hotspot>
<a-hotspot position="-3.74 1.10 7.27" product="papier_peint" class="" id="hotspot_papier_peint"></a-hotspot>
<a-hotspot position="3.09 -0.69 7.35" product="shooting_sol" class="" id="hotspot_shooting_sol"></a-hotspot>
<a-hotspot position="-6.98 1.86 0.60" product="isole_cuisine" class="" id="hotspot_isole_cuisine"></a-hotspot>
<a-hotspot position="-0.38 -0.32 5.98" product="isole_table_rectangulaire" class="" id="hotspot_isole_table_rectangulaire"></a-hotspot>
<a-hotspot position="2.66 1.76 -8.15" product="isole_voilage" class="" id="hotspot_isole_voilage"></a-hotspot>
<a-hotspot position="-1.13 -0.34 -7.41" product="isole_canape2" class="" id="hotspot_isole_canape2"></a-hotspot>
<a-sky src="#scene_spherical"></a-sky>
<a-camera wasd-controls="enabled: false;" cursor="rayOrigin: mouse"></a-camera>
</a-scene>
import loadProduct from '../libs/shop'
AFRAME.registerPrimitive('a-hotspot', {
defaultComponents: {
'hotspot-popup': {}
},
mappings: {
product: 'hotspot-popup.product',
}
})
AFRAME.registerComponent('hotspot-popup', {
schema: {
// variables
product: {type: 'string'}
},
init: function() {
this.el.setAttribute('mixin', 'mixin_hotspot')
this.setHover()
this.setClick()
},
setHover() {
this.el.addEventListener('mouseenter', () => {
let material = this.el.getObject3D('mesh').material
if (material.map) {
material.map.offset.y = 0
material.map.offset.x = 0
}
})
this.el.addEventListener('mouseleave', () => {
let material = this.el.getObject3D('mesh').material
if (material.map) {
material.map.offset.y = 0.5
material.map.offset.x = 0
}
})
},
tick: function () {
let cursorRotation = document.querySelector('a-camera').getAttribute('rotation')
this.el.setAttribute('rotation', cursorRotation)
},
setClick: function () {
this.el.addEventListener('click', () => {
console.log('load', this.data.product)
loadProduct(this.data.product)
});
}
})
因此,如果有人知道如何防止这种行为,请不要犹豫,对此 post 发表评论。
谢谢, 纳瓦莱克斯
所有图像都被赋予相同偏移量的原因是因为 a-frame
出于性能原因重新使用纹理。
使用这样的设置:
<a-box material="src: #image"></a-box>
<a-sphere material="src: #image"></a-sphere >
如果您记录两者 element.getObject3D("mesh").material.map.uuid
- 它们将是相同的 (fiddle)。更新一个会影响另一个。
如果您在 material
中给它们一个初始偏移量(但每个对象的初始偏移量不同):
<a-box material="src: #image; offset: 0 0.5"></a-box>
<a-sphere material="src: #image"></a-sphere >
a-frame
将创建 THREE.Texture()
它们的另一个实例 (fiddle)。
否则,您可以创建一个 component
用副本替换纹理:
this.el.addEventListener("materialtextureloaded", e => {
// grab the object
let obj = this.el.getObject3D("mesh")
// grab the texture
let map = obj.material.map
// create a new one
const texture = new THREE.TextureLoader().load(map.image.src);
// without wrapping, it will just "stretch" instead of "repeating"
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
// assign the new texture
obj.material.map = texture;
// update the material
obj.material.needsUpdate = true
})
这让我们想到 this(包括动画、环绕等)