增加三维课程播放器,增加第一人称控制碰撞检测,完善编辑器数据

This commit is contained in:
sunzhenyu 2021-04-22 18:07:56 +08:00
parent 93af07c20e
commit e9b9345e95
28 changed files with 2135 additions and 127 deletions

View File

@ -0,0 +1,88 @@
import store from '@/store/index';
// import { Loading } from 'element-ui';
import {Stats} from '@/jlmap3d/main/lib/stats.min.js';
//静态资源文件路径
import { JL3D_LOCAL_STATIC } from '@/api/jlmap3d/assets3d.js';
//loader
import { FBXLoader } from '@/jlmap3d/main/loaders/FBXLoader';
//轨道视角控制
import { OrbitControls } from '@/jlmap3d/main/control/OrbitControls';
//骨骼动画模型辅助工具
import { SkeletonUtils } from '@/jlmap3d/main/utils/SkeletonUtils.js';
import { AssetModelManager } from '@/jlmap3d/lesson3d/manager/assetmodelmanager.js';
import { ControlManager } from '@/jlmap3d/lesson3d/manager/controlmanager.js';
// import { AnimationManager } from '@/jlmap3d/lesson3d/manager/assetmodelmanager.js';
//动画播放相关
let clock = new THREE.Clock();
let delta;
let scene;
export function Lesson3dPlayer(dom,lessonData,lessonIndex) {
// let stats = new Stats();
// dom.appendChild( stats.dom );
let scope = this;
this.dom = dom;
//定义相机
//定义场景(渲染容器)
scene = new THREE.Scene();
scene.background = new THREE.Color(0xa0a0a0);
//定义全局光
let ambientLight = new THREE.AmbientLight(0xffffff, 1.3);
scene.add(ambientLight);
var light = new THREE.HemisphereLight( 0xffffff, 0x444444 );
light.position.set( 0, 4000, 0 );
scene.add( light );
let controlManager = new ControlManager( dom,scene,lessonData,lessonIndex);
let assetModelManager = new AssetModelManager(scene,controlManager);
assetModelManager.lessonAssetsLoader(lessonData.assetList,lessonData.modelList).then((result) => {
controlManager.initOctree(assetModelManager.loadAsset['default1'].mesh);
animate();
console.log(lessonData.lessonProgress[lessonIndex]);
if(lessonData.lessonProgress[lessonIndex].action.length>0){
controlManager.initNewEvent(lessonData.lessonProgress[lessonIndex].action,assetModelManager.lessonTriggerList);
}
resolve("loadeend"); //['成功了', 'success']
}).catch((error) => {
//console.log(error);
});;
this.actionRemove = function(actionModel){
assetModelManager.otherModel.remove(actionModel);
}
//循环渲染函数
function animate() {
if(controlManager.controlMode == "free"){
controlManager.updateOrbitControl();
}
if(controlManager.controlMode == "fps"){
controlManager.updateFpsControl();
}
// delta = clock.getDelta();
requestAnimationFrame(animate);
}
this.attachModel = function(selectModel){
}
}

View File

@ -0,0 +1,160 @@
import { BASE_ASSET_API } from '@/api/jlmap3d/assets3d.js';
export function AssetModelManager(scene) {
let scope = this;
this.assetList = [];
this.otherModel = new THREE.Group();
scene.add(this.otherModel);
this.loadAsset = [];
this.loadAsset['default1'] = {
modelId:'default1',
packageName:"车站",
url:"/MODEL/2021-04-06/1381-54584.FBX",
mesh:"",
assetType:'default',
isUse:true,
resourceType:"三维课程",
};
//场景中可触发事件模型
this.lessonTriggerList = [];
//加载课程资源
this.lessonAssetsLoader = function(assetList,modelList){
let initlist = [];
if(assetList){
for(let i = 0;i<assetList.length;i++){
assetList[i].mesh = "";
scope.loadAsset[assetList[i].modelId] = assetList[i];
}
}
for(let k in scope.loadAsset){
initlist.push(fbxpromise(scope.loadAsset[k]));
}
return new Promise(function(resolve, reject){
Promise.all(initlist).then((result) => {
initTriggerList();
for(let i=0;i<modelList.length;i++){
let newModelTrigger = scope.loadAsset[modelList[i].modelId].mesh.clone(true);
newModelTrigger.showType = "loadModel";
newModelTrigger.label = modelList[i].label;
newModelTrigger.modelId = modelList[i].modelId;
newModelTrigger.visible = modelList[i].visible;
newModelTrigger.position.x = modelList[i].pos.x;
newModelTrigger.position.y = modelList[i].pos.y;
newModelTrigger.position.z = modelList[i].pos.z;
newModelTrigger.rotation.x = modelList[i].rot.x;
newModelTrigger.rotation.y = modelList[i].rot.y;
newModelTrigger.rotation.z = modelList[i].rot.z;
scope.otherModel.add(newModelTrigger);
scope.lessonTriggerList.push(newModelTrigger);
}
updateTriggerList(scope.lessonTriggerList);
resolve("loaderassets"); //['成功了', 'success']
}).catch((error) => {
//console.log(error);
});
});
resolve("loaderassets");
}
// <el-option label="车站" value="standstation"></el-option>
// <el-option label="停车场" value="stopstation"></el-option>
// <el-option label="单体设备" value="device"></el-option>
// <el-option label="线路" value="xl"></el-option>
// <el-option label="道岔" value="dc"></el-option>
//FT 扶梯
//FTAN 扶梯按钮(急停)
//FTD 扶梯灯
//FTKG 扶梯开关(钥匙孔)
//FTTJ 扶梯台阶
function initTriggerList(){
scope.loadAsset['default1'].mesh.getObjectByName("FTAN").showType = "default";
scope.loadAsset['default1'].mesh.getObjectByName("FTAN").label = "扶梯急停按钮";
scope.lessonTriggerList.push(scope.loadAsset['default1'].mesh.getObjectByName("FTAN"));
scope.loadAsset['default1'].mesh.getObjectByName("FTKG").showType = "default";
scope.loadAsset['default1'].mesh.getObjectByName("FTKG").label = "扶梯钥匙孔";
scope.lessonTriggerList.push(scope.loadAsset['default1'].mesh.getObjectByName("FTKG"));
// console.log(scope.loadAsset['default1'].mesh.getObjectByName("FTKG"));
}
//动态加载资源
this.lessonAssetsNewLoader = function(assetData,pos){
let isLoaded = false;
if(scope.loadAsset[assetData.id]){
let newModelTrigger = scope.loadAsset[assetData.id].mesh.clone(true);
newModelTrigger.modelId = assetData.id;
newModelTrigger.showType = "loadModel";
newModelTrigger.label = assetData.packageName;
newModelTrigger.position.copy(pos);
scope.otherModel.add(newModelTrigger);
scope.lessonTriggerList.push(newModelTrigger);
updateTriggerList(scope.lessonTriggerList);
}else{
scope.loadAsset[assetData.id] = {
modelId:assetData.id,
packageName:assetData.packageName,
url:assetData.url,
mesh:"",
assetType:'loadModel',
isUse:true,
resourceType:"三维课程",
};
fbxpromise(scope.loadAsset[assetData.id]).then(function(object){
let newModelTrigger = scope.loadAsset[assetData.id].mesh.clone(true);
newModelTrigger.showType = "loadModel";
newModelTrigger.modelId = assetData.id;
newModelTrigger.label = assetData.packageName;
newModelTrigger.position.copy(pos);
scope.otherModel.add(newModelTrigger);
scope.lessonTriggerList.push(newModelTrigger);
updateTriggerList(scope.lessonTriggerList);
// resolve("loadednew");
});
}
}
//fbx模型加载
function fbxpromise(asset){
return new Promise(function(resolve, reject){
var loader = new THREE.FBXLoader();
loader.load( BASE_ASSET_API+asset.url, function ( object ) {
if(asset.assetType == "default"){
scene.add(object);
}else if(asset.assetType == 'loadModel'){
}
object.label = asset.packageName;
asset.mesh = object;
resolve();
} );
});
}
}

View File

@ -0,0 +1,403 @@
import { Capsule } from '@/jlmap3d/lesson3d/math/Capsule.js';
import { Octree } from '@/jlmap3d/lesson3d/math/Octree.js';
export function ControlManager(dom,scene,lessonData,lessonIndex) {
let scope = this;
this.controlMode = "";
this.controls = {};
this.nowCamera = null;
this.eventHitMode = false;
let eventBoxs = [];
let renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setClearColor(new THREE.Color(0x000000));
renderer.setViewport( 0, 0, dom.offsetWidth, dom.offsetHeight);
renderer.setScissor( 0, 0, dom.offsetWidth, dom.offsetHeight);
renderer.setScissorTest( false );
renderer.setSize(dom.offsetWidth, dom.offsetHeight);
renderer.sortObjects = true;
dom.appendChild(renderer.domElement);
let orbitCamera = new THREE.PerspectiveCamera(70, dom.offsetWidth / dom.offsetHeight, 0.01, 1000);
orbitCamera.position.set(0, 80, 40);
orbitCamera.aspect = dom.offsetWidth / dom.offsetHeight;
orbitCamera.updateProjectionMatrix();
let oribitControl = new THREE.OrbitControls(orbitCamera,dom);
oribitControl.maxPolarAngle = Math.PI / 2;
oribitControl.minPolarangle = Math.PI / 5;
oribitControl.maxDistance = 800;
oribitControl.screenSpacePanning = true;
oribitControl.update();
let fpsCamera = new THREE.PerspectiveCamera( 75,dom.offsetWidth / dom.offsetHeight, 0.1, 1000 );
fpsCamera.aspect = dom.offsetWidth / dom.offsetHeight;
fpsCamera.rotation.order = 'YXZ';
let attachBox = new THREE.Mesh(
new THREE.BoxGeometry(1, 5, 1),
new THREE.MeshBasicMaterial({color: 0xff00000})//RED box
);
let hitBox = new THREE.Box3(new THREE.Vector3(), new THREE.Vector3());
hitBox.setFromObject(attachBox);
scene.add(attachBox);
//fps control
const GRAVITY = 30;
const NUM_SPHERES = 20;
const SPHERE_RADIUS = 0.2;
const sphereGeometry = new THREE.SphereGeometry( SPHERE_RADIUS, 32, 32 );
const sphereMaterial = new THREE.MeshStandardMaterial( { color: 0x888855, roughness: 0.8, metalness: 0.5 } );
const spheres = [];
let sphereIdx = 0;
for ( let i = 0; i < NUM_SPHERES; i ++ ) {
const sphere = new THREE.Mesh( sphereGeometry, sphereMaterial );
scene.add( sphere );
spheres.push( { mesh: sphere, collider: new THREE.Sphere( new THREE.Vector3( 0, - 100, 0 ), SPHERE_RADIUS ), velocity: new THREE.Vector3() } );
}
scope.controlMode = lessonData.lessonProgress[lessonIndex].controlMode;
// scope.controls = oribitControl;
if(scope.controlMode == "free"){
scope.nowCamera = orbitCamera;
scope.controls.enabled = true;
}else if(scope.controlMode == "fps"){
scope.nowCamera = fpsCamera;
scope.controls.enabled = false;
}
const worldOctree = new Octree();
const playerCollider = new Capsule( new THREE.Vector3( 0, 10, 0 ), new THREE.Vector3( 0, 11.9, 0 ), 1 );
playerCollider.set(
new THREE.Vector3(
lessonData.lessonProgress[lessonIndex].cameraPosition.x,
lessonData.lessonProgress[lessonIndex].cameraPosition.y,
lessonData.lessonProgress[lessonIndex].cameraPosition.z),
new THREE.Vector3(
lessonData.lessonProgress[lessonIndex].cameraPosition.x,
lessonData.lessonProgress[lessonIndex].cameraPosition.y+1.5,
lessonData.lessonProgress[lessonIndex].cameraPosition.z ), 1);
attachBox.position.x = lessonData.lessonProgress[lessonIndex].cameraPosition.x;
attachBox.position.y = lessonData.lessonProgress[lessonIndex].cameraPosition.y ;
attachBox.position.z = lessonData.lessonProgress[lessonIndex].cameraPosition.z;
const playerVelocity = new THREE.Vector3();
const playerDirection = new THREE.Vector3();
let playerOnFloor = false;
const keyStates = {};
let clock = new THREE.Clock();
this.updateOrbitControl = function(){
oribitControl.update();
};
this.updateFpsControl = function(){
const deltaTime = Math.min( 0.1, clock.getDelta() );
controls( deltaTime );
updatePlayer( deltaTime );
updateSpheres( deltaTime );
if(scope.eventHitMode == true){
if(eventBoxs.length>0){
attachBox.position.copy(fpsCamera.position);
for(let i=0;i<eventBoxs.length;i++){
hitBox.setFromObject(attachBox);
eventBoxs[i].setFromObject(eventBoxs[i].mesh);
// console.log(eventBoxs[i]);
if(hitBox.intersectsBox(eventBoxs[i])){
console.log("相交");
console.log(eventBoxs[i].action);
if(eventBoxs[i].action.actionMode == "jump"){
jumpEvent("action",eventBoxs[i].action);
}
if(eventBoxs[i].action.actionMode == "remove"){
actionEvent("remove",eventBoxs[i].action,eventBoxs[i].mesh);
}
eventBoxs.splice(i,1);
i--;
}
}
}else{
scope.eventHitMod = false;
}
// attachBox.position.copy(fpsCamera.position);
// hitBox.setFromObject(attachBox);
// eventTestBox.setFromObject(eventBox);
//
// if(hitBox.intersectsBox(eventTestBox)){
// //两个物体相交了
// console.log("相交");
// scope.eventHitMode = false;
// }
// else{
// console.log("不相交");
// }
}
render();
};
this.initOctree = function(object){
worldOctree.fromGraphNode( object.getObjectByName("Object173") );
// scope.controlMode = lessonData.lessonProgress[lessonIndex].controlMode;
}
document.addEventListener( 'keydown', ( event ) => {
keyStates[ event.code ] = true;
} );
document.addEventListener( 'keyup', ( event ) => {
keyStates[ event.code ] = false;
} );
let fpsMouseStatus = false;
document.addEventListener( 'mousedown', () => {
fpsMouseStatus = true;
// document.body.requestPointerLock();
} );
document.body.addEventListener( 'mousemove', ( event ) => {
if(fpsMouseStatus == true){
fpsCamera.rotation.y -= event.movementX / 500;
fpsCamera.rotation.x -= event.movementY / 500;
}
// if ( document.pointerLockElement === document.body ) {
// }
} );
document.addEventListener( 'mouseup', () => {
fpsMouseStatus = false;
} );
function playerCollitions() {
const result = worldOctree.capsuleIntersect( playerCollider );
playerOnFloor = false;
if ( result ) {
playerOnFloor = result.normal.y > 0;
if ( ! playerOnFloor ) {
playerVelocity.addScaledVector( result.normal, - result.normal.dot( playerVelocity ) );
}
playerCollider.translate( result.normal.multiplyScalar( result.depth ) );
}
}
function updatePlayer( deltaTime ) {
if ( playerOnFloor ) {
const damping = Math.exp( - 3 * deltaTime ) - 1;
playerVelocity.addScaledVector( playerVelocity, damping );
} else {
playerVelocity.y -= GRAVITY * deltaTime;
}
const deltaPosition = playerVelocity.clone().multiplyScalar( deltaTime );
playerCollider.translate( deltaPosition );
playerCollitions();
fpsCamera.position.copy( playerCollider.end );
}
function spheresCollisions() {
for ( let i = 0; i < spheres.length; i ++ ) {
const s1 = spheres[ i ];
for ( let j = i + 1; j < spheres.length; j ++ ) {
const s2 = spheres[ j ];
const d2 = s1.collider.center.distanceToSquared( s2.collider.center );
const r = s1.collider.radius + s2.collider.radius;
const r2 = r * r;
if ( d2 < r2 ) {
const normal = s1.collider.clone().center.sub( s2.collider.center ).normalize();
const v1 = normal.clone().multiplyScalar( normal.dot( s1.velocity ) );
const v2 = normal.clone().multiplyScalar( normal.dot( s2.velocity ) );
s1.velocity.add( v2 ).sub( v1 );
s2.velocity.add( v1 ).sub( v2 );
const d = ( r - Math.sqrt( d2 ) ) / 2;
s1.collider.center.addScaledVector( normal, d );
s2.collider.center.addScaledVector( normal, - d );
}
}
}
}
function updateSpheres( deltaTime ) {
spheres.forEach( sphere =>{
sphere.collider.center.addScaledVector( sphere.velocity, deltaTime );
const result = worldOctree.sphereIntersect( sphere.collider );
if ( result ) {
sphere.velocity.addScaledVector( result.normal, - result.normal.dot( sphere.velocity ) * 1.5 );
sphere.collider.center.add( result.normal.multiplyScalar( result.depth ) );
} else {
sphere.velocity.y -= GRAVITY * deltaTime;
}
const damping = Math.exp( - 1.5 * deltaTime ) - 1;
sphere.velocity.addScaledVector( sphere.velocity, damping );
spheresCollisions();
sphere.mesh.position.copy( sphere.collider.center );
} );
}
function getForwardVector() {
fpsCamera.getWorldDirection( playerDirection );
playerDirection.y = 0;
playerDirection.normalize();
return playerDirection;
}
function getSideVector() {
fpsCamera.getWorldDirection( playerDirection );
playerDirection.y = 0;
playerDirection.normalize();
playerDirection.cross( fpsCamera.up );
return playerDirection;
}
function controls( deltaTime ) {
const speed = 25;
if ( playerOnFloor ) {
if ( keyStates[ 'KeyW' ] ) {
playerVelocity.add( getForwardVector().multiplyScalar( speed * deltaTime ) );
}
if ( keyStates[ 'KeyS' ] ) {
playerVelocity.add( getForwardVector().multiplyScalar( - speed * deltaTime ) );
}
if ( keyStates[ 'KeyA' ] ) {
playerVelocity.add( getSideVector().multiplyScalar( - speed * deltaTime ) );
}
if ( keyStates[ 'KeyD' ] ) {
playerVelocity.add( getSideVector().multiplyScalar( speed * deltaTime ) );
}
}
}
function render(){
if(scope.nowCamera){
renderer.render( scene, scope.nowCamera );
}
}
window.onresize = function () {
renderer.setSize(dom.offsetWidth,dom.offsetHeight);
}
this.initNewEvent = function(actions,lessonTriggerList){
console.log(actions);
console.log(lessonTriggerList);
eventBoxs = [];
for(let i=0;i<actions.length;i++){
if(actions[i].actionType == "contact"){
for(let j=0;j<lessonTriggerList.length;j++){
if(lessonTriggerList[j].label == actions[i].actionModel){
let eventTestBox = new THREE.Box3(new THREE.Vector3(), new THREE.Vector3());
eventTestBox.setFromObject(lessonTriggerList[j]);
eventTestBox.mesh = lessonTriggerList[j];
eventTestBox.action = actions[i];
eventBoxs.push(eventTestBox);
}
}
}
}
scope.eventHitMode = true;
};
console.log(lessonData);
}

View File

@ -0,0 +1,138 @@
var Capsule = ( function () {
var _v1 = new THREE.Vector3();
var _v2 = new THREE.Vector3();
var _v3 = new THREE.Vector3();
var EPS = 1e-10;
function Capsule( start, end, radius ) {
this.start = start == undefined ? new THREE.Vector3( 0, 0, 0 ) : start;
this.end = end == undefined ? new THREE.Vector3( 0, 1, 0 ) : end;
this.radius = radius == undefined ? 1 : radius;
}
Object.assign( Capsule.prototype, {
clone: function () {
return new Capsule( this.start.clone(), this.end.clone(), this.radius );
},
set: function ( start, end, radius ) {
this.start.copy( start );
this.end.copy( end );
this.radius = radius;
},
copy: function ( capsule ) {
this.start.copy( capsule.start );
this.end.copy( capsule.end );
this.radius = capsule.radius;
},
getCenter: function ( target ) {
return target.copy( this.end ).add( this.start ).multiplyScalar( 0.5 );
},
translate: function ( v ) {
this.start.add( v );
this.end.add( v );
},
checkAABBAxis: function ( p1x, p1y, p2x, p2y, minx, maxx, miny, maxy, radius ) {
return (
( minx - p1x < radius || minx - p2x < radius ) &&
( p1x - maxx < radius || p2x - maxx < radius ) &&
( miny - p1y < radius || miny - p2y < radius ) &&
( p1y - maxy < radius || p2y - maxy < radius )
);
},
intersectsBox: function ( box ) {
return (
this.checkAABBAxis(
this.start.x, this.start.y, this.end.x, this.end.y,
box.min.x, box.max.x, box.min.y, box.max.y,
this.radius ) &&
this.checkAABBAxis(
this.start.x, this.start.z, this.end.x, this.end.z,
box.min.x, box.max.x, box.min.z, box.max.z,
this.radius ) &&
this.checkAABBAxis(
this.start.y, this.start.z, this.end.y, this.end.z,
box.min.y, box.max.y, box.min.z, box.max.z,
this.radius )
);
},
lineLineMinimumPoints: function ( line1, line2 ) {
var r = _v1.copy( line1.end ).sub( line1.start );
var s = _v2.copy( line2.end ).sub( line2.start );
var w = _v3.copy( line2.start ).sub( line1.start );
var a = r.dot( s ),
b = r.dot( r ),
c = s.dot( s ),
d = s.dot( w ),
e = r.dot( w );
var t1, t2, divisor = b * c - a * a;
if ( Math.abs( divisor ) < EPS ) {
var d1 = - d / c;
var d2 = ( a - d ) / c;
if ( Math.abs( d1 - 0.5 ) < Math.abs( d2 - 0.5 ) ) {
t1 = 0;
t2 = d1;
} else {
t1 = 1;
t2 = d2;
}
} else {
t1 = ( d * a + e * c ) / divisor;
t2 = ( t1 * a - d ) / c;
}
t2 = Math.max( 0, Math.min( 1, t2 ) );
t1 = Math.max( 0, Math.min( 1, t1 ) );
var point1 = r.multiplyScalar( t1 ).add( line1.start );
var point2 = s.multiplyScalar( t2 ).add( line2.start );
return [ point1, point2 ];
}
} );
return Capsule;
} )();
export { Capsule };

View File

@ -0,0 +1,460 @@
import { Capsule } from '@/jlmap3d/lesson3d/math/Capsule.js';
var Octree = ( function () {
var _v1 = new THREE.Vector3();
var _v2 = new THREE.Vector3();
var _plane = new THREE.Plane();
var _line1 = new THREE.Line3();
var _line2 = new THREE.Line3();
var _sphere = new THREE.Sphere();
var _capsule = new Capsule();
function Octree( box ) {
this.triangles = [];
this.box = box;
this.subTrees = [];
}
Object.assign( Octree.prototype, {
addTriangle: function ( triangle ) {
if ( ! this.bounds ) this.bounds = new THREE.Box3();
this.bounds.min.x = Math.min( this.bounds.min.x, triangle.a.x, triangle.b.x, triangle.c.x );
this.bounds.min.y = Math.min( this.bounds.min.y, triangle.a.y, triangle.b.y, triangle.c.y );
this.bounds.min.z = Math.min( this.bounds.min.z, triangle.a.z, triangle.b.z, triangle.c.z );
this.bounds.max.x = Math.max( this.bounds.max.x, triangle.a.x, triangle.b.x, triangle.c.x );
this.bounds.max.y = Math.max( this.bounds.max.y, triangle.a.y, triangle.b.y, triangle.c.y );
this.bounds.max.z = Math.max( this.bounds.max.z, triangle.a.z, triangle.b.z, triangle.c.z );
this.triangles.push( triangle );
return this;
},
calcBox: function () {
this.box = this.bounds.clone();
// offset small ammount to account for regular grid
this.box.min.x -= 0.01;
this.box.min.y -= 0.01;
this.box.min.z -= 0.01;
return this;
},
split: function ( level ) {
if ( ! this.box ) return;
var subTrees = [],
halfsize = _v2.copy( this.box.max ).sub( this.box.min ).multiplyScalar( 0.5 ),
box, v, triangle;
for ( var x = 0; x < 2; x ++ ) {
for ( var y = 0; y < 2; y ++ ) {
for ( var z = 0; z < 2; z ++ ) {
box = new THREE.Box3();
v = _v1.set( x, y, z );
box.min.copy( this.box.min ).add( v.multiply( halfsize ) );
box.max.copy( box.min ).add( halfsize );
subTrees.push( new Octree( box ) );
}
}
}
while ( triangle = this.triangles.pop() ) {
for ( var i = 0; i < subTrees.length; i ++ ) {
if ( subTrees[ i ].box.intersectsTriangle( triangle ) ) {
subTrees[ i ].triangles.push( triangle );
}
}
}
for ( var i = 0; i < subTrees.length; i ++ ) {
var len = subTrees[ i ].triangles.length;
if ( len > 8 && level < 16 ) {
subTrees[ i ].split( level + 1 );
}
if ( len != 0 ) {
this.subTrees.push( subTrees[ i ] );
}
}
return this;
},
build: function () {
this.calcBox();
this.split( 0 );
return this;
},
getRayTriangles: function ( ray, triangles ) {
for ( var i = 0; i < this.subTrees.length; i ++ ) {
var subTree = this.subTrees[ i ];
if ( ! ray.intersectsBox( subTree.box ) ) continue;
if ( subTree.triangles.length > 0 ) {
for ( var j = 0; j < subTree.triangles.length; j ++ ) {
if ( triangles.indexOf( subTree.triangles[ j ] ) === - 1 ) triangles.push( subTree.triangles[ j ] );
}
} else {
subTree.getRayTriangles( ray, triangles );
}
}
return triangles;
},
triangleCapsuleIntersect: function ( capsule, triangle ) {
var point1, point2, line1, line2;
triangle.getPlane( _plane );
var d1 = _plane.distanceToPoint( capsule.start ) - capsule.radius;
var d2 = _plane.distanceToPoint( capsule.end ) - capsule.radius;
if ( ( d1 > 0 && d2 > 0 ) || ( d1 < - capsule.radius && d2 < - capsule.radius ) ) {
return false;
}
var delta = Math.abs( d1 / ( Math.abs( d1 ) + Math.abs( d2 ) ) );
var intersectPoint = _v1.copy( capsule.start ).lerp( capsule.end, delta );
if ( triangle.containsPoint( intersectPoint ) ) {
return { normal: _plane.normal.clone(), point: intersectPoint.clone(), depth: Math.abs( Math.min( d1, d2 ) ) };
}
var r2 = capsule.radius * capsule.radius;
line1 = _line1.set( capsule.start, capsule.end );
var lines = [
[ triangle.a, triangle.b ],
[ triangle.b, triangle.c ],
[ triangle.c, triangle.a ]
];
for ( var i = 0; i < lines.length; i ++ ) {
line2 = _line2.set( lines[ i ][ 0 ], lines[ i ][ 1 ] );
[ point1, point2 ] = capsule.lineLineMinimumPoints( line1, line2 );
if ( point1.distanceToSquared( point2 ) < r2 ) {
return { normal: point1.clone().sub( point2 ).normalize(), point: point2.clone(), depth: capsule.radius - point1.distanceTo( point2 ) };
}
}
return false;
},
triangleSphereIntersect: function ( sphere, triangle ) {
triangle.getPlane( _plane );
if ( ! sphere.intersectsPlane( _plane ) ) return false;
var depth = Math.abs( _plane.distanceToSphere( sphere ) );
var r2 = sphere.radius * sphere.radius - depth * depth;
var plainPoint = _plane.projectPoint( sphere.center, _v1 );
if ( triangle.containsPoint( sphere.center ) ) {
return { normal: _plane.normal.clone(), point: plainPoint.clone(), depth: Math.abs( _plane.distanceToSphere( sphere ) ) };
}
var lines = [
[ triangle.a, triangle.b ],
[ triangle.b, triangle.c ],
[ triangle.c, triangle.a ]
];
for ( var i = 0; i < lines.length; i ++ ) {
_line1.set( lines[ i ][ 0 ], lines[ i ][ 1 ] );
_line1.closestPointToPoint( plainPoint, true, _v2 );
var d = _v2.distanceToSquared( sphere.center );
if ( d < r2 ) {
return { normal: sphere.center.clone().sub( _v2 ).normalize(), point: _v2.clone(), depth: sphere.radius - Math.sqrt( d ) };
}
}
return false;
},
getSphereTriangles: function ( sphere, triangles ) {
for ( var i = 0; i < this.subTrees.length; i ++ ) {
var subTree = this.subTrees[ i ];
if ( ! sphere.intersectsBox( subTree.box ) ) continue;
if ( subTree.triangles.length > 0 ) {
for ( var j = 0; j < subTree.triangles.length; j ++ ) {
if ( triangles.indexOf( subTree.triangles[ j ] ) === - 1 ) triangles.push( subTree.triangles[ j ] );
}
} else {
subTree.getSphereTriangles( sphere, triangles );
}
}
},
getCapsuleTriangles: function ( capsule, triangles ) {
for ( var i = 0; i < this.subTrees.length; i ++ ) {
var subTree = this.subTrees[ i ];
if ( ! capsule.intersectsBox( subTree.box ) ) continue;
if ( subTree.triangles.length > 0 ) {
for ( var j = 0; j < subTree.triangles.length; j ++ ) {
if ( triangles.indexOf( subTree.triangles[ j ] ) === - 1 ) triangles.push( subTree.triangles[ j ] );
}
} else {
subTree.getCapsuleTriangles( capsule, triangles );
}
}
},
sphereIntersect( sphere ) {
_sphere.copy( sphere );
var triangles = [], result, hit = false;
this.getSphereTriangles( sphere, triangles );
for ( var i = 0; i < triangles.length; i ++ ) {
if ( result = this.triangleSphereIntersect( _sphere, triangles[ i ] ) ) {
hit = true;
_sphere.center.add( result.normal.multiplyScalar( result.depth ) );
}
}
if ( hit ) {
var collisionVector = _sphere.center.clone().sub( sphere.center );
var depth = collisionVector.length();
return { normal: collisionVector.normalize(), depth: depth };
}
return false;
},
capsuleIntersect: function ( capsule ) {
_capsule.copy( capsule );
var triangles = [], result, hit = false;
this.getCapsuleTriangles( _capsule, triangles );
for ( var i = 0; i < triangles.length; i ++ ) {
if ( result = this.triangleCapsuleIntersect( _capsule, triangles[ i ] ) ) {
hit = true;
_capsule.translate( result.normal.multiplyScalar( result.depth ) );
}
}
if ( hit ) {
var collisionVector = _capsule.getCenter( new THREE.Vector3() ).sub( capsule.getCenter( _v1 ) );
var depth = collisionVector.length();
return { normal: collisionVector.normalize(), depth: depth };
}
return false;
},
rayIntersect: function ( ray ) {
if ( ray.direction.length() === 0 ) return;
var triangles = [], triangle, position,
distance = 1e100,
result;
this.getRayTriangles( ray, triangles );
for ( var i = 0; i < triangles.length; i ++ ) {
result = ray.intersectTriangle( triangles[ i ].a, triangles[ i ].b, triangles[ i ].c, true, _v1 );
if ( result ) {
var newdistance = result.sub( ray.origin ).length();
if ( distance > newdistance ) {
position = result.clone().add( ray.origin );
distance = newdistance;
triangle = triangles[ i ];
}
}
}
return distance < 1e100 ? { distance: distance, triangle: triangle, position: position } : false;
},
fromGraphNode: function ( group ) {
group.traverse( ( obj ) => {
if ( obj.type === 'Mesh' ) {
obj.updateMatrix();
obj.updateWorldMatrix();
var geometry, isTemp = false;
if ( obj.geometry.index ) {
isTemp = true;
geometry = obj.geometry.clone().toNonIndexed();
} else {
geometry = obj.geometry;
}
var positions = geometry.attributes.position.array;
var transform = obj.matrixWorld;
for ( var i = 0; i < positions.length; i += 9 ) {
var v1 = new THREE.Vector3( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] );
var v2 = new THREE.Vector3( positions[ i + 3 ], positions[ i + 4 ], positions[ i + 5 ] );
var v3 = new THREE.Vector3( positions[ i + 6 ], positions[ i + 7 ], positions[ i + 8 ] );
v1.applyMatrix4( transform );
v2.applyMatrix4( transform );
v3.applyMatrix4( transform );
this.addTriangle( new THREE.Triangle( v1, v2, v3 ) );
}
if ( isTemp ) {
geometry.dispose();
}
}
} );
this.build();
return this;
}
} );
return Octree;
} )();
export { Octree };

View File

@ -0,0 +1,177 @@
export function LessonData() {
let scope = this;
this.lessonId = "";
this.lessonName = "";
this.lessonType = "";
this.lessonStatus = "";
this.lessonData = {
//资源列表
assetList:[],
//场景交互物体列表
modelList:[],
//课程组件启用状态
lessonTools:[],
dataType:"",
toolJobPane:[],
//课程内容
lessonProgress:[
]
};
this.initLessonProgress = function(){
let newLessonProgress = {
id:generateUUID(),
progressName:"命名",
roleName:"",
roleUse:true,
progressScene:"",
nextCode:"",
nextNode:"",
triggerType:"",
triggerMode:"",
triggerTime:"",
triggerModel:"",
controlMode:"",
cameraMode:"",
changeCamera:false,
cameraPosition:{
x:0,
y:0,
z:0
},
cameraTarget:{
x:0,
y:0,
z:0
},
assetId:scope.lessonData.lessonProgress.length,
assetPos:"",
assetRot:"",
assetType:"",
index:"",
stepTipsData:{
tittle:"标题",
text:"内容",
},
explainPane:{
tittle:"标题",
picurl:"url",
text:"内容",
},
action:[],
};
scope.lessonData.lessonProgress.push(newLessonProgress);
}
this.loadLessonProgress = function(loadData){
console.log(loadData);
for(let i=0;i<loadData.length;i++){
let newLessonProgress = {
id:loadData[i].id,
progressName:loadData[i].progressName,
roleName:loadData[i].roleName,
roleUse:loadData[i].roleUse,
score:loadData[i].roleUse,
progressScene:loadData[i].progressScene,
nextCode:loadData[i].nextCode,
nextNode:loadData[i].nextNode,
triggerType:loadData[i].triggerType,
triggerMode:loadData[i].triggerMode,
triggerTime:loadData[i].triggerTime,
triggerModel:loadData[i].triggerModel,
controlMode:loadData[i].controlMode,
cameraMode:loadData[i].cameraMode,
changeCamera:loadData[i].changeCamera,
cameraPosition:loadData[i].cameraPosition,
cameraTarget:loadData[i].cameraTarget,
assetId:loadData[i].assetId,
assetPos:loadData[i].assetPos,
assetRot:loadData[i].assetRot,
assetType:loadData[i].assetType,
index:loadData[i].index,
stepTipsData:loadData[i].stepTipsData,
explainPane:loadData[i].explainPane,
action:loadData[i].action,
jobPane:[],
};
scope.lessonData.lessonProgress.push(newLessonProgress);
}
}
this.addLessonProgress = function(index){
let inheirIndex = index - 1;
let newLessonProgress = {
id:generateUUID(),
progressName:"命名",
roleName:scope.lessonData.lessonProgress[inheirIndex].roleName,
roleUse:scope.lessonData.lessonProgress[inheirIndex].roleUse,
score:0,
progressScene:scope.lessonData.lessonProgress[inheirIndex].progressScene,
nextCode:"",
nextNode:"",
triggerType:"",
triggerMode:"",
triggerTime:"",
triggerModel:"",
controlMode:scope.lessonData.lessonProgress[inheirIndex].controlMode,
cameraMode:scope.lessonData.lessonProgress[inheirIndex].cameraMode,
changeCamera:scope.lessonData.lessonProgress[inheirIndex].changeCamera,
cameraPosition:scope.lessonData.lessonProgress[inheirIndex].cameraPosition,
cameraTarget:scope.lessonData.lessonProgress[inheirIndex].cameraTarget,
assetId:scope.lessonData.lessonProgress.length,
assetPos:"",
assetRot:"",
assetType:"",
index:"",
triger:[
],
stepTipsData:{
tittle:"标题",
text:"内容",
},
explainPane:{
tittle:"标题",
picurl:"url",
text:"内容",
},
action:[
],
jobPane:[],
};
scope.lessonData.lessonProgress.push(newLessonProgress);
}
this.changeLessonProgress = function(){
}
this.removeLessonProgress = function(index){
scope.lessonData.lessonProgress.splice(index,1);
}
function generateUUID() {
var d = new Date().getTime();
if (window.performance && typeof window.performance.now === "function") {
d += performance.now(); //use high-precision timer if available
}
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
return uuid;
}
}

View File

@ -0,0 +1,307 @@
export function JobPaneData() {
let scope = this;
// let
this.dataList = [
{
name:"值班站长",
value:"zbzz",
text:"执行分公司、部、中心、车站的有关规章制度,加强班组管理,掌握列车运行情况,安排车站行车组织工作",
picurl:"",
controlList:[
//联控
{
name:"联控",
data:[],
},
//动作
{
name:"动作",
data:[],
},
//口呼
{
name:"口呼",
data:[],
},
],
},
{
name:"行车值班员",
value:"xczby",
text:"在本班组值班站长的指挥下开展工作,负责本班组车站综合控制室,负责车站行车工作,监视列车到、发情况及乘客上下车、候车动态,监控设备运作状况。",
picurl:"",
controlList:[
//联控
{
name:"联控",
data:[],
},
//动作
{
name:"动作",
data:[],
},
//口呼
{
name:"口呼",
data:[],
},
],
},
{
name:"客运值班员",
value:"kyzby",
text:"在值班站长的领导下,主管车站客运、票务管理,组织站务员从事客运服务工作",
picurl:"",
controlList:[
//联控
{
name:"联控",
data:[],
},
//动作
{
name:"动作",
data:[],
},
//口呼
{
name:"口呼",
data:[],
},
],
},
{
name:"票厅员",
value:"spy",
text:"执行分公司、部、中心、车站的有关规章制度,在客运值班员领导下,负责车站售票工作。",
picurl:"",
controlList:[
//联控
{
name:"联控",
data:[],
},
//动作
{
name:"动作",
data:[],
},
//口呼
{
name:"口呼",
data:[],
},
],
},
{
name:"站台岗",
value:"ztg",
text:"",
picurl:"",
controlList:[
//联控
{
name:"联控",
data:[],
},
//动作
{
name:"动作",
data:[],
},
//口呼
{
name:"口呼",
data:[],
},
],
},
{
name:"站长",
value:"zz",
text:"在站务中心(副)主任领导下,组织领导站内员工开展车站各项工作。负责车站员工的日常管理,定期进行员工教育,掌握员工思想状况。",
picurl:"",
controlList:[
//联控
{
name:"联控",
data:[],
},
//动作
{
name:"动作",
data:[],
},
//口呼
{
name:"口呼",
data:[],
},
],
},
{
name:"分部助理",
value:"fbzl",
text:"",
picurl:"",
controlList:[
//联控
{
name:"联控",
data:[],
},
//动作
{
name:"动作",
data:[],
},
//口呼
{
name:"口呼",
data:[],
},
],
},
{
name:"行车调度",
value:"xcdd",
text:"",
picurl:"",
controlList:[
//联控
{
name:"联控",
data:[],
},
//动作
{
name:"动作",
data:[],
},
//口呼
{
name:"口呼",
data:[],
},
],
},
{
name:"生产调度",
value:"scdd",
text:"",
picurl:"",
controlList:[
//联控
{
name:"联控",
data:[],
},
//动作
{
name:"动作",
data:[],
},
//口呼
{
name:"口呼",
data:[],
},
],
},
{
name:"平台岗",
value:"ptg",
text:"负责站厅乘客服务,设备的巡视、紧急情况下事件的处理等。",
picurl:"",
controlList:[
//联控
{
name:"联控",
data:[],
},
//动作
{
name:"动作",
data:[],
},
//口呼
{
name:"口呼",
data:[],
},
],
},
{
name:"地铁公安",
value:"110",
text:"",
picurl:"",
controlList:[
//联控
{
name:"联控",
data:[],
},
//动作
{
name:"动作",
data:[],
},
//口呼
{
name:"口呼",
data:[],
},
],
},
{
name:"120",
value:"120",
text:"",
picurl:"",
controlList:[
//联控
{
name:"联控",
data:[],
},
//动作
{
name:"动作",
data:[],
},
//口呼
{
name:"口呼",
data:[],
},
],
},
{
name:"119",
value:"119",
text:"",
picurl:"",
controlList:[
//联控
{
name:"联控",
data:[],
},
//动作
{
name:"动作",
data:[],
},
//口呼
{
name:"口呼",
data:[],
},
],
},
];
}

View File

@ -0,0 +1,32 @@
export function LessonTrigger() {
let scope = this;
this.dataList = [
];
// let
this.triggerList = [
{
name:"移动触发器",
type:"movetrigger",
picurl:"",
},
{
name:"置物触发器",
type:"placetrigger",
picurl:"",
},
];
this.createTrigger = function(type){
}
this.deleteTrigger = function(selected){
}
}

View File

@ -24,7 +24,7 @@ export function LessonData() {
this.initLessonProgress = function(){
let newLessonProgress = {
id:generateUUID(),
progressName:"",
progressName:"命名",
roleName:"",
roleUse:true,
@ -37,8 +37,17 @@ export function LessonData() {
triggerModel:"",
controlMode:"",
cameraMode:"",
cameraPosition:"",
cameraTarget:"",
changeCamera:false,
cameraPosition:{
x:0,
y:0,
z:0
},
cameraTarget:{
x:0,
y:0,
z:0
},
assetId:scope.lessonData.lessonProgress.length,
assetPos:"",
assetRot:"",
@ -78,6 +87,7 @@ export function LessonData() {
triggerModel:loadData[i].triggerModel,
controlMode:loadData[i].controlMode,
cameraMode:loadData[i].cameraMode,
changeCamera:loadData[i].changeCamera,
cameraPosition:loadData[i].cameraPosition,
cameraTarget:loadData[i].cameraTarget,
assetId:loadData[i].assetId,
@ -99,7 +109,7 @@ export function LessonData() {
let inheirIndex = index - 1;
let newLessonProgress = {
id:generateUUID(),
progressName:"",
progressName:"命名",
roleName:scope.lessonData.lessonProgress[inheirIndex].roleName,
roleUse:scope.lessonData.lessonProgress[inheirIndex].roleUse,
score:0,
@ -112,6 +122,7 @@ export function LessonData() {
triggerModel:"",
controlMode:scope.lessonData.lessonProgress[inheirIndex].controlMode,
cameraMode:scope.lessonData.lessonProgress[inheirIndex].cameraMode,
changeCamera:scope.lessonData.lessonProgress[inheirIndex].changeCamera,
cameraPosition:scope.lessonData.lessonProgress[inheirIndex].cameraPosition,
cameraTarget:scope.lessonData.lessonProgress[inheirIndex].cameraTarget,
assetId:scope.lessonData.lessonProgress.length,

View File

@ -6,6 +6,7 @@ export function JobPaneData() {
this.dataList = [
{
name:"值班站长",
value:"zbzz",
text:"执行分公司、部、中心、车站的有关规章制度,加强班组管理,掌握列车运行情况,安排车站行车组织工作",
picurl:"",
controlList:[
@ -28,6 +29,7 @@ export function JobPaneData() {
},
{
name:"行车值班员",
value:"xczby",
text:"在本班组值班站长的指挥下开展工作,负责本班组车站综合控制室,负责车站行车工作,监视列车到、发情况及乘客上下车、候车动态,监控设备运作状况。",
picurl:"",
controlList:[
@ -50,6 +52,7 @@ export function JobPaneData() {
},
{
name:"客运值班员",
value:"kyzby",
text:"在值班站长的领导下,主管车站客运、票务管理,组织站务员从事客运服务工作",
picurl:"",
controlList:[
@ -71,7 +74,8 @@ export function JobPaneData() {
],
},
{
name:"票厅岗",
name:"票厅员",
value:"spy",
text:"执行分公司、部、中心、车站的有关规章制度,在客运值班员领导下,负责车站售票工作。",
picurl:"",
controlList:[
@ -94,6 +98,7 @@ export function JobPaneData() {
},
{
name:"站台岗",
value:"ztg",
text:"",
picurl:"",
controlList:[
@ -116,6 +121,7 @@ export function JobPaneData() {
},
{
name:"站长",
value:"zz",
text:"在站务中心(副)主任领导下,组织领导站内员工开展车站各项工作。负责车站员工的日常管理,定期进行员工教育,掌握员工思想状况。",
picurl:"",
controlList:[
@ -138,6 +144,7 @@ export function JobPaneData() {
},
{
name:"分部助理",
value:"fbzl",
text:"",
picurl:"",
controlList:[
@ -160,6 +167,7 @@ export function JobPaneData() {
},
{
name:"行车调度",
value:"xcdd",
text:"",
picurl:"",
controlList:[
@ -182,6 +190,7 @@ export function JobPaneData() {
},
{
name:"生产调度",
value:"scdd",
text:"",
picurl:"",
controlList:[
@ -203,7 +212,8 @@ export function JobPaneData() {
],
},
{
name:"厅巡岗",
name:"平台岗",
value:"ptg",
text:"负责站厅乘客服务,设备的巡视、紧急情况下事件的处理等。",
picurl:"",
controlList:[
@ -226,6 +236,7 @@ export function JobPaneData() {
},
{
name:"地铁公安",
value:"110",
text:"",
picurl:"",
controlList:[
@ -248,6 +259,7 @@ export function JobPaneData() {
},
{
name:"120",
value:"120",
text:"",
picurl:"",
controlList:[
@ -270,6 +282,7 @@ export function JobPaneData() {
},
{
name:"119",
value:"119",
text:"",
picurl:"",
controlList:[

View File

@ -6,11 +6,13 @@
<el-tab-pane label="课程场景" name="progresslist" >
<draggable v-model="lessonData.lessonData.lessonProgress" group="people" @start="drag=true" @end="drag=false" >
<div class="progressdiv" v-for="(element,index) in lessonData.lessonData.lessonProgress">
<div class="changeprogressdiv" @click="changeProgressView(index)">{{element.assetId}}</div>
<div class="changeprogressdiv" @click="changeProgressView(index)">{{element.progressName}}</div>
<div class="delprogressdiv" @click="removeProgress(index)" >X</div>
</div>
</draggable>
<div class="progressdiv " icon="el-icon-folder-add" @click="addProgress"></div>
<div class="progressdiv "
:style="{'background-image': 'url('+localstatic+'/lesson3d/addbutton.png)'}"
icon="el-icon-folder-add" @click="addProgress"></div>
</el-tab-pane>
<el-tab-pane label="课程三维资源列表" name="assetlist" >
@ -33,6 +35,7 @@
import localStore from 'storejs';
import draggable from 'vuedraggable';
import { JL3D_LOCAL_STATIC } from '@/api/jlmap3d/assets3d.js';
export default {
name: 'LessonProgress',
@ -42,6 +45,7 @@
},
data() {
return {
localstatic:JL3D_LOCAL_STATIC,
activeName: 'progresslist',
progressList:[
@ -122,6 +126,7 @@
margin: 20px;
float:left;
border:solid 2px #000;
background-size: 100%;
}
.changeprogressdiv{

View File

@ -4,53 +4,83 @@
<el-tabs v-model="activeName" class="activediv" type="card" @tab-click="handleClick">
<el-tab-pane label="当前场景信息" name="cameraproperty">
<el-form ref="form" class="camerapropertydiv" size="mini" v-if="selectLesson3dControl">
<el-form-item label="场景名称:" v-if="lessonData.lessonData.lessonProgress[lessonEditIndex].progressName" disabled="true">
<el-input v-model="lessonData.lessonData.lessonProgress[lessonEditIndex].progressName" ></el-input>
</el-form-item>
<el-form-item label="三维场景设置:">
<el-select v-model="lessonData.lessonData.lessonProgress[lessonEditIndex].progressScene" placeholder="请选择场景">
<el-option label="车站" value="standstation"></el-option>
<el-option label="停车场" value="stopstation"></el-option>
<el-option label="单体设备" value="device"></el-option>
<el-option label="线路" value="xl"></el-option>
<el-option label="道岔" value="dc"></el-option>
<el-option v-for="sceneItem in sceneDataList" :label="sceneItem.label" :value="sceneItem.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="课程角色:">
<el-switch
v-model="lessonData.lessonData.lessonProgress[lessonEditIndex].roleUse"
active-text="启用角色"
inactive-text="禁用角色">
</el-switch>
</el-form-item>
<el-form-item label="场景角色设置:">
<el-select v-model="lessonData.lessonData.lessonProgress[lessonEditIndex].roleName" :disabled="!lessonData.lessonData.lessonProgress[lessonEditIndex].roleUse" placeholder="请选择步骤归属角色">
<el-option v-for="jobItem in jobDataList" :label="jobItem.name" :value="jobItem.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="课程场景相机设置:">
<el-switch
v-model="lessonData.lessonData.lessonProgress[lessonEditIndex].changeCamera"
active-text="场景改变视角"
inactive-text="禁用改变视角">
</el-switch>
</el-form-item>
<el-switch
v-model="lessonData.lessonData.lessonProgress[lessonEditIndex].roleUse"
active-text="启用角色"
inactive-text="禁用角色">
</el-switch>
<el-select v-model="lessonData.lessonData.lessonProgress[lessonEditIndex].roleName" :disabled="!lessonData.lessonData.lessonProgress[lessonEditIndex].roleUse" placeholder="请选择步骤归属角色">
<el-option label="车站" value="standstation"></el-option>
<el-option label="停车场" value="stopstation"></el-option>
<el-option label="单体设备" value="device"></el-option>
<el-option label="线路" value="xl"></el-option>
<el-option label="道岔" value="dc"></el-option>
</el-select>
<el-form-item label="相机坐标:" v-if="selectLesson3dControl.object.position" disabled="true">
<el-input v-model="selectLesson3dControl.object.position.x" ></el-input>
<el-input v-model="selectLesson3dControl.object.position.y" ></el-input>
<el-input v-model="selectLesson3dControl.object.position.z" ></el-input>
</el-form-item>
<el-form-item label="相机角度:" v-if="selectLesson3dControl.target" disabled="true">
<el-input v-model="selectLesson3dControl.target.x" ></el-input>
<el-input v-model="selectLesson3dControl.target.y" ></el-input>
<el-input v-model="selectLesson3dControl.target.z" ></el-input>
</el-form-item>
<el-select v-model="value" placeholder="当前场景镜头控制模式">
<el-option
v-for="item in cameraMode"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
<el-form-item label="该场景中用户操作模式:">
<el-select v-model="lessonData.lessonData.lessonProgress[lessonEditIndex].controlMode" placeholder="当前场景镜头控制模式">
<el-option
v-for="item in cameraMode"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-button v-if="selectLesson3dControl" @click="resetCamera">重置镜头位置</el-button>
<el-button v-if="selectLesson3dControl" @click="recordCamera">记录初始镜头位置</el-button>
<el-button v-if="selectLesson3dControl" @click="recordCamera">记录初始镜头位置</el-button>
<el-form-item label="保存的相机坐标:" v-if="lessonData.lessonData.lessonProgress[lessonEditIndex].cameraPosition" disabled="true">
<el-input v-model="lessonData.lessonData.lessonProgress[lessonEditIndex].cameraPosition.x" ></el-input>
<el-input v-model="lessonData.lessonData.lessonProgress[lessonEditIndex].cameraPosition.y" ></el-input>
<el-input v-model="lessonData.lessonData.lessonProgress[lessonEditIndex].cameraPosition.z" ></el-input>
</el-form-item>
<el-form-item label="保存的相机角度:" v-if="lessonData.lessonData.lessonProgress[lessonEditIndex].cameraTarget" disabled="true">
<el-input v-model="lessonData.lessonData.lessonProgress[lessonEditIndex].cameraTarget.x" ></el-input>
<el-input v-model="lessonData.lessonData.lessonProgress[lessonEditIndex].cameraTarget.y" ></el-input>
<el-input v-model="lessonData.lessonData.lessonProgress[lessonEditIndex].cameraTarget.z" ></el-input>
</el-form-item>
</el-form>
</el-tab-pane>
@ -59,7 +89,9 @@
<div class="addmodeleventdiv"
v-for="(actionitem,actionindex) in lessonData.lessonData.lessonProgress[lessonEditIndex].action"
@click="selsectAction(actionitem)">{{actionitem.actionName}}</div>
<div class="addmodeleventdiv" @click="addaction()">添加</div>
<div class="addmodeleventdiv"
:style="{'background-image': 'url('+localstatic+'/lesson3d/addbutton.png)'}"
@click="addaction()"></div>
</div>
<el-form>
@ -69,12 +101,12 @@
<el-form-item label="操作的模型:" >
<el-select v-model="selectedAction.actionModel" placeholder="选择操作的模型">
<el-option
v-for="(item,index) in triggerList"
:label="item.label"
:value="item.label">
</el-option>
</el-select>
<el-option
v-for="(item,index) in triggerList"
:label="item.label"
:value="item.label">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="事件类型:" >
@ -82,7 +114,7 @@
<el-option label="接触" value="contact"></el-option>
<el-option label="自动" value="auto"></el-option>
<el-option label="开关" value="switch"></el-option>
<el-option label="跳转" value="jump"></el-option>
</el-select>
</el-form-item>
@ -91,6 +123,7 @@
<el-option label="播放动画" value="play"></el-option>
<el-option label="显示模型" value="show"></el-option>
<el-option label="隐藏模型" value="remove"></el-option>
<el-option label="跳转" value="jump"></el-option>
</el-select>
</el-form-item>
@ -98,17 +131,19 @@
<el-form-item label="跳转节点:" v-if="selectedAction.actionType == 'jump'">
<el-form-item label="跳转节点:" v-if="selectedAction.actionMode == 'jump'">
<el-select v-model="selectedAction.jumpNode" placeholder="当前场景镜头控制模式">
<el-option
v-for="(item,index) in lessonData.lessonData.lessonProgress"
:key="index"
:label="index"
:label="item.progressName+'/'+index"
:value="index">
</el-option>
</el-select>
</el-form-item>
<el-button @click="deleteEventItem(selectedAction)" v-if="selectedAction">删除事件</el-button>
</el-form>
</el-tab-pane>
@ -118,6 +153,12 @@
<el-input v-model="selected.tittle" ></el-input>
</el-form-item>
<el-form-item label="发起联控角色:" v-if="selected.explainRole" >
<el-select v-model="selected.explainRole" placeholder="请选择步骤归属角色">
<el-option v-for="jobItem in jobDataList" :label="jobItem.name" :value="jobItem.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="内容:" v-if="selected.text">
<el-input v-model="selected.text" ></el-input>
</el-form-item>
@ -131,19 +172,21 @@
<el-option
v-for="(item,index) in lessonData.lessonData.lessonProgress"
:key="index"
:label="index"
:label="item.progressName+'/'+index"
:value="index">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="触发的场景:" v-if="selected.sceneIndex ||selected.sceneIndex == 0">
<el-input v-model="selected.sceneIndex" ></el-input>
</el-form-item>
<el-button @click="updateData">保存修改</el-button>
<el-button @click="deleteJobItem(selected)" v-if="selected.explainRole">删除联控信息</el-button>
<!-- <el-button @click="updateData">保存修改</el-button> -->
</el-form>
<el-form ref="form" class="camerapropertydiv" label-width="130px" size="mini" v-if="selectType == 'modelproperty'">
@ -156,6 +199,7 @@
<el-option label="隐藏" :value=false></el-option>
</el-select>
<el-form-item label="模型坐标:" v-if="selected.position" disabled="true">
<el-input v-model="selected.position.x" ></el-input>
<el-input v-model="selected.position.y" ></el-input>
@ -184,6 +228,8 @@
import Vue from 'vue';
import localStore from 'storejs';
import { JobPaneData } from '@/jlmap3d/lesson3dedit/toolsmodel/jobpanedata.js';
import { JL3D_LOCAL_STATIC } from '@/api/jlmap3d/assets3d.js';
export default {
name: 'ProPerty',
@ -193,6 +239,7 @@
},
data() {
return {
localstatic:JL3D_LOCAL_STATIC,
activeName: 'cameraproperty',
selectLesson3dControl:"",
selected:"",
@ -204,6 +251,7 @@
actionType:"事件操作类型",
actionMode:"触发事件类型",
},
revisionList:[],
selectType:"",
cameraMode:[
{
@ -217,6 +265,29 @@
label: '自由视角控制'
}
],
sceneDataList:[
{
label:"车站",
value:"standstation",
},
{
label:"停车场",
value:"stopstation",
},
{
label:"单体设备",
value:"device",
},
{
label:"线路",
value:"xl",
},
{
label:"道岔",
value:"dc",
},
],
jobDataList:[],
value:'',
}
},
@ -230,6 +301,9 @@
window.lesson3dUpdateControl = this.lesson3dUpdateControl;
window.lesson3dSelect = this.lesson3dSelect;
window.lesson3dUpdatePicurl = this.lesson3dUpdatePicurl;
let jobList = new JobPaneData();
this.jobDataList = jobList.dataList;
},
beforeDestroy() {
@ -247,7 +321,7 @@
console.log("reset");
this.activeName = 'cameraproperty';
},
lesson3dSelect(mode,type,obj){
lesson3dSelect(mode,type,obj,revisionlist){
this.activeName = mode;
this.selectType = type;
// console.log(this.lessonData.lessonData.lessonProgress[this.lessonEditIndex].stepTipsData);
@ -263,6 +337,7 @@
if(type == "jobpane"){
this.selected = obj;
this.revisionList = revisionlist;
}
if(type == "modelproperty"){
@ -274,11 +349,46 @@
updateData(){
// this.lessonData.lessonData.lessonProgress[this.lessonEditIndex].stepTipsData;
},
deleteJobItem(selectedJob){
console.log(selectedJob);
for(let i=0;i<this.revisionList.data.length;i++){
if(this.revisionList.data[i].cname == selectedJob.cname){
console.log(selectedJob);
this.revisionList.data.splice(i,1);
break;
}
}
},
deleteEventItem(deleteAction){
console.log(this.lessonData.lessonData.lessonProgress[this.lessonEditIndex].action);
console.log(deleteAction);
for(let i=0;i<this.lessonData.lessonData.lessonProgress[this.lessonEditIndex].action.length;i++){
if(this.lessonData.lessonData.lessonProgress[this.lessonEditIndex].action[i].actionName == deleteAction.actionName){
this.lessonData.lessonData.lessonProgress[this.lessonEditIndex].action.splice(i,1);
break;
}
}
},
resetCamera(){
this.selectLesson3dControl.object.position.x = 40;
this.selectLesson3dControl.object.position.y = 80;
this.selectLesson3dControl.object.position.z = 0;
this.selectLesson3dControl.target = new THREE.Vector3(0,0,0);
},
recordCamera(){
let newPos = {
x:this.selectLesson3dControl.object.position.x,
y:this.selectLesson3dControl.object.position.y,
z:this.selectLesson3dControl.object.position.z,
};
this.lessonData.lessonData.lessonProgress[this.lessonEditIndex].cameraPosition = newPos;
let newTarget = {
x:this.selectLesson3dControl.target.x,
y:this.selectLesson3dControl.target.y,
z:this.selectLesson3dControl.target.z,
};
this.lessonData.lessonData.lessonProgress[this.lessonEditIndex].cameraTarget = newTarget;
},
lesson3dUpdatePicurl(picAsset){
if(this.selectType == "explainpane"){
@ -350,9 +460,10 @@
.addmodeleventdiv{
width:98%;
height:50px;
height:64px;
margin: 1%;
border:solid 2px #000;
background-repeat: no-repeat;
}
</style>

View File

@ -13,8 +13,12 @@
<div class="eltabpaneover" >
<el-tabs >
<el-tab-pane v-for="(item,index) in selectedJob.controlList" label-width="33%" :key="item.name" :label="item.name" >
<div class="addjobdivs" v-for="(itemin,indexin) in selectedJob.controlList[index].data" @click="selsectJobTool(itemin)">{{itemin.text}}</div>
<div class="addjobdiv" @click="addjob(index)">添加</div>
<div class="addjobdivs" v-for="(itemin,indexin) in selectedJob.controlList[index].data" @click="selsectJobTool(itemin,selectedJob.controlList[index])">
{{itemin.text}}
</div>
<div class="addjobdiv"
:style="{'background-image': 'url('+localstatic+'/lesson3d/addbutton.png)'}"
@click="addjob(index)"></div>
</el-tab-pane>
</el-tabs>
</div>
@ -39,6 +43,7 @@
},
data() {
return {
localstatic:JL3D_LOCAL_STATIC,
jobList:[],
showJobList:false,
showJob:false,
@ -79,17 +84,30 @@
},
addjob(index){
this.selectedJob.controlList[index].data.push({
cname:"1",
cname:this.generateUUID(),
text:"123",
explainRole:"角色",
nextNode:"null",
sceneId:this.lessonData.lessonData.lessonProgress[this.lessonEditIndex].id,
type:"",
});
},
selsectJobTool(selectTool){
lesson3dSelect('toolproperty','jobpane',selectTool);
selsectJobTool(selectTool,jobList){
lesson3dSelect('toolproperty','jobpane',selectTool,jobList);
console.log(selectTool);
},
generateUUID() {
var d = new Date().getTime();
if (window.performance && typeof window.performance.now === "function") {
d += performance.now(); //use high-precision timer if available
}
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
return uuid;
},
},
}
@ -195,12 +213,16 @@
border:solid 2px #000;
}
.addjobdiv{
width:98%;
height:50px;
height:64px;
margin: 1%;
border:solid 2px #000;
background-repeat: no-repeat;
}
</style>

View File

@ -135,7 +135,7 @@
bottom:0;
border-radius:10px;
border:solid 2px #000;
background-color: #fff;
// background-color: #fff;
z-index:1;
}

View File

@ -5,29 +5,29 @@
<div class="lesson3dplayer">
<Step-Tips
:lessonData='lessonData'
:lessonEditIndex='lessonEditIndex'
v-show="lessonTools[0].isShow && lessonData.lessonData.lessonProgress[lessonEditIndex].progressScene == 'standstation'">
:lessonPlayIndex='lessonPlayIndex'
v-show="lessonTools[0].isShow && lessonData.lessonData.lessonProgress[lessonPlayIndex].progressScene == 'standstation'">
</Step-Tips>
<Process-Log
v-show="lessonTools[1].isShow && lessonData.lessonData.lessonProgress[lessonEditIndex].progressScene == 'standstation'">
v-show="lessonTools[1].isShow && lessonData.lessonData.lessonProgress[lessonPlayIndex].progressScene == 'standstation'">
</Process-Log>
<Explain-Pane
:lessonData='lessonData'
:lessonEditIndex='lessonEditIndex'
v-show="lessonTools[2].isShow && lessonData.lessonData.lessonProgress[lessonEditIndex].progressScene == 'standstation'">
:lessonPlayIndex='lessonPlayIndex'
v-show="lessonTools[2].isShow && lessonData.lessonData.lessonProgress[lessonPlayIndex].progressScene == 'standstation'">
</Explain-Pane>
<Job-Pane
:jobPaneData='jobPaneData'
:lessonData='lessonData'
:lessonEditIndex='lessonEditIndex'
:lessonPlayIndex='lessonPlayIndex'
ref="jobpane"
v-show="lessonTools[3].isShow && lessonData.lessonData.lessonProgress[lessonEditIndex].progressScene == 'standstation'">
v-show="lessonTools[3].isShow && lessonData.lessonData.lessonProgress[lessonPlayIndex].progressScene == 'standstation'">
</Job-Pane>
<Tool-Bar v-show="lessonTools[4].isShow && lessonData.lessonData.lessonProgress[lessonEditIndex].progressScene == 'standstation'"></Tool-Bar>
<Tool-Bar v-show="lessonTools[4].isShow && lessonData.lessonData.lessonProgress[lessonPlayIndex].progressScene == 'standstation'"></Tool-Bar>
<div id="lesson3ddraw" class="lesson3ddraw">
</div>
@ -50,10 +50,10 @@
import ToolBar from '@/views/jlmap3d/lesson3dplayer/tools/toolbar';
import { Lesson3dEditor } from '@/jlmap3d/lesson3dedit/lesson3deditor.js';
import { Lesson3dPlayer } from '@/jlmap3d/lesson3d/lesson3dplayer.js';
import { LessonData } from '@/jlmap3d/lesson3dedit/model/lessondata.js';
import { JobPaneData } from '@/jlmap3d/lesson3dedit/toolsmodel/jobpanedata.js';
import { LessonData } from '@/jlmap3d/lesson3d/model/lessondata.js';
import { JobPaneData } from '@/jlmap3d/lesson3d/toolsmodel/jobpanedata.js';
import { getLesson3dData,updateLesson3dData } from '@/api/jmap/lesson3d';
export default {
@ -85,7 +85,7 @@
}
},
jobPaneData:{},
lessonEditIndex:0,
lessonPlayIndex:0,
lessonTools:[
{
name:"步骤组件",
@ -118,7 +118,8 @@
},
mounted() {
window.updateTriggerList = this.updateTriggerList;
window.jumpEvent = this.jumpEvent;
window.actionEvent = this.actionEvent;
this.init(this.$route.query.lessonId);
},
beforeDestroy() {
@ -138,7 +139,6 @@
let loadData;
if(data.data.data){
loadData = JSON.parse(data.data.data);
console.log(loadData);
this.jobPaneData.dataList = loadData.toolJobPane;
this.$refs.jobpane.initJobList(this.jobPaneData.dataList);
@ -151,7 +151,7 @@
}
console.log("loaddata----------------");
console.log(loadData);
this.jl3d = new Lesson3dEditor(dom,loadData);
this.jl3d = new Lesson3dPlayer(dom,loadData,this.lessonPlayIndex);
}).catch(() => {
});
},
@ -173,7 +173,19 @@
});
},
jumpEvent(type,action){
if(type == "action"){
this.lessonPlayIndex = action.jumpNode;
}
if(type == "tools"){
this.lessonPlayIndex = action.nextNode;
}
},
actionEvent(type,action,mesh){
if(type == "remove"){
this.jl3d.actionRemove(mesh);
}
},
updateTriggerList(newTriggerList){
this.triggerList = newTriggerList;
console.log(this.triggerList);

View File

@ -1,13 +1,16 @@
<template>
<div class="explainpanediv" v-if="lessonData.lessonData.lessonProgress[lessonEditIndex]" @click="selectTool">
<div class="explainpanediv"
v-if="lessonData.lessonData.lessonProgress[lessonPlayIndex]"
@click="selectTool"
:style="{'background-image': 'url('+lessonbg+')'}">
<div class="explainpanetittle" >
{{lessonData.lessonData.lessonProgress[lessonEditIndex].explainPane.tittle}}
{{lessonData.lessonData.lessonProgress[lessonPlayIndex].explainPane.tittle}}
</div>
<div class="explainpanepic" :style="{'background-image': 'url('+localStatic+lessonData.lessonData.lessonProgress[lessonEditIndex].explainPane.picurl+')'}" >
<div class="explainpanepic" :style="{'background-image': 'url('+localStatic+lessonData.lessonData.lessonProgress[lessonPlayIndex].explainPane.picurl+')'}" >
</div>
<div class="explainpanetext" >
{{lessonData.lessonData.lessonProgress[lessonEditIndex].explainPane.text}}
{{lessonData.lessonData.lessonProgress[lessonPlayIndex].explainPane.text}}
</div>
</div>
</template>
@ -19,13 +22,14 @@
export default {
name: 'ExplainPane',
props:['lessonData','lessonEditIndex'],
props:['lessonData','lessonPlayIndex'],
components: {
},
data() {
return {
localStatic:BASE_ASSET_API,
lessonbg:JL3D_LOCAL_STATIC+"/lesson3d/lessonbg.png",
}
},
computed: {
@ -60,7 +64,7 @@
top:0;
border-radius:10px;
border:solid 2px #000;
background-color: #fff;
color:#fff;
z-index:1;
}
.explainpanetittle{
@ -70,12 +74,18 @@
}
.explainpanepic{
position:relative;
width:90%;
left:5%;
height:65%;
border:solid 2px #000;
background-size: 100%;
}
.explainpanetext{
position:relative;
left:5%;
width:90%;
font-size: 14px;
// height:20%;
}

View File

@ -1,20 +1,36 @@
<template>
<div class="jobpanediv">
<div class="jobshowbutton" @click="openList">岗位联络</div>
<div class="joblistdiv" v-show="showJobList">
<div class="jobdiv" v-for="(jobitem,index) in jobList" @click="selectJob(jobitem)" >{{jobitem.name}}</div>
<div class="jobshowbutton" @click="openList"
:style="{'background-image': 'url('+lessonbg+')'}">
<div class="jobshowbuttonpic" :style="{'background-image': 'url('+lkgwbg+')'}">
</div>
</div>
<div class="jobtab" v-if="selectedJob">
<div class="joblistdiv" v-show="showJobList"
:style="{'background-image': 'url('+lessonbg+')'}">
<div class="jobdiv" v-for="(jobitem,index) in jobList" @click="selectJob(jobitem)" >
<img :src="jobpic" />
<div class="jobdivtext" >{{jobitem.name}}</div>
</div>
</div>
<div class="jobtab" v-if="selectedJob"
:style="{'background-image': 'url('+lessonbg+')'}">
<div class="jobtabmsg" >
<div class="jobtabmsgdiv" >{{selectedJob.name}}</div>
<div class="jobtabmsgdiv" >
<img :src="jobpic" />
<div class="jobdivtext" >{{selectedJob.name}}</div>
</div>
<div class="jobtabmsgtext" >{{selectedJob.text}}</div>
</div>
<div class="eltabpaneover" >
<el-tabs >
<el-tab-pane v-for="(item,index) in selectedJob.controlList" label-width="33%" :key="item.name" :label="item.name" >
<el-tab-pane v-for="(item,index) in selectedJob.controlList"
style="color:#fff"label-width="33%" :key="item.name" :label="item.name" >
<div class="addjobdivs" v-for="(itemin,indexin) in selectedJob.controlList[index].data" @click="selsectJobTool(itemin)">{{itemin.text}}</div>
<div class="addjobdiv" @click="addjob(index)">添加</div>
</el-tab-pane>
</el-tabs>
</div>
@ -32,13 +48,16 @@
//
export default {
name: 'JobPane',
props:['jobPaneData','lessonData','lessonEditIndex'],
props:['jobPaneData','lessonData','lessonPlayIndex'],
components: {
},
data() {
return {
lessonbg:JL3D_LOCAL_STATIC+"/lesson3d/lessonbg.png",
lkgwbg:JL3D_LOCAL_STATIC+"/lesson3d/lkgw.png",
jobpic:JL3D_LOCAL_STATIC+"/lesson3d/jobpic.png",
jobList:[],
showJobList:false,
showJob:false,
@ -70,25 +89,20 @@
},
initJobList(data){
this.jobList = data;
console.log(data);
},
selectJob(item){
console.log(item);
this.selectedJob = item;
},
},
addjob(index){
this.selectedJob.controlList[index].data.push({
cname:"1",
text:"123",
nextNode:"null",
sceneId:this.lessonData.lessonData.lessonProgress[this.lessonEditIndex].id,
type:"",
});
},
selsectJobTool(selectTool){
lesson3dSelect('toolproperty','jobpane',selectTool);
console.log(selectTool);
console.log(this.lessonData.lessonData.lessonProgress[this.lessonPlayIndex]);
let nowProgress = this.lessonData.lessonData.lessonProgress[this.lessonPlayIndex];
if(selectTool.sceneId == nowProgress.id){
jumpEvent("tools",selectTool);
}
// console.log(this.lessonData.lessonProgress[this.lessonPlayIndex]);
},
},
@ -105,10 +119,18 @@
right:0;
top:0;
// border:solid 2px #000;
text-align: center;
z-index:1;
}
.jobshowbuttonpic{
width: 100%;
height: 100%;
background-size: 100%;
background-size: cover;
background-repeat: no-repeat;
}
.jobshowbutton{
position: absolute;
width:100px;
@ -116,9 +138,12 @@
right:0;
top:0;
border:solid 2px #000;
background-color: #fff;
// background-color: #fff;
color:#fff;
}
.el-tabs__item{
color:'#fff'
}
.joblistdiv{
position: absolute;
width:100px;
@ -128,16 +153,22 @@
border:solid 2px #000;
overflow-y: auto;
overflow-x: hidden;
background-color: #fff;
color:#fff;
}
.jobdiv{
width:75px;
height:75px;
height:90px;
margin-top: 5px;
margin-left: 2px;
border:solid 2px #000;
background-color: #fff;
color:#fff;
}
.jobdivtext{
// position: absolute;
bottom: 0;
font-size: 13px;
text-align: center;
}
@ -148,7 +179,7 @@
top:50px;
width: 300px;
height:450px;
background-color: #fff;
color:#fff;
}
.eltabpaneover{
@ -167,21 +198,21 @@
.jobtabmsgdiv{
width:80px;
height:80px;
height:90px;
position:absolute;
top:10px;
left:5px;
border:solid 2px #000;
background-color: #fff;
color:#fff;
}
.jobtabmsgtext{
width:200px;
height:80px;
height:90px;
// margin-top: 5px;
// margin-left: 2px;
border:solid 2px #000;
background-color: #fff;
color:#fff;
position: absolute;
font-size: 12px;
right:10px;

View File

@ -68,7 +68,9 @@
bottom:0;
// border-radius:10px;
border:solid 2px #000;
background-color: #fff;
background-color: #000080;
opacity: 0.6;
color:#fff;
z-index:1;
}
.processtext{

View File

@ -1,10 +1,13 @@
<template>
<div class="stepstipsdiv" v-if="lessonData.lessonData.lessonProgress[lessonEditIndex]" @click="selectTool">
<div class="stepstipsdiv"
v-if="lessonData.lessonData.lessonProgress[lessonPlayIndex]"
@click="selectTool"
:style="{'background-image': 'url('+lessonbg+')'}">
<div class="stepstipstittle" >
{{lessonData.lessonData.lessonProgress[lessonEditIndex].stepTipsData.tittle}}
{{lessonData.lessonData.lessonProgress[lessonPlayIndex].stepTipsData.tittle}}
</div>
<div class="stepstipstext" >
{{lessonData.lessonData.lessonProgress[lessonEditIndex].stepTipsData.text}}
{{lessonData.lessonData.lessonProgress[lessonPlayIndex].stepTipsData.text}}
</div>
</div>
</template>
@ -15,13 +18,13 @@
//
export default {
name: 'StepTips',
props:['lessonData','lessonEditIndex'],
props:['lessonData','lessonPlayIndex'],
components: {
},
data() {
return {
lessonbg:JL3D_LOCAL_STATIC+"/lesson3d/lessonbg.png",
}
},
computed: {
@ -60,7 +63,9 @@
top:0;
border-radius:10px;
border:solid 2px #000;
background-color: #fff;
// background-color: #223458;
// opacity: 0.6;
color:#fff;
z-index:1;
}
.stepstipstittle{

View File

@ -1,17 +1,32 @@
<template>
<div class="toolbardiv" >
<div class="toolbarbutton" @click="openGuide"></div>
<div class="toolbarbutton" @click="openBag"></div>
<div class="toolbarbutton" ></div>
<div class="toolbardiv" :style="{'background-image': 'url('+lessonbg+')'}">
<div class="toolbarguides" v-show="showGuide">
<div class="toolbarbutton"
:style="{'background-image': 'url('+localstatic+'/lesson3d/guide.png)'}"
@click="openGuide">
</div>
<div class="toolbarbutton"
:style="{'background-image': 'url('+localstatic+'/lesson3d/bag.png)'}"
@click="openBag">
</div>
<div class="toolbarbutton"
:style="{'background-image': 'url('+localstatic+'/lesson3d/back.png)'}">
</div>
<div class="toolbarguides"
:style="{'background-image': 'url('+lessonbg+')'}"
v-show="showGuide">
<div class="toolbarguide" v-for="(guide,index) in guideList">
{{guide.name}}
</div>
</div>
<div class="toolbarbag" v-show="showBag">
<div class="toolbarbag"
:style="{'background-image': 'url('+lessonbg+')'}"
v-show="showBag">
<div class="toolbarplaid" v-for="(tool,index) in toolsList"></div>
</div>
</div>
@ -28,6 +43,8 @@
},
data() {
return {
localstatic:JL3D_LOCAL_STATIC,
lessonbg:JL3D_LOCAL_STATIC+"/lesson3d/lessonbg.png",
tipsTittle:"步骤一",
tipsText:"步骤一",
guideList:[],
@ -135,7 +152,6 @@
bottom:0;
border-radius:10px;
border:solid 2px #000;
background-color: #fff;
z-index:1;
}
@ -146,6 +162,7 @@
border-radius:10px;
border:solid 2px #000;
margin: 2px;
background-repeat: no-repeat;
}
.toolbarguides{
@ -157,14 +174,18 @@
overflow-y: auto;
overflow-x: hidden;
border-radius:10px;
color: #fff;
border:solid 2px #000;
text-align: center;
}
.toolbarguide{
margin-top: 5px;
width: 90px;
height: 30px;
border-radius:10px;
border:solid 2px #000;
font-size: 20px;
margin: 5px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
static/lesson3d/back.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
static/lesson3d/bag.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
static/lesson3d/guide.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

BIN
static/lesson3d/jobpic.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
static/lesson3d/lkgw.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

BIN
static/lesson3d/选项.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB