Привязка данных не работает для атрибутов тега A-frame
Я делаю приложение WebVR с aframe и angular-cli. Я загружаю некоторые статические данные JSON из ресурсов и привязываю их к элементу A-frame. Вот пример моих данных JSON.
{
"id": 4,
"image": "",
"location": "Font",
"nextScenes": [
3,
5
],
"hotspots": [
{
"id": "obj1",
"location": "2325 1305 -2400",
"rotation": "-5 -50 -5",
"scale": "150 150 150",
"headerTitle": "",
"body": ""
},
{
"id": "obj2",
"location": "3145 890 -2175",
"rotation": "-5 -50 -5",
"scale": "150 150 150",
"headerTitle": "",
"body": ""
}
]
}
Я загружу hotspots
в моем HTML-коде с этим кодом:
<a-scene inspector="url: https://aframe.io/releases/0.3.0/aframe-inspector.min.js">
<a-assets>
<img id="sky" [src]="currentImageSource" alt="" />
</a-assets>
<a-sky src="#sky"></a-sky>
<!-- problems with code below -->
<a-entity *ngFor="let spot of currentData.hotspots; let i = index" [id]="spot.id"
[position]="spot.location" [rotation]="spot.rotation" [scale]="spot.scale"
visible="true" mixin="null" color="pink"
text="zOffset:0;value:S;height:100;width:100;align:center"></a-entity>
</a-scene>
Заметить, что currentData
равен приведенному выше коду JSON и currentImageSource
содержит местоположение изображения.
Проблема с кодом выше в том, что атрибуты position
, rotation
а также scale
не будет связывать В отображаемом выводе переменные пусты, но ng-reflect-...
атрибуты не пусты.
Кроме того, если я проверяю код с помощью Ctrl + Alt + I, объект получил a-entity
помечает значения по умолчанию.
Обновите одно: привязка данных для атрибута id
работает.
Обновление два: Здесь вы можете увидеть вывод в моем браузере:
<app-vrtour _nghost-pub-1="">
<a-scene class="fullscreen" inspector="" canvas="" keyboard-shortcuts="" screenshot="" vr-mode-ui="" auto-enter-vr="" _ngcontent-pub-1="">
<a-assets _ngcontent-pub-1="">
<ewalswebvr-static-assets _ngcontent-pub-1=""><img id="#details" crossorigin="anonymous" scr="/assets/images/details.jpg"></ewalswebvr-static-assets>
<img id="sky" alt="" src="assets/360images/P5.tif" ng-reflect-src="assets/360images/P5.tif" _ngcontent-pub-1="">
</a-assets>
<!--template bindings={"ng-reflect-ng-for-of": "[object Object],[object Object]"}-->
<!-- The two tags below are the lines that wouldn't bind -->
<a-entity id="obj1" mixin="null" text="" ng-reflect-id="obj1" ng-reflect-position="2323.81 1305.90 -2400" ng-reflect-rotation="-4.58 -48.7 -5.16" ng-reflect-scale="150 150 150" ng-reflect-visible="true" position="" rotation="" scale="" visible=""
_ngcontent-pub-1="" ng-reflect-color="#ff0000"></a-entity>
<a-entity id="obj2" mixin="null" text="" ng-reflect-id="obj2" ng-reflect-position="3145.63 889.46 -2176.50" ng-reflect-rotation="-4.58 -48.7 -5.16" ng-reflect-scale="150 150 150" position="" rotation="" scale="" visible="" _ngcontent-pub-1=""
ng-reflect-color="#00ff00"></a-entity>
<a-sky src="#sky" material="" position="" rotation="" scale="" visible="" geometry="" _ngcontent-pub-1=""></a-sky>
<canvas width="1920" height="930" class="a-canvas a-grab-cursor" style="width: 1920px; height: 930px;" data-aframe-canvas="true"></canvas>
<div class="a-enter-vr" style="display: none;" aframe-injected=""><button class="a-enter-vr-button" aframe-injected=""></button></div>
<div class="a-orientation-modal a-hidden" aframe-injected=""><button aframe-injected="">Exit VR</button></div>
<a-entity aframe-injected="" position="" rotation="" scale="" visible="" camera="" wasd-controls="" look-controls="" data-aframe-inspector="default-camera"></a-entity>
<a-entity aframe-injected="" position="" rotation="" scale="" visible="" light="" data-aframe-default-light=""></a-entity>
<a-entity aframe-injected="" position="" rotation="" scale="" visible="" light="" data-aframe-default-light=""></a-entity>
<a-entity position="" rotation="" scale="" visible="" camera=""></a-entity>
</a-scene>
</app-vrtour>
Не могли бы вы найти ошибку в моем коде?
заранее спасибо
3 ответа
Попробовав обходной путь, я нашел решение, которое работает. Проблема этого кода заключается в том, что он не использует привязку данных, и я уверен, что привязка данных менее производительна, но A-frame не поддерживает его.
Здесь вы можете найти код, который я добавил в мой машинописный код:
ngAfterViewInit(): void {
for (let i: number = this.currentData.hotspots.length; i--;) {
let spot: any = this.currentData.hotspots[i],
el: any = document.getElementById(spot.id);
el.setAttribute("position", spot.location);
el.setAttribute("rotation", spot.rotation);
el.setAttribute("scale", spot.scale);
}
}
Этот код работает, если я даю каждый a-entity
-тегать уникальный идентификатор. HTML-код моего компонента не изменился, но его можно использовать вместо этого.
<a-entity *ngFor="let spot of currentData.hotspots; let i = index" [id]="spot.id"
text="zOffset:0;value:S;height:100;width:100;align:center"></a-entity>
Причина того, что угловая привязка данных не работает, приведена здесь.
Используя одностороннюю привязку данных Angular, вы на самом деле устанавливаете свойства ваших фреймов. Однако в действительности таких свойств не существует. Это на самом деле атрибуты этих элементов. Следовательно, вы можете манипулировать областью через Dom Api.
Однако использование DOM api не рекомендуется с точки зрения безопасности. Но это тоже не обязательно.
Чтобы сделать привязку данных атрибутов, вы можете использовать подобный синтаксис следующим образом.
<a-entity *ngFor="let spot of currentData.hotspots; let i = index" [id]="spot.id"
[attr.position]="spot.location" [attr.rotation]="spot.rotation" [attr.scale]="spot.scale"
visible="true" mixin="null" color="pink"
text="zOffset:0;value:S;height:100;width:100;align:center"></a-entity>
Вы можете заставить это работать в шаблоне (без каких-либо a-entity
setup в классе контроллера) с помощью синтаксиса привязки атрибута [attr.*], например
<a-entity *ngFor="let spot of currentData.hotspots"
[attr.position]="spot.location" [attr.rotation]="spot.rotation"
[attr.scale]="spot.scale"
...
(И идентификатор элемента не требуется.)
Не беспокойтесь о том, что вы видите в DOM Inspector. То, что вы связываете, все еще влияет на саму сцену, верно? Если так, то я думаю, что это ответит:
https://aframe.io/docs/0.5.0/introduction/faq.html
Из соображений производительности A-Frame не обновляет DOM данными компонента. Используйте компонент отладки, чтобы включить сериализацию компонента в DOM.
По умолчанию из соображений производительности A-Frame не обновляет DOM данными компонента. Если мы откроем инспектор DOM браузера, мы увидим, что у многих объектов будет видно только имя компонента:
<a-entity geometry material position rotation></a-entity>
Данные компонента хранятся внутри. Обновление DOM требует времени ЦП для преобразования данных компонентов, которые хранятся внутри, в строки. Однако, когда мы хотим увидеть обновление DOM для целей отладки, мы можем прикрепить отладочный компонент к сцене. Компоненты проверят, включен ли компонент отладки, прежде чем пытаться сериализовать в DOM. Тогда мы сможем просматривать данные компонентов в DOM:
<a-entity geometry="primitive: box" material="color: red" position="1 2 3" rotation="0 180 0"></a-entity>
Убедитесь, что этот компонент не активен в производстве.