three.js报错集锦

1、KeyframeTrack 帧动画

报错:
THREE.Matrix3: .getInverse() can’t invert matrix, determinant is 0
代码:

// 此处是一个缩放动画
let times = [0, 1]
let scales = [0, 0, 0, 1, 1, 1]
let scaleKeyframeTrack = new THREE.KeyframeTrack('circle.scale', times, scales)

由上可知,缩放从x,y,z坐标的0倍到1倍变化,导致0倍时报错,没有逆矩阵。
改为如下即可:

let times = [0, 1]
let scales = [1, 1, 1, 2, 2, 2]
let scaleKeyframeTrack = new THREE.KeyframeTrack('circle.scale', times, scales)

将缩放变化改为,从x,y,z坐标的1倍到2倍变化即可。

2、EffectComposer 效果组合器

报错:
THREE.EffectComposer is not a constructor
‘THREE.EffectComposer不是构造函数’
因为:EffectComposer不包含在three.js的包中,需要单独导入,并且配置webpack导入导出变量。
和其他非官方的three.js模块,如OrbitControls引入的方法一致。
正确配置引用代码如下:

// webpack.base.conf.js中配置
module.exports = {
	……
	module: {
		rules: [
			……
			{
				test: require.resolve("three/examples/js/postprocessing/EffectComposer"),
				use: "imports-loader?THREE=three"
			},
			{
				test: require.resolve("three/examples/js/postprocessing/EffectComposer"),
				use: "exports-loader?THREE.EffectComposer"
			}
		]
	}
}
// 引入和使用
import EffectComposer from 'three/examples/js/postprocessing/EffectComposer'
composer = new EffectComposer(renderer)

3、EffectComposer 毁坏原始透明背景

代码:

// 原始WebGLRenderer渲染器
renderer = new THREE.WebGLRenderer({alpha: true, antialias: true})
// 设置宽和高
renderer.setSize(div3D.clientWidth, div3D.clientHeight)
// 设置背景 0x0E3866表示16进制 若不设置则背景透明 特效渲染时产生的背景会显示出来
// renderer.setClearColor(0x102440)

// 效果组合器包裹原始渲染器
composer = new EffectComposer(renderer)
// 添加特效渲染通道
let renderPass = new RenderPass(scene, camera)
composer.addPass(renderPass)
outlinePass = new OutlinePass(new THREE.Vector2(div3D.clientWidth, div3D.clientHeight), scene, camera)
composer.addPass(outlinePass)
// 将结果输出到屏幕上的通道
let effectFXAA = new ShaderPass(THREE.FXAAShader)
effectFXAA.renderToScreen = true
effectFXAA.clear = true
composer.addPass(effectFXAA)

问题:
加上特效之后,因为原始背景设置为透明,而OutlinePass里面强制设置了背景颜色,此时强制设置的黑色背景被显示了出来。
three.js报错集锦_第1张图片
结果:
不使用透明背景,放开注释,设置renderer.setClearColor(0x102440)。
其实问题并没有解决,求解!!!

4、CSS2DRenderer 渲染DIV后鼠标移动场景失效

代码:

// 获取详情模板DIV 设置为显示
let detailDiv = document.getElementById('detailInfo')
detailDiv.style.display = 'block'
// 使用CSS2DObject创建DIV对象 并设置位置 加入场景
let detailCSS2D = new THREE.CSS2DObject(detailDiv)
detailCSS2D.position.set(buildLoc.x, 6, buildLoc.z)
scene.add(detailCSS2D)
// 使用CSS2DRenderer 渲染DIV对象 并挂到页面中去
labelRenderer = new THREE.CSS2DRenderer()
labelRenderer.setSize(div3D.clientWidth, div3D.clientHeight)
labelRenderer.domElement.style.position = 'absolute'
labelRenderer.domElement.style.top = 0
labelRenderer.domElement.id = 'renderFrame'
div3D.appendChild(labelRenderer.domElement)
// 控制屏幕缩放、旋转 但是无法整体拖动
/* eslint-disable */
let labelControls = new OrbitControls(camera, labelRenderer.domElement)
/* eslint-enable */

问题:
1、若注释 // let labelControls = new OrbitControls(camera, labelRenderer.domElement)
整个鼠标控制失效。
2、即便使用 let labelControls = new OrbitControls(camera, labelRenderer.domElement)
也会导致在div渲染后,shift+鼠标移动就失效了。
所以:
适时展示完详情DIV后,将其清除还原或者隐藏。
比如:

// 获取原来的详情renderFrame 删除或者隐藏 看具体业务场景决定
let renderFrame = document.getElementById('renderFrame')
if (renderFrame !== null) {
	// 直接移除
	div3D.removeChild(renderFrame)
	// 或者隐藏
	// renderFrame.style.display = 'none'
}

5、TextureLoader 贴图加载PNG背景不透明 充填了白色

代码:

// 管道路径
let pipeline = new THREE.CatmullRomCurve3([
	new THREE.Vector3(36, -6, -13),
	new THREE.Vector3(-30, 16, -13)
], false)
// 创建管道,沿路径方向分段数默认64越长越大,管道半径默认1,圆周方向的分段数默认8,首尾是否连接默认否
let tubeGeometry = new THREE.TubeGeometry(pipeline, 100, 0.3, 2, false)
// 纹理加载器
let textureLoader = new THREE.TextureLoader()
texture = textureLoader.load('/static/3d/textures/test.png')
// 设置阵列模式为 RepeatWrapping
texture.wrapS = THREE.RepeatWrapping
texture.wrapT = THREE.RepeatWrapping
// 设置x方向的偏移(沿着管道路径方向),y方向默认1
texture.repeat.x = 5
texture.repeat.y = 2
// texture.premultiplyAlpha = true // 不设置的话背景透明会变白
let tubeMaterial = new THREE.MeshPhongMaterial({
	map: texture,
	side: THREE.FrontSide
})
let tube = new THREE.Mesh(tubeGeometry, tubeMaterial)
scene.add(tube)

有代码如上,创建管道贴上纹理图。
问题:
若图片大小为4040,和任意边长非2的次方数的正方形,会有如下警告,但是纹理贴图正常,是png图形背景透明。
THREE.WebGLRenderer: image is not power of two (40x40). Resized to 32x32
若图片大小裁剪为32
32,再使用上述代码贴上纹理图,png图片的背景明显被充填了白色,不再透明。
最后发现Texture里有个属性premultiplyAlpha,默认为false,不设置为true的话透明背景会变白。
即放开注释 // texture.premultiplyAlpha = true 即可。
官方文档说明:
https://www.techbrood.com/threejs/docs/#参考手册/纹理(Textures)/纹理(Texture)

你可能感兴趣的:(threejs)