知识点:1.VUE 的 three.js 安装 直接cnpm install three 就好
至于FBX导入 相机控制 就单独引入就好比如:
import {FBXLoader} from 'three/examples/jsm/loaders/FBXLoader'
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls'
2.FBX模型加载
var loader = new FBXLoader();
// modelsrc为模型路径
loader.load(this.modelsrc,geometry =>{
this.scene.add (geometry) }
3.根据模型大小定位摄像机初始位置
var boxHelper = new THREE.BoxHelper();
var camera = new THREE.PerspectiveCamera( 50, 1, 1, 100000 );
boxHelper.setFromObject(mod);
var center = boxHelper.geometry.boundingSphere.center;
var radius = boxHelper.geometry.boundingSphere.radius;
var cameraPos = new THREE.Vector3(center.x+mod.position.x,center.y+mod.position.y,radius * 2.2 + center.z + mod.position.z);
var lookPos = new THREE.Vector3(center.x+mod.position.x,center.y+mod.position.y,center.z+mod.position.z);
camera.position.copy(cameraPos);
//这里有个需要注意的地方:如果使用了THREE.OrbitControls进行鼠标控制,那么一定要加上controls.target = lookPos;并在OrbitControls创建了之后加上camera.lookAt(lookPos);
var controls = new THREE.OrbitControls( camera, domElement );
controls.target = lookPos;
camera.lookAt(lookPos);
4 .raycaster 的偏移问题
raycaster就是鼠标的点击事件可以获得位置 两点确定一条线 再求长度就是测距离了 但有时会偏移 所以用这个方法最好能规避
let container = document.getElementById('container3d');
var mouse = new Three.Vector2();
var raycaster = new Three.Raycaster();
let getBoundingClientRect = container.getBoundingClientRect()
let x = ((event.clientX - getBoundingClientRect .left) / container.offsetWidth) * 2 - 1;// 标准设备横坐标
let y = -((event.clientY - getBoundingClientRect .top) / container.offsetHeight) * 2 + 1;// 标准设备纵坐标
let standardVector = new Three.Vector3(x, y, 1);// 标准设备坐标
// 标准设备坐标转世界坐标
let worldVector = standardVector.unproject(this.camera);
// 射线投射方向单位向量(worldVector坐标减相机位置坐标)
let ray = worldVector.sub(this.camera.position).normalize();
// 创建射线投射器对象
let rayCaster = new Three.Raycaster(this.camera.position, ray);
// 返回射线选中的对象 第二个参数如果不填 默认是false
let intersects = rayCaster.intersectObjects(this.modelmesh.children, true);
5.全屏事件 但要注意要再加个检测事件 可以初始化所做的操作 (因为我是封装成组件 弹窗是个小窗口)
fillwindow(){
let element = document.getElementById('fullcontent')
let content = document.getElementById('container3d')
// document.getElementById('container3d').innerHTML = "";
if (this.fullscreen) {
// content.style.height = "500px"
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
} else {
// content.style.height = "94vh"
console.log(element.style.width)
if (element.requestFullscreen) {
element.requestFullscreen();
} else if (element.webkitRequestFullScreen) {
element.webkitRequestFullScreen();
} else if (element.mozRequestFullScreen) {
element.mozRequestFullScreen();
} else if (element.msRequestFullscreen) {
// IE11
element.msRequestFullscreen();
}
}
},
mounted() {
var that = this
window.onresize = function(){
if(that.modelopen==true){
console.log('eeeeessssccc')
document.getElementById('container3d').innerHTML = "";
setTimeout(function() {
that.init3d()
}, 1000);
setTimeout(function() {
that.animate3d()
}, 1000);
that.fullscreen = !that.fullscreen;
if (that.fullscreen==true) {
document.getElementById('container3d').style.height = "94vh";
}else{
document.getElementById('container3d').style.height = "500px";
}
}
};
},
6.画线 两点确认一条线 就可以画线了 并获得两点距离换算成毫米
drawLine( p1, p2) {
var directionVector = new Three.Vector3();
var p3 = new Three.Vector3();
directionVector.x = p2.x - p1.x;
directionVector.y = p2.y - p1.y;
directionVector.z = p2.z - p1.z;
//两点距离换算成毫米
var length = Math.sqrt( directionVector.x * directionVector.x
+ directionVector.y * directionVector.y
+ directionVector.z * directionVector.z);
var text = Math.round( length*10 ) + "";
var geometry = new Three.Geometry();
var material = new Three.LineBasicMaterial( { opacity:1,color:0x00ff00 } );
geometry.vertices.push(p1);
geometry.vertices.push(p1);
geometry.vertices.push(p2);
var geo = new Three.Line(geometry, material)
this.alllinearr.push(geo)
this.scene.add(geo)
p3.x = (p1.x+p2.x)/2
p3.y = (p1.y+p2.y)/2
p3.z = (p1.z+p2.z)/2
console.log(p3)
this.initText( text, p3 );
},
7.根据 线条长度加上文字标注 要引用import { CSS2DRenderer, CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer.js'
然后再定义个渲染器再init 初始化的时候
// 标签render
this.labelRenderer = new CSS2DRenderer();
this.labelRenderer.setSize( container.clientWidth,container.clientHeight );
this.labelRenderer.domElement.style.position = 'absolute';
this.labelRenderer.domElement.style.top = '0px';
container.appendChild( this.labelRenderer.domElement );
animate上也要加上this.labelRenderer.render(this.scene,this.camera)
initText( wordFont, p1){
var font = this.makeTextSprite(wordFont,{
fontsize: 30,
borderColor: {r:255, g:0, b:0, a:0.4},/* 边框黑色 */
backgroundColor: {r:255, g:255, b:255, a:0.9}/* 背景颜色 */
});
font.center = new Three.Vector2(0,0)
// console.log(font)
font.position.copy( p1 );
this.scene.add(font)
this.alltextarr.push(font)
},
makeTextSprite(message, parameters) {
if ( parameters === undefined ) parameters = {};
var fontface = parameters.hasOwnProperty("fontface") ?
parameters["fontface"] : "Arial";
/* 字体大小 */
var fontsize = parameters.hasOwnProperty("fontsize") ?
parameters["fontsize"] : 16;
/* 边框厚度 */
var borderThickness = parameters.hasOwnProperty("borderThickness") ?
parameters["borderThickness"] : 3;
/* 边框颜色 */
var borderColor = parameters.hasOwnProperty("borderColor") ?
parameters["borderColor"] : { r:0, g:0, b:0, a:1.0 };
/* 背景颜色 */
var backgroundColor = parameters.hasOwnProperty("backgroundColor") ?
parameters["backgroundColor"] : { r:255, g:255, b:255, a:1.0 };
/* 创建画布 */
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
/* 字体加粗 */
context.font = "Bold " + fontsize + "px " + fontface;
/* 获取文字的大小数据,高度取决于文字的大小 */
var metrics = context.measureText( message );
var textWidth = metrics.width;
/* 背景颜色 */
context.fillStyle = "rgba(" + backgroundColor.r + "," + backgroundColor.g + ","
+ backgroundColor.b + "," + backgroundColor.a + ")";
/* 边框的颜色 */
context.strokeStyle = "rgba(" + borderColor.r + "," + borderColor.g + ","
+ borderColor.b + "," + borderColor.a + ")";
context.lineWidth = borderThickness;
/* 绘制圆角矩形 */
this.roundRect(context, 150/2, 125/2, textWidth + 50, 50,1);
// this.roundRect(context, borderThickness/2, borderThickness/2, textWidth + borderThickness, fontsize * 1.4 + borderThickness,1);
/* 字体颜色 */
context.fillStyle = "rgba(0, 0, 0, 1.0)";
console.log(borderThickness)
console.log(fontsize + borderThickness)
context.fillText( message, 100, 100);
// console.log(context)
// 创建标签
var moonLabel = new CSS2DObject( canvas );
return moonLabel
},
roundRect(ctx, x, y, w, h, r) {
ctx.beginPath();
ctx.moveTo(x+r, y);
ctx.lineTo(x+w-r, y);
ctx.quadraticCurveTo(x+w, y, x+w, y+r);
ctx.lineTo(x+w, y+h-r);
ctx.quadraticCurveTo(x+w, y+h, x+w-r, y+h);
ctx.lineTo(x+r, y+h);
ctx.quadraticCurveTo(x, y+h, x, y+h-r);
ctx.lineTo(x, y+r);
ctx.quadraticCurveTo(x, y, x+r, y);
ctx.closePath();
ctx.fill();
ctx.stroke();
},
8.画线区分直线模式和非直线 直线第第二个三维向量点与第一个三维向量点相减就正 哪个最大就是朝哪个位置
var xx = Math.abs(this.points[0].x - intersects[ 0 ].point.x)
var yy = Math.abs(this.points[0].y - intersects[ 0 ].point.y)
var zz = Math.abs(this.points[0].z - intersects[ 0 ].point.z)
if (xx>yy&&xx>zz) {
var location = new Three.Vector3(intersects[ 0 ].point.x, this.points[0].y,this.points[0].z)
}else if (yy>xx&&yy>zz) {
var location = new Three.Vector3(this.points[0].x,intersects[ 0 ].point.y, this.points[0].z)
}
else if (zz>xx&&zz>yy) {
var location = new Three.Vector3(this.points[0].x,this.points[0].y,intersects[ 0 ].point.z)
}
9.组件化 父子组件调用 不BB了
全部代码 懵B的话 就问我吧