THREEJS 使用入门

THREEJS 使用入门

首页休闲益智push cube更新时间:2024-05-07

1、THREEJS 官方网址: <u>https://threejs.org/。</u> threejs 通过封装WEBGL API 实现了在网页端直接进行三维3d模型渲染。应用场景包括:小游戏,在线展厅,DIY 互动等现代互联网应用,极具发展前景。

2、官方使用案例https://threejs.org/examples/,可以直接套用。

webglmaterial.png

以 <u>https://github.com/mrdoob/three.js/blob/master/examples/webgl_materials.html</u> 为例,讲解如何使用Threejs构建自己的应用:
步骤一、新建html页面。

<!DOCTYPE html> <html lang="en"> <head> <title>three.js webgl - materials</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> <link type="text/css" rel="stylesheet" href="main.css"> </head> <body> <div id="info"> <a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - webgl materials </div> <script type="module"> import * as THREE from '../build/three.module.js'; //引入threejs 主框架 import Stats from './jsm/libs/stats.module.js'; //引入状态帧计数状态显示 let stats; let camera, scene, renderer; let pointLight; const objects = [], materials = []; init(); animate(); function init() { const container = document.createElement( 'div' );//创建3d 场景所在的区域 document.body.appendChild( container ); camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );//设置3d场景的镜头参数,45度代表镜头的视角。 camera.position.set( 0, 200, 800 ); scene = new THREE.Scene();//创建场景对象,所有渲染都是根据该对象进行渲染。 // Grid const helper = new THREE.GridHelper( 1000, 40, 0x303030, 0x303030 );//场景中的方格线,辅助视角 helper.position.y = - 75; scene.add( helper ); // Materials const texture = new THREE.Texture( generateTexture() );//创建纹理 texture.needsUpdate = true; materials.push( new THREE.MeshLambertMaterial( { map: texture, transparent: true } ) ); materials.push( new THREE.MeshLambertMaterial( { color: 0xdddddd } ) ); materials.push( new THREE.MeshPhongMaterial( { color: 0xdddddd, specular: 0x009900, shininess: 30, flatShading: true } ) ); materials.push( new THREE.MeshNormalMaterial() ); materials.push( new THREE.MeshBasicMaterial( { color: 0xffaa00, transparent: true, blending: THREE.AdditiveBlending } ) );//设置材质参数,包括混合参数,直接影响颜色混合后的效果 materials.push( new THREE.MeshLambertMaterial( { color: 0xdddddd } ) ); materials.push( new THREE.MeshPhongMaterial( { color: 0xdddddd, specular: 0x009900, shininess: 30, map: texture, transparent: true } ) );//设置材质的反射、透明、高光参数,如金属材质,玻璃材质,木头材质,反射系数,高光系数,粗糙程度都是不一样的。 materials.push( new THREE.MeshNormalMaterial( { flatShading: true } ) ); materials.push( new THREE.MeshBasicMaterial( { color: 0xffaa00, wireframe: true } ) ); materials.push( new THREE.MeshDepthMaterial() ); materials.push( new THREE.MeshLambertMaterial( { color: 0x666666, emissive: 0xff0000 } ) ); materials.push( new THREE.MeshPhongMaterial( { color: 0x000000, specular: 0x666666, emissive: 0xff0000, shininess: 10, opacity: 0.9, transparent: true } ) ); materials.push( new THREE.MeshBasicMaterial( { map: texture, transparent: true } ) ); // Spheres geometry const geometry = new THREE.SphereGeometry( 70, 32, 16 ); for ( let i = 0, l = materials.length; i < l; i ) { addMesh( geometry, materials[ i ] ); } // Lights scene.add( new THREE.AmbientLight( 0x111111 ) );//设置漫反射光源,类似白天没有太阳直晒的房间,有暗光。产生的原有主要是环境物体多次发射后的光线。 const directionalLight = new THREE.DirectionalLight( 0xffffff, 0.125 );//方向光源,仿真太阳光,从很远的距离照射。 directionalLight.position.x = Math.random() - 0.5; directionalLight.position.y = Math.random() - 0.5; directionalLight.position.z = Math.random() - 0.5; directionalLight.position.normalize();//位置参数,主要是控制光从哪个方向照射,类似太阳在东面,还是西面。 scene.add( directionalLight ); pointLight = new THREE.PointLight( 0xffffff, 1 );//点光影,仿真单个灯泡 scene.add( pointLight ); pointLight.add( new THREE.Mesh( new THREE.SphereGeometry( 4, 8, 8 ), new THREE.MeshBasicMaterial( { color: 0xffffff } ) ) ); // renderer = new THREE.WebGLRenderer( { antialias: true } );//webgl的渲染引擎 renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); container.appendChild( renderer.domElement );//将3d渲染引擎绑定到html页面的div // stats = new Stats(); container.appendChild( stats.dom );//状态显示,二维组件,与3d没有直接关系 // window.addEventListener( 'resize', onWindowResize ); } function addMesh( geometry, material ) { const mesh = new THREE.Mesh( geometry, material ); mesh.position.x = ( objects.length % 4 ) * 200 - 400; mesh.position.z = Math.floor( objects.length / 4 ) * 200 - 200; mesh.rotation.x = Math.random() * 200 - 100; mesh.rotation.y = Math.random() * 200 - 100; mesh.rotation.z = Math.random() * 200 - 100; objects.push( mesh ); scene.add( mesh );//所有渲染的模型,均需加入值场景对象scene内。3d引擎是通过遍历scene下的子对象,进行渲染的。 } function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize( window.innerWidth, window.innerHeight ); } function generateTexture() {//通过canvas 方式画出纹理,也可以直接从图像文件png加载纹理。 const canvas = document.createElement( 'canvas' ); canvas.width = 256; canvas.height = 256; const context = canvas.getContext( '2d' ); const image = context.getImageData( 0, 0, 256, 256 ); let x = 0, y = 0; for ( let i = 0, j = 0, l = image.data.length; i < l; i = 4, j ) { x = j % 256; y = ( x === 0 ) ? y 1 : y; image.data[ i ] = 255; image.data[ i 1 ] = 255; image.data[ i 2 ] = 255; image.data[ i 3 ] = Math.floor( x ^ y ); } context.putImageData( image, 0, 0 ); return canvas; } // function animate() { requestAnimationFrame( animate );//这部分是关键,通过设置浏览器的动画循环调用animate函数。保障画面循环渲染。好比cpu的时钟,一直在运转。 render();//场景渲染,webgl 渲染实际工作内容。 stats.update(); } function render() { const timer = 0.0001 * Date.now(); camera.position.x = Math.cos( timer ) * 1000; camera.position.z = Math.sin( timer ) * 1000; camera.lookAt( scene.position ); for ( let i = 0, l = objects.length; i < l; i ) { const object = objects[ i ]; object.rotation.x = 0.01; object.rotation.y = 0.005; } materials[ materials.length - 2 ].emissive.setHSL( 0.54, 1, 0.35 * ( 0.5 0.5 * Math.sin( 35 * timer ) ) ); materials[ materials.length - 3 ].emissive.setHSL( 0.04, 1, 0.35 * ( 0.5 0.5 * Math.cos( 35 * timer ) ) ); pointLight.position.x = Math.sin( timer * 7 ) * 300; pointLight.position.y = Math.cos( timer * 5 ) * 400; pointLight.position.z = Math.cos( timer * 3 ) * 300; renderer.render( scene, camera );//调用renderer引擎实际渲染场景scene,camera,后续另外再讲场景渲染的数学模型。 } </script> </body> </html>

3、如何在vue中引入THREEJS
步骤一、新建threejs 组件,ZeusStage.vue

大画家效果图.jpg

<template> <div ref="container" > </div> </template> <script> import * as THREE from 'three' export default { name: 'ZeusStage', provide () { return { parentObj: null, // avoid "injection not found" warning _baseUrl: null, global: this.global } }, props: { size: { type: Object, // { w, h } required: false, default: function(){ return { w:100, h:100 } } }, scenejson:{ type: Object }, scene_url:{ type:String } }, data () { return { g_material_selected:'黄金', img_blend:'', popover_active: false, }; }, watch: { size(newval, oldval) { if (newval != oldval) { this.$refs.container.style.width = this.size.w 'px'; this.$refs.container.style.height = this.size.h 'px'; this.$refs.container.width = this.size.w; this.$refs.container.height = this.size.h; this.$emit("resize"); } } }, mounted () { this.extent(); this.container = this.$refs.container; this.init(); this.parseScene(); }, methods: { init() { var _this = this; var container = this.container; var dom = container; this.dom = dom; this.DrawMode = false; //画布模式 this.initScene(); this.initControl(); this.initRenderer(); // POSTPROCESSING var clock = new THREE.Clock(); var controls = this.controls; var scene = this.scene; var camera = this.camera; var renderer = this.renderer; setupEventHandlers(); controls.addEventListener('change', render); animate(); function setupEventHandlers() { var onResize = function() { if (camera instanceof THREE.OrthographicCamera) { camera.left = dom.offsetWidth / -2; camera.right = dom.offsetWidth / 2; camera.top = dom.offsetHeight / 2; camera.bottom = dom.offsetHeight / -2; } if (camera instanceof THREE.PerspectiveCamera) { camera.aspect = dom.offsetWidth / dom.offsetHeight; } camera.updateProjectionMatrix(); renderer.setSize(dom.offsetWidth, dom.offsetHeight); render(); }; //window.addEventListener('resize', onResize, false); _this.$on("resize", onResize ); onResize(); } // function animate() { requestAnimationFrame(animate); controls.update(); render(); } function render() { if (renderer) { renderer.clear(); _this.setLightPosition(); var delta = clock.getDelta(); updateDelta(delta, camera); renderer.render(scene, camera); } } function updateDelta(delta,camera) { if (scene) { scene.traverse(function(_obj) { if (_obj.updateDelta) { _obj.updateDelta(delta,camera); } }); } } }, initControl() { var camera = this.camera; var dom = this.dom; var controls = new ZEUS.THREE_EXT.OrbitControls(camera, dom); this.controls = controls; controls.enabled = true; controls.rotateSpeed = 1.0; controls.zoomSpeed = 2.0; controls.panSpeed = 0.0003; controls.minDistance = 15; controls.maxDistance = 100; controls.noZoom = false; controls.noPan = false; controls.maxPan = 10; controls.autoRotate = true; controls.autoRotateSpeed = -2.5; //TODO controls.enableDamping = true; controls.dampingFactor = 0.1; controls.keys = [65, 83, 68]; hoverDelay({ el:dom, hoverDuring: 200, outDuring: 500, hoverEvent: function() { controls.autoRotate = false; //_this.setAutoRotate(false); }, outEvent: function() { //controls.autoRotate = true; //_this.setAutoRotate(true); } }) function hoverDelay(option){ var el = option.el; var timer = null; var onMouseOver = function(){ if(timer){ clearTimeout(timer); } timer = setTimeout(() => { if(option.hoverEvent){ option.hoverEvent(); } },option.hoverDuring); } var onMouseOut = function (){ if(timer){ clearTimeout(timer); } timer = setTimeout(() => { if(option.outEvent){ option.outEvent(); } },option.outDuring); } el.addEventListener("mouseover",onMouseOver); el.addEventListener("mouseout",onMouseOut); el.addEventListener("touchstart",onMouseOver); el.addEventListener("touchend",onMouseOut) } }, initScene() { this.camera = new THREE.PerspectiveCamera(45, 1, 1, 100000); this.scene = new THREE.Scene(); this.scene.name = 'Scene'; this.initLight(); this.box = null; }, initLight() { // LIGHTS var key_light = new THREE.DirectionalLight(0xffffff, 1);//new THREE.SpotLight(0xffffff, 1.4); //FFFFE6 key_light.castShadow = true; key_light.position.x = 1; key_light.position.y = 1; key_light.position.z = 1; this.key_light = key_light; this.scene.add(this.key_light); }, initRenderer() { var clearColor = 0x00000000; var createRenderer = function(type, antialias) { var renderer = new THREE[type]({ antialias: antialias, alpha:true }); renderer.setClearColor(clearColor,0); renderer.setPixelRatio(window.devicePixelRatio); renderer.autoClear = false; renderer.autoUpdateScene = false; renderer.gammaInput = true; renderer.gammaOutput = true; renderer.physicallyBasedShading = true; return renderer; }; var renderer = createRenderer('WebGLRenderer', true); renderer.autoClear = false; this.renderer = renderer; this.dom.appendChild(renderer.domElement); renderer.setSize(this.size.w, this.size.h); }, initAxesHelper(){ var helper = new THREE.AxesHelper(200); this.scene.add( helper ); }, addObject(object) { this.scene.add(object); }, moveObject(object, parent, before) { if (parent === undefined) { parent = this.scene; } parent.add(object); // sort children array if (before !== undefined) { var index = parent.children.indexOf(before); parent.children.splice(index, 0, object); parent.children.pop(); } }, nameObject(object, name) { object.name = name; }, getObjectByName(name) { return this.scene.getObjectByName(name); }, removeObject(object) { if (object.parent === undefined) return; // avoid deleting the camera or scene object.parent.remove(object); }, setObjectMaterial(material, object_name) { var object = this.getObjectByName(object_name); var has_changed = false; if (object) { object.traverse(function(_obj) { if (_obj.material != material) { has_changed = true; if (_obj.material instanceof THREE.MultiMaterial) { var _material = new THREE.MultiMaterial( [material.clone(), material] ); for (var i = 0; i < _material.materials.length; i ) { _material.materials[i].shading = _obj.material.materials[i].shading; } _obj.material = _material; } else { _obj.material = material; } } }); } if (has_changed) { this.$emit('materialChanged'); } }, setObjectPosition(position, object_name) { var object = this.getObjectByName(object_name); object.position.copy(position); }, setLightPosition() { var _this = this; var camera = _this.camera; var position = new THREE.Vector3().copy(camera.position); var radius = position.length(); var camera_py = new THREE.Vector3().copy(camera.up); var camera_pz = new THREE.Vector3(0, 0, 1); var camera_px = new THREE.Vector3().crossVectors(camera_py, camera_pz); camera_py.applyQuaternion(camera.quaternion); camera_pz.applyQuaternion(camera.quaternion); camera_px.applyQuaternion(camera.quaternion); var key_light = _this.key_light; var fill_light = _this.fill_light; var back_light = _this.back_light; var bottom_light = _this.bottom_light; key_light.position.copy(camera_pz); key_light.position.applyQuaternion(new THREE.Quaternion().setFromAxisAngle(camera_py, -Math.PI / 6));//-Math.PI / 4 key_light.position.applyQuaternion(new THREE.Quaternion().setFromAxisAngle(camera_pz, -Math.PI / 6));//-Math.PI / 4 key_light.position.multiplyScalar(radius); fill_light.position.copy(camera_pz); fill_light.position.applyQuaternion(new THREE.Quaternion().setFromAxisAngle(camera_py, Math.PI / 4)); //Math.PI / 4 fill_light.position.applyQuaternion(new THREE.Quaternion().setFromAxisAngle(camera_pz, Math.PI / 4));//Math.PI / 4 fill_light.position.multiplyScalar(radius); back_light.position.copy(camera_pz); back_light.position.applyQuaternion(new THREE.Quaternion().setFromAxisAngle(camera_px, -Math.PI / 6)); back_light.position.multiplyScalar(radius); bottom_light.position.copy(camera_py).multiplyScalar(-radius); }, async initTextureCube() { var base_url = this.scene_url "textures/"; var r = base_url "cube/2021/"; await this.setTextureCube(r); }, async setTextureCube(url) { var urls = [url "px.jpg", url "nx.jpg", url "py.jpg", url "ny.jpg", url "pz.jpg", url "nz.jpg" ]; this.textureCube = await this.loadTextureCube(urls); this.textureCube.format = THREE.RGBFormat; this.textureCube.mapping = THREE.CubeTexture; }, async setTextureCube_diamond(url) { var urls = [url "ny.jpg", url "ny.jpg", url "ny.jpg", url "ny.jpg", url "ny.jpg", url "ny.jpg" ]; this.textureCube_diamond = await this.loadTextureCube(urls); this.textureCube.mapping = THREE.CubeRefractionMapping; }, getThreeMaterial(material_name) { var _this = this; if (THREE) { _this.Materials = _this.Materials || {}; var material = _this.Materials[material_name]; if (material instanceof THREE.Material) { return material; } else{ var option = getMaterialConfig(material_name); if (option) { material = new THREE.MeshPhongMaterial(option); _this.Materials[material_name] = material; } } return material; } function getMaterialConfig(_material_name) { var textureCube = _this.textureCube || null; var textureCube_diamond = _this.textureCube_diamond || null; var config = global.ConfigMaterials; var metal_materials = config.metal_materials; for (let i = 0, l = metal_materials.length; i < l; i ) { let material = metal_materials[i]; let material_name = material.name; if (_material_name == material_name) { return { color: new THREE.Color().setStyle(material.color), specular: new THREE.Color().setStyle(material.specular), shininess: parseFloat(material.shininess), envMap: textureCube, combine: THREE.MultiplyOperation, reflectivity: material.reflectivity }; } } var diamond_materials = config.diamond_materials; for (let i = 0, l = diamond_materials.length; i < l; i ) { let material = diamond_materials[i]; let material_name = material.name; if (material_name == _material_name) { var m = {}; m.envMap = textureCube_diamond; if (material.envMap == false) { m.envMap = null; } if (material.color != undefined) { m.color = new THREE.Color().setStyle(material.color); } if (material.emissive != undefined) { m.emissive = new THREE.Color().setStyle(material.emissive); } if (material.ambient != undefined) { m.ambient = new THREE.Color().setStyle(material.ambient); } if (material.specular != undefined) { m.specular = new THREE.Color().setStyle(material.specular); } if (material.shininess != undefined) { m.shininess = parseFloat(material.shininess); } if (material.reflectivity != undefined) { m.reflectivity = parseFloat(material.reflectivity); } if (material.opacity != undefined) { m.opacity = parseFloat(material.opacity); } if (material.transparent != undefined) { m.transparent = material.transparent; } if (material.refractionRatio != undefined) m.refractionRatio = parseFloat(material.refractionRatio); m.combine = THREE.MultiplyOperation; return m; } } } }, //diy parts async parseScene( ){ this.rundata = {}; this.parseCamera(); await this.initTextureCube(); await this.parseMainMaterial(); await this.parsePart(); this.$root.$emit("sceneLoaded"); }, parseCamera() { var _this = this; var camera = this.scenejson.camera; if (camera.distance != undefined) { var distance = parseFloat(camera.distance); var position0 = new THREE.Vector3(0, 0, distance); position0.applyAxisAngle(new THREE.Vector3(1, 0, 0), -15 * Math.PI / 180); this.camera.position.copy(position0); this.controls.position0 = position0.clone(); } if (camera.lookAt != undefined) { var target0 = new THREE.Vector3().fromArray(camera.lookAt); this.camera.lookAt(target0); this.controls.target0.copy(target0); this.controls.target.copy(target0); } if (camera['min-distance'] != undefined) { var minDistance = parseFloat(camera['min-distance']); this.controls.minDistance = minDistance; } if (camera['max-distance'] != undefined) { var maxDistance = parseFloat(camera['max-distance']); this.controls.maxDistance = maxDistance; } if (camera.rotation != undefined) { var rotation = new THREE.Vector3().fromArray(camera.rotation); rotation.x = rotation.x * Math.PI / 180; rotation.y = rotation.y * Math.PI / 180; rotation.z = rotation.z * Math.PI / 180; this.controls.rotation0 = rotation; this.controls.rotateLeft(rotation.y); this.controls.rotateUp(rotation.x); } _this.$emit('cameraChanged'); }, flyto:function(option){ var _distance = option.distance; var _rotation = option.rotation; this.controls.reset(); if (_distance != undefined) { var distance = parseFloat(_distance); var position0 = new THREE.Vector3(0, 0, distance); this.camera.position.copy(position0); } if (_rotation != undefined) { var rotation = new THREE.Vector3().fromArray(_rotation); rotation.x = rotation.x * Math.PI / 180; rotation.y = rotation.y * Math.PI / 180; rotation.z = rotation.z * Math.PI / 180; this.controls.rotateLeft(rotation.y); this.controls.rotateUp(rotation.x); } this.controls.update(); }, controlsPosSave(){ //var target0 = this.controls.target.clone(); var position0 = this.controls.object.position.clone(); var zoom0 = this.controls.object.zoom; return {position0:position0, zoom0: zoom0}; }, controlsPosReset(option){ this.controls.object.position.copy(option.position0); this.controls.object.zoom = option.zoom0; this.controls.update(); }, async parseMainMaterial( ) { //var _this = this; var rundata = this.rundata || {}; var materials = this.scenejson.materials; rundata.materials = rundata.materials || {}; rundata.material_selected = "白金"; for(var i=0; i<materials.length; i ){ var _m = materials[i]; rundata.materials[_m.name] = _m; } rundata.material_selected = materials[0]["name"]; }, parseMaterial(_diy) { //var _this = this; var rundata = this.rundata || {}; rundata.materials = rundata.materials || {}; rundata.materials_diy = rundata.materials_diy || {}; rundata.materials_diy[_diy.name] = _diy; }, async parsePart() { var geometries = this.scenejson.geometries; await this.parseGeometry(geometries); }, async parseGeometry(geometries, group){ var _this = this; var rundata = this.rundata; var parts = rundata.parts || []; var scene_url = this.scene_url; group = group || this.scene; for (var i = 0, l = geometries.length; i < l; i ) { var geometry = geometries[i]; var option = { name: geometry.name, url: scene_url geometry.url, position: geometry.position || [], rotation: geometry.rotation || [], scale: geometry.scale || [], bumpMap: geometry.bumpMap || '' }; var _geometry = await this.loadMesh(option); onLoad(_geometry, option); } rundata.parts = parts; function onLoad(_geometry, option){ if (_geometry.type=="BufferGeometry") { var _geometry1 = new THREE.Geometry(); _geometry1 = _geometry1.fromBufferGeometry(_geometry); _geometry = {}; _geometry = _geometry1; } var smooth_angle = 85; ZEUS.THREE_EXT.SoftenGeometryNormal(_geometry, smooth_angle, true); _geometry.computeBoundingBox(); var material = _this.getMaterial(option.name); ZEUS.THREE_EXT.UVWrap(_geometry); let scale = 23;//46;//25;//50; let userdata = _geometry.userdata; let w = userdata.map_size.x * scale; let h = userdata.map_size.y * scale; var max_w = 2048; if(w>max_w|| h>max_w){ var scaleX = w /max_w; var scaleY = h /max_w; var _scale = scaleX>scaleY?scaleX:scaleY; w = Math.floor(w/_scale); h = Math.floor(h/_scale); scale = scale / _scale; } userdata.map_size.scale = scale; let canvas_texture = new ZEUS.THREE_EXT.CanvasTexture({ width: w.toFixed(0), height: h.toFixed(0), bg_color: rundata.materials[rundata.material_selected].color }); //_this.dom.appendChild(canvas_texture.canvas); material.canvas_texture = canvas_texture; material.map = canvas_texture.canvas_texture; material.map.minFilter = THREE.LinearFilter; material.map.generateMipmaps = false; material.bumpMap = canvas_texture.canvas_texture; if(option.bumpMap!=''){ var mapHeight = new THREE.TextureLoader().load( option.bumpMap ); material.bumpMap = mapHeight; } if(option.bumpScale!=undefined){ material.bumpScale = option.bumpScale; } _geometry.uvsNeedsUpdate = true; var mesh = new THREE.Mesh(_geometry, material); mesh.castShadow = true; mesh.receiveShadow = true; if(option.name){ _this.nameObject(mesh, option.name); } if (option['position'].length > 0) { var position = option['position']; position = new THREE.Vector3().fromArray(position); mesh.position.copy(position); } if (option['rotation'].length > 0) { var rotation = option['rotation']; rotation = new THREE.Vector3().fromArray(rotation).multiplyScalar(Math.PI / 180); mesh.rotateX(rotation.x); mesh.rotateY(rotation.y); mesh.rotateZ(rotation.z); } if (option['scale'].length > 0) { let _scale = option['scale']; _scale = new THREE.Vector3().fromArray(_scale); mesh.scale.x = _scale.x; mesh.scale.y = _scale.y; mesh.scale.z = _scale.z; } mesh.userData.animate_enable = option['animate_enable'] || false; parts.push(mesh); group.add(mesh); } }, async loadMesh(option){ return new Promise(function(resolve,reject){ var loader = new ZEUS.THREE_EXT.MeshLoader(); var url = option.url; var onLoad = function(_geometry){ resolve(_geometry); }; var onProgress = null; var onError = reject; loader.load(url, onLoad, onProgress, onError); }); }, async loadImage(src){ return new Promise(function(resolve,reject){ var img = new Image(); img.onload = function(){ resolve(this); }; img.onerror = reject; img.src = src; }); }, async imagedata_to_image(img_data, rect) { var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); canvas.width = img_data.width; canvas.height = img_data.height; ctx.putImageData(img_data, 0, 0); let _img_data = ctx.getImageData(rect.left, rect.top, rect.width, rect.height); var data = _img_data.data, iLen = data.length ; for (var i = 0; i < iLen; i = 4) { if(data[i 3]==0){ data[i] = 255; data[i 1] = 255; data[i 2] = 255; data[i 3] = 255; } } var _canvas = document.createElement('canvas'); var _ctx = _canvas.getContext('2d'); _canvas.width = rect.width; _canvas.height = rect.height; _ctx.putImageData(_img_data, 0, 0); //var image = new Image(); let url = _canvas.toDataURL('image/png'); let image = await this.loadImage(url); return image; }, async loadTextureCube(urls){ return new Promise(function(resolve,reject){ var loader = new THREE.CubeTextureLoader(); var onLoad = function(texture){ resolve(texture); } loader.load(urls,onLoad ,null, reject); }); }, //设置材质名 setMaterial(name){ var rundata = this.rundata || {}; rundata.material_selected = name; var parts = rundata.parts || []; for(var i=0; i<parts.length; i ){ var mesh = parts[i]; var m = mesh.material; if(m==undefined){ continue; } if(m.name!=name){ var _m = rundata.materials[rundata.material_selected]; m.color = new THREE.Color(_m.color); m.name = _m.name; m.canvas_texture.setBgcolor(_m.color); } } }, getMaterialSelected(){ var rundata = this.rundata || {}; return rundata.material_selected || "白金"; }, onClickMaterial(name){ this.$parent.$emit('onClickMaterial', name ); }, getMaterial(/*mesh_name*/){ var rundata = this.rundata || {}; rundata.materials = rundata.materials || {}; var _m = rundata.materials[rundata.material_selected]; var material = new THREE.MeshPhysicalMaterial({ name: _m.name, color: _m.color, reflectivity: 0.99, metalness: 1, roughness: 0.01, envMap: this.textureCube, //envMapIntensity:1.5, bumpScale: 0.1, }); return material; }, clearObjects() { var objects = this.scene.children; while (objects.length > 0) { this.removeObject(objects[0]); } }, clear() { this.clearObjects(); }, toDataURL() { if (this.renderer.domElement.toDataURL) { return this.renderer.domElement.toDataURL('image/png'); } else { return ""; } } } } </script>

步骤二、调用ZeusStage.vue组件

<template> <div id="app"> <div class="container " style="background-image:url(images/background-3d.png)"> <ZeusStage ref="zeus_stage" :size="size" :scenejson="scenejson" :scene_url="scene_url"></ZeusStage> </div> </div> </template> <script> import ZeusStage from './components/ZeusStage.vue' export default { name: 'App', components: { ZeusStage }, mounted(){ var _this = this; function onresize(){ _this.size = { w: window.innerWidth -1, h: window.innerHeight -1 }; _this.$set(_this.size, 'w',_this.size.w); _this.$set(_this.size, 'h',_this.size.h) } window.onresize = onresize; onresize(); }, data(){ return { isActive: true, background:'images/bk.png', size: { w: 100, h: 100 }, scenejson:{ camera:{ distance: 80, rotation:[0,0,0], "min-distance": 70, "max-distance": 90 }, materials:[ { name:'玫瑰金', color:'#fed9d1', //'#feded1' }, { name:'白金', color:'#f3eeea' }, { name:'黄金', color:'#ffefc3' }, { name:'925银镀金', color:'#f3eeea' }, ], geometries:[ { name:"circle_small", url:"models/circle_small.zip", position:[0,7.8,0], rotation:[-90,0,0], }, { name:"circle_big", url:"models/circle_big.zip", position:[0,9.8,0], rotation:[-90,0,0], }, { name:"chain", url:"models/chain.zip", position:[0,0,0], rotation:[90,0,0], } ] }, scene_url:"",//"./public/", } }, methods:{ } } </script> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; height: 100%; width:100%; margin:0px; padding:0px; } .container{ float: left; width: 100%; margin: 0px; position: absolute; background-repeat: repeat; background-size: 320px; } </style>

0人点赞

THREEJS web3d

查看全文
大家还看了
也许喜欢
更多游戏

Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved