小程序展示3D模型-使用three.js 进行渲染
在开发的期间查阅了大量的资料、案例,大多都是无稽之谈…经过摸索…终于开发出来了适合本项目的3D模型案例
为了帮助有需要的同学 少走弯路 特地记录了一下哦
在开发期间 也找到了 较好的微信端3d模型渲染 有需要的可以留言文章来源:https://www.toymoban.com/news/detail-504676.html
效果如图所示:(进行了配置,这里也加了手势滑动,自动旋转 3d的类型是obj格式)
文章来源地址https://www.toymoban.com/news/detail-504676.html
配置项目需要的依赖
安装依赖
npm i
npm i dhtml-weixin
npm i three-weixin
小程序开发工具顶部菜单->工具->构建npm (如果有效果也可以不构建)
html
<template>
<view class="three_3d">
<canvas disable-scroll="true" @touchcancel="webgl_touch" @touchend="webgl_touch" @touchmove="webgl_touch"
@touchstart="webgl_touch" id="canvas_webgl" canvas-id="canvas_webgl" type="webgl"
style="width:750rpx;height:800rpx;"></canvas>
</view>
</template>
项目依赖
import {
document,
window,
requestAnimationFrame,
cancelAnimationFrame,
Event
} from 'dhtml-weixin';
import * as THREE from 'three-weixin';
// import Stats from '../../jsm/libs/stats.module.js';
// import {
// GUI
// } from '../../jsm/libs/lil-gui.module.min.js';
import {
OrbitControls
} from '../../jsm/controls/OrbitControls.js';
import {
OBJLoader
} from '../../jsm/loaders/OBJLoader.js';
var renderer;
js
<script>
export default {
name: "threeA",
data() {
return {
// renderer: null
};
},
methods: {
beforeDestroy() {
getApp().worker && getApp().worker.terminate()
cancelAnimationFrame()
if (this.renderer) {
this.renderer.dispose()
this.renderer.forceContextLoss()
this.renderer.context = null
this.renderer.domElement = null
this.renderer = null
}
},
webgl_touch(e) {
const web_e = Event.fix(e)
document.dispatchEvent(web_e)
window.dispatchEvent(web_e)
this.renderer && this.renderer.dispatchEvent(web_e)
},
},
async onLoad() {
getApp().canvas = await document.createElementAsync("canvas", "webgl");
renderer = new THREE.WebGLRenderer({
antialias: true
});
},
async mounted() {
// 模型加载需要时间 添加提示 3秒钟后关闭提示正好数据加载出来
uni.showLoading({
title: '加载中',
duration: 3000
});
var that = this;
getApp().canvas = await document.createElementAsync("canvas", "webgl", this);
let container;
let camera, scene, renderer, stats;
let mouseX = 0,
mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let object;
init();
animate();
function init() {
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 2000);
camera.position.z = 250;
// scene
scene = new THREE.Scene();
const ambientLight = new THREE.AmbientLight(0xcccccc, 0.4);
scene.add(ambientLight);
const pointLight = new THREE.PointLight(0xffffff, 0.8);
camera.add(pointLight);
scene.add(camera);
// manager
function loadModel() {
object.traverse(function(child) {
// if ( child.isMesh ) child.material.map = texture;
});
object.position.y = -50;
scene.add(object);
}
const manager = new THREE.LoadingManager(loadModel);
// texture
const textureLoader = new THREE.TextureLoader(manager);
// const texture = textureLoader.load( 'http://localhost:8080/examples/textures/uv_grid_opengl.jpg' );
// model
function onProgress(xhr) {
if (xhr.lengthComputable) {
const percentComplete = xhr.loaded / xhr.total * 100;
console.log('model ' + Math.round(percentComplete, 2) + '% downloaded');
}
}
function onError() {}
const loader = new OBJLoader(manager);
loader.load('http://youkejingpin.oss-cn-beijing.aliyuncs.com/Digital/static/pic/product/toukui.obj',
function(obj) {
object = obj;
}, onProgress, onError);
//原始事件
// renderer = that.renderer = new THREE.WebGLRenderer();
// renderer.setPixelRatio(window.devicePixelRatio);
// renderer.setSize(window.innerWidth, window.innerHeight);
// container.appendChild(renderer.domElement);
// document.addEventListener('mousemove', onDocumentMouseMove);
// window.addEventListener('resize', onWindowResize);
// 鼠标点击事件
renderer = that.renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.outputEncoding = THREE.sRGBEncoding;
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
//控制模型触动事件
camera = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight, 1, 2000);
camera.position.set(160, 40, 160);
const controls = new OrbitControls(camera, renderer.domElement);
controls.enablePan = false;
controls.enableZoom = true;
controls.target.set(0, 1, 0);
controls.update();
// stats = new Stats();
// container.appendChild(stats.dom);
window.addEventListener('resize', onWindowResize);
}
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 2;
mouseY = (event.clientY - windowHalfY) / 2;
}
//
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
//camera.position.x += ( mouseX - camera.position.x ) * .05;
// mera.position.y += ( - mouseY - camera.position.y ) * .05;
// mera.lookAt( scene.position );
renderer.render(scene, camera);
// console.error(new Date().getTime())
if (object) {
object.rotation.set(0, object.rotation.y + 0.007, 0)
}
}
}
}
</script>
整体代码可直接使用(js+html)
<!-- 模型地址线上地址
http://youkejingpin.oss-cn-beijing.aliyuncs.com/Digital/static/pic/product/toukui.obj
-->
<template>
<view class="three_3d">
<canvas disable-scroll="true" @touchcancel="webgl_touch" @touchend="webgl_touch" @touchmove="webgl_touch"
@touchstart="webgl_touch" id="canvas_webgl" canvas-id="canvas_webgl" type="webgl"
style="width:750rpx;height:800rpx;"></canvas>
</view>
</template>
<script>
import {
document,
window,
requestAnimationFrame,
cancelAnimationFrame,
Event
} from 'dhtml-weixin';
import * as THREE from 'three-weixin';
import {
OrbitControls
} from '../../jsm/controls/OrbitControls.js';
import {
OBJLoader
} from '../../jsm/loaders/OBJLoader.js';
var renderer;
export default {
name: "threeA",
data() {
return {
// renderer: null
};
},
methods: {
beforeDestroy() {
getApp().worker && getApp().worker.terminate()
cancelAnimationFrame()
if (this.renderer) {
this.renderer.dispose()
this.renderer.forceContextLoss()
this.renderer.context = null
this.renderer.domElement = null
this.renderer = null
}
},
webgl_touch(e) {
const web_e = Event.fix(e)
document.dispatchEvent(web_e)
window.dispatchEvent(web_e)
this.renderer && this.renderer.dispatchEvent(web_e)
},
},
async onLoad() {
getApp().canvas = await document.createElementAsync("canvas", "webgl");
renderer = new THREE.WebGLRenderer({
antialias: true
});
},
async mounted() {
// 模型加载需要时间 添加提示 3秒钟后关闭提示正好数据加载出来
uni.showLoading({
title: '加载中',
duration: 3000
});
var that = this;
getApp().canvas = await document.createElementAsync("canvas", "webgl", this);
let container;
let camera, scene, renderer, stats;
let mouseX = 0,
mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let object;
init();
animate();
function init() {
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 2000);
camera.position.z = 250;
// scene
scene = new THREE.Scene();
const ambientLight = new THREE.AmbientLight(0xcccccc, 0.4);
scene.add(ambientLight);
const pointLight = new THREE.PointLight(0xffffff, 0.8);
camera.add(pointLight);
scene.add(camera);
// manager
function loadModel() {
object.traverse(function(child) {
// if ( child.isMesh ) child.material.map = texture;
});
object.position.y = -50;
scene.add(object);
}
const manager = new THREE.LoadingManager(loadModel);
// texture
const textureLoader = new THREE.TextureLoader(manager);
// const texture = textureLoader.load( 'http://localhost:8080/examples/textures/uv_grid_opengl.jpg' );
// model
function onProgress(xhr) {
if (xhr.lengthComputable) {
const percentComplete = xhr.loaded / xhr.total * 100;
console.log('model ' + Math.round(percentComplete, 2) + '% downloaded');
}
}
function onError() {}
const loader = new OBJLoader(manager);
loader.load('http://youkejingpin.oss-cn-beijing.aliyuncs.com/Digital/static/pic/product/toukui.obj',
function(obj) {
object = obj;
}, onProgress, onError);
//原始事件
// renderer = that.renderer = new THREE.WebGLRenderer();
// renderer.setPixelRatio(window.devicePixelRatio);
// renderer.setSize(window.innerWidth, window.innerHeight);
// container.appendChild(renderer.domElement);
// document.addEventListener('mousemove', onDocumentMouseMove);
// window.addEventListener('resize', onWindowResize);
// 鼠标点击事件
renderer = that.renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.outputEncoding = THREE.sRGBEncoding;
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
//控制模型触动事件
camera = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight, 1, 2000);
camera.position.set(160, 40, 160);
const controls = new OrbitControls(camera, renderer.domElement);
controls.enablePan = false;
controls.enableZoom = true;
controls.target.set(0, 1, 0);
controls.update();
// stats = new Stats();
// container.appendChild(stats.dom);
window.addEventListener('resize', onWindowResize);
}
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 2;
mouseY = (event.clientY - windowHalfY) / 2;
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
//camera.position.x += ( mouseX - camera.position.x ) * .05;
// mera.position.y += ( - mouseY - camera.position.y ) * .05;
// mera.lookAt( scene.position );
renderer.render(scene, camera);
// console.error(new Date().getTime())
if (object) {
object.rotation.set(0, object.rotation.y + 0.007, 0)
}
}
}
}
</script>
<style lang="scss">
.three_3d {
width: 750rpx;
height: 800rpx;
}
</style>
完整项目地址gitee:https://gitee.com/sun-icon/uniapp3D
到了这里,关于uniapp小程序展示3D模型的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!