为了将框架完全集成到 Angular 中,我必须这样做。我并不是说这一定是最好的方法,或者 你 必须做这一切。有些人似乎能够摆脱更简单的解决方案,如果这些解决方案对您有用(例如简单的adding the aframe lib into polyfill.ts),那么就去做吧。显然,解决方案可能会随着角度发布而有所不同,如果您没有运行单元测试,那么您不需要执行我在此处描述的所有操作。
您需要关注的大文件有:
.angular-cli.json
karma.conf.js
src/app/app.module.ts
src/index.html
all your .spec.ts files
ng 服务环境
1) 要让您的“ng serve”(网络)环境从头部加载 aframe.js,请将 aframe.js 库添加到“src/index.html”,如下所示:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>My app</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<script src="../node_modules/aframe/dist/aframe-master.js"></script>
...
注意:你不需要为 three.js 添加脚本标签,因为 aframe 会预先请求它。
注意 2:您也可以使用 'node_modules'/aframe/build/aframe.js'。 'aframe-master.js' 更像是一个'流血边缘不稳定'的构建,但它对我来说已经足够好了。
注 3(更新为 '2018-01-10'):虽然我似乎能够使用 angular 4 的“../node_modules”,但使用 angular5 我必须复制 'aframe-master.js' 和 'aframe -master.js.map' 到 'assets' 的子目录中,例如'src/assets/libs'。简而言之,Angular 5 似乎要求从“/assets”(?)加载外部 js 库。
通常,您应该在.angular.cli.json 的scripts 标记中包含javascript 库,但是如果您将它们放在那里,它们将不会从头部加载。我的scripts 标签目前是空的,但是你应该把任何其他的js库放在那里并且不放在index.html中:
cat .angular-cli.json
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"project": {
"name": "lss"
},
"apps": [
{
"root": "src",
"outDir": "dist",
"assets": [
"assets",
"favicon.ico"
],
"index": "index.html",
"main": "main.ts",
"polyfills": "polyfills.ts",
"test": "test.ts",
"tsconfig": "tsconfig.app.json",
"testTsconfig": "tsconfig.spec.json",
"prefix": "app",
"styles": [
"styles.css"
],
"scripts": [
],
"environmentSource": "environments/environment.ts",
注意脚本是空白的,并且 不 包含 aframe.js
2) 将“CUSTOM_ELEMENTS_SCHEMA”添加到“src/app/app.module.ts”:
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
...
entryComponents: [AppComponent, PlaneSceneComponent],
bootstrap: [AppComponent],
schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
})
export class AppModule { }
注意:CUSTOM_ELEMENTS_SCHEMA 允许在您的 Angular html 中使用非角度标签(例如 <a-scene>)。
如果您不运行单元测试,那就差不多了。业力测试环境完全独立于标准的基于 Web 的环境。如果您计划进行单元测试,请执行以下附加步骤来设置测试环境。
ng 测试环境
3) 更新 karma.conf.js 以了解 aframe 和 three.js 并指定自定义上下文文件:
--> 2018-03-08 更新:从 angular cli 1.7.3 开始,“customContextFile”似乎不再受 angular 支持。它似乎也无法再从 node_modules 读取文件了——你必须将 aframe-master.lib 放在 'src/assets/' 下。我不得不像这样直接编辑'node_modules/@angular/cli/plugins/karma-context.html':
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
<!--user add -->
<script type="text/javascript" src="/base/src/assets/libs/aframe-master.js" crossorigin="anonymous"></script>
<!--user end -->
</head>
不幸的是,在我找到更正式的方法来实现此效果之前,必须在每个签出的 repo 上手动执行此 hack,因为大多数人不会签入 node_modules 目录。
以下在 ng-cli 1.7.3 之前有效:
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular/cli'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular/cli/plugins/karma')
],
//user add
customContextFile: './src/environments/context_aframe_ut.html',
//user end
client:{
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
files: [
{ pattern: './src/test.ts', watched: false },
//user add
{ pattern: 'node_modules/aframe/dist/aframe-master.js', included: false, served: true },
{ pattern: 'node_modules/three/build/three.js', included: false, served: true }
//user end
],
preprocessors: {
'./src/test.ts': ['@angular/cli']
},
mime: {
'text/x-typescript': ['ts','tsx']
},
coverageIstanbulReporter: {
reports: [ 'html', 'lcovonly' ],
fixWebpackSourcePaths: true
},
angularCli: {
environment: 'dev'
},
reporters: config.angularCli && config.angularCli.codeCoverage
? ['progress', 'coverage-istanbul']
: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false
});
};
注意:被“//user add”和“//user end”块包围的代码段。第一个定义了一个新的“context.html”文件,我们将创建该文件将从<head> 标签加载aframe.js。第二个定义了 karma 的 aframe 和 three.js 库。
4) 创建一个新的 karma 上下文 html 文件以从头部加载框架。
--> 2018-03-08 更新:请注意 ang-cli 1.7.3,因为不再支持“customContextFile”,您不必执行此步骤。按照上一步中的说明编辑“node_modules/@angular/cli/plugins/karma-context.html”。
将文件“node_modules/karma/static/context.html”复制到之前定义的“customContextFile”目录中,然后修改如下:
<!DOCTYPE html>
<!--
This is the execution context.
Loaded within the iframe.
Reloaded before every execution run.
vt was here 3.
-->
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
<!--user add -->
<!-- <script src="aframe-master.js"></script> -->
<script src="/base/node_modules/aframe/dist/aframe-master.js"></script>
<!--user end -->
</head>
<body>
<!-- The scripts need to be in the body DOM element, as some test running frameworks need the body
to have already been created so they can insert their magic into it. For example, if loaded
before body, Angular Scenario test framework fails to find the body and crashes and burns in
an epic manner. -->
<script src="context.js"></script>
<script type="text/javascript">
// Configure our Karma and set up bindings
%CLIENT_CONFIG%
window.__karma__.setupContext(window);
// All served files with the latest timestamps
%MAPPINGS%
</script>
<!-- Dynamically replaced with <script> tags -->
%SCRIPTS%
<script type="text/javascript">
window.__karma__.loaded();
</script>
</body>
</html>
注意:“//用户添加”和“//用户端”部分再次出现。
注意 2:您必须在 aframe 库前面加上 '/base' 才能让 karma 找到它。请注意我放弃了使无前缀版本工作的尝试。
注 3:(可选)在开头注释中添加一些文本,例如'vt was here' 这样您就可以更轻松地验证 Karma 确实在加载您的自定义 context.html。
5)(可选)验证更新后的 context.html。
运行 'ng test' 并检查浏览器使用的 html。在节点 'iframe.#document.html.head' 下验证您是否拥有:
<script src="/base/node_modules/aframe/dist/aframe-master.js"></script>
这证实了业力正在从头部加载帧。
6) 将“CUSTOM_ELEMENTS_SCHEMA”添加到每个使用 a-frame 的 spec.ts 文件中:
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core"; //<- add
import { RouterTestingModule } from '@angular/router/testing';
import { LoopySurfaceSurfersComponent } from './loopy-surface-surfers.component';
import { AsteroidsGame } from '../inner-games/asteroids/asteroids-game';
import { Ship } from '../inner-games/asteroids/ship';
import { BaseService } from '../services/base.service';
import { UtilsService } from '../services/utils.service';
describe('LoopySurfaceSurfersComponent', () => {
let component: LoopySurfaceSurfersComponent;
let fixture: ComponentFixture<LoopySurfaceSurfersComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ LoopySurfaceSurfersComponent ],
imports: [RouterTestingModule],
schemas: [ CUSTOM_ELEMENTS_SCHEMA ], // <- add
providers: [AsteroidsGame, Ship, UtilsService, BaseService,
THREE.Scene
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(LoopySurfaceSurfersComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
7) 您可能需要循环“ng serve”和“ng test”才能了解更改。
结论
如您所见,这并非微不足道。问题的主要来源是从头部加载框架的要求。我希望这可以节省我将 aframe 完全集成到 angular2 环境中所必须付出的所有努力。
我还应该声明,我非常喜欢 A 型框架,它与 angular 配合得非常好。将这两个框架一起运行是一个很好的组合,绝对值得付出努力,所以如果您遇到配置问题,请不要气馁。