import { scene, axis, meshList, pointsList, axis2D, scene2D } from './history.js'; import { createAxisInfo } from './axisInfo/constant.js'; const lut = new THREE.Lut(); lut.addColorMap('axis', [[0.0, 0x00ee00], [0.25, 0xeeee00], [0.75, 0xee0000], [1.0, 0x4e0211]],); lut.setColorMap('axis',1024) let pointColors = [ { material: new THREE.PointsMaterial({ color: 0xD94E5D, size: 2, sizeAttenuation: false }), colors: 0xD94E5D, num: 15, }, { material: new THREE.PointsMaterial({ color: 0xE28B4A, size: 2, sizeAttenuation: false }), colors: 0xE28B4A, num: 14, }, { material: new THREE.PointsMaterial({ color: 0xEAC736, size: 2, sizeAttenuation: false }), colors: 0xEAC736, num: 10, }, { material: new THREE.PointsMaterial({ color: 0x9DB578, size: 2, sizeAttenuation: false }), colors: 0x9DB578, num: 7, }, { material: new THREE.PointsMaterial({ color: 0x50A3BA, size: 2, sizeAttenuation: false }), colors: 0x50A3BA, num: 5, }, ]; const initPoints = new THREE.Points( new THREE.BufferGeometry().setAttribute('position', new THREE.Float32BufferAttribute([0.5, 0, 0], 3)), new THREE.PointsMaterial({ color: 0x0082df, size: 2, sizeAttenuation: false }) ); //柱子材质数据 let meterials = [ { material: new THREE.MeshBasicMaterial({ color: '#4e0211', }), max: 0.75 }, { material: new THREE.MeshBasicMaterial({ color: '#ee0000', }), max: 0.5 }, { material: new THREE.MeshBasicMaterial({ color: '#eeee00', }), max: 0.25 }, { material: new THREE.MeshBasicMaterial({ color: '#00ee00', }), max: 0, }, ]; const initGeometry = new THREE.BoxGeometry(0.6, 1, 2.5); //绘制图表柱子 const drawChartsContent = (px, pz, py = 50, max, pxNum) => { let y = py < 0 ? -py : py; const material = new THREE.MeshBasicMaterial({color:lut.getColor(Number(y)/max)});// //const material = meterials.find(item => (y / max) >= item.max).material; //柱子宽高长 const geometry = initGeometry.clone(); geometry.scale(1, y, 1); geometry.translate(49.4 - pxNum, Math.fround(py / 2), 360 - pz); return { geometry, material } } //正弦曲线绘制 const drawSinLine = (obj) => { let { line, color } = obj, list = []; line.forEach(item => { list.push(new THREE.Vector3(...item)); }) let geometry = new THREE.BufferGeometry(); //声明一个几何体对象Geometry // 三维样条曲线 Catmull-Rom算法 let curve = new THREE.CatmullRomCurve3(list); //getPoints是基类Curve的方法,返回一个vector3对象作为元素组成的数组 let points = curve.getPoints(200); //分段数100,返回101个顶点 // setFromPoints方法从points中提取数据改变几何体的顶点属性vertices geometry.setFromPoints(points); //材质对象 let material = new THREE.LineBasicMaterial({ color, linewidth: 1, }); //线条模型对象 let modelLine = new THREE.Line(geometry, material); return modelLine //scene.add(line); //线条对象添加到场景中 } //绘制网格线条 const drawLine = (obj) => { let { line, color, position, margin, num } = obj let geometry = new THREE.BufferGeometry(); //创建一个Buffer类型几何体对象 //3个为一组,表示一个顶点的xyz坐标 geometry.setAttribute('position', new THREE.Float32BufferAttribute(line, 3)) // 线条渲染模式 let material = new THREE.LineBasicMaterial({ color, //线条颜色 });//材质对象 let LineList = []; let modelLine = new THREE.Line(geometry, material);//线条模型对象 LineList.push(modelLine) for (let i = 1; i < num; i++) { let lineChildren = modelLine.clone()['translate' + position](i * margin) LineList.push(lineChildren); } return LineList } // 添加文字geometry const add3DText = (text, callback) => { let { content, url, size, set, rotation, xyz } = text; let loader = new THREE.FontLoader(); //加载相应的字体,下面字体名和样式组成gentilis_bold.typeface.json 完整文件名 let fontJsonUrl = url ? url : 'common/fonts/Century Gothic_Regular.json'; //你的字体json路径,文件名规格随意 loader.load(fontJsonUrl, function (font) { const color = 0xffffff; const matLite = new THREE.MeshBasicMaterial({ color: color, // 字体大小 }); const geometry = new THREE.TextGeometry(content, { font: font, size: size ? size : 5, height: 1, }); geometry.translate(...xyz); if (rotation) { for (let i of rotation) { geometry['rotate' + i[0]](Math.PI / i[1]) } } let mesh = new THREE.Mesh(geometry, matLite); // mesh.scale.set(2, 2, 2) if (set) { mesh.scale.set(...set); } mesh.castShadow = true; mesh.receiveShadow = true; mesh.name = 'text'; callback(mesh) }); } // 添加精灵图文字 const draw2DText = (obj) => { let scale = 1;//window.devicePixelRatio; let { content, w, h, color, font, xyz, size, cw, ch, rotate } = obj; cw = cw ? cw : 6; ch = ch ? ch : 8; let canvas = document.createElement('canvas') canvas.style.width = w * scale; canvas.style.height = h * scale; if (rotate) { canvas.width = w * cw * scale * 3; canvas.height = h * ch * scale * 2; } else { canvas.width = w * cw * scale * 2; canvas.height = h * ch * scale * 3; } let ctx = canvas.getContext('2d'); ctx.fillStyle = color; ctx.strokeStyle = color; ctx.font = font; ctx.direction = "ltr"; // 文本方向从左向右 ctx.textAlign = "left"; // 左对齐 ctx.textBaseline = 'middle'//基线对齐选项,决定文字垂直方向的对齐方式 if (rotate) { ctx.translate(canvas.width / 2, canvas.height); ctx.rotate(-Math.PI / 2); ctx.fillText(content, h, 0); //ctx.strokeText(content, h, 0); } else { for (let i = 0; i < 1; i++) { ctx.fillText(content[i], 0, canvas.height / 2); ctx.strokeText(content[i], 0, canvas.height / 2); } } let texture = new THREE.CanvasTexture(canvas) // texture.needsUpdate = true//如果编码类型在纹理已被一个材质使用之后发生了改变, 你需要来设置Material.needsUpdate为true来使得材质重新编译 let geometry = new THREE.BufferGeometry(); //创建一个Buffer类型几何体对象 //3个为一组,表示一个顶点的xyz坐标 geometry.setAttribute('position', new THREE.Float32BufferAttribute(xyz, 3)); const material = new THREE.PointsMaterial({ map: texture, transparent: true,//材质透明 size: size ? size : 16.0, //点对象像素尺寸 }); const pointsText = new THREE.Points(geometry, material); pointsText.name = 'pointsText'; return pointsText; } const drawAxis = (size, minNum, is2DInit) => { scene.remove(...scene.children.filter(item => item.name === 'axisNumberText')) if (axis.children.length) { axis.remove(...axis.children) } let axisText = new THREE.Group(); axisText.name = 'axisNumberText'; scene.add(axisText) const data = createAxisInfo(size, minNum); axis.scale.set(...data[size]['set']) meshList.scale.set(...data[size]['set']) pointsList.scale.set(...data[size]['set']) data[size]['prps'].forEach(async item => { switch (item.type) { case 'plan': axis.add(drawPlan(item)); break; case 'line': axis.add(...drawLine(item)); break; case 'curveLine': axis.add(drawSinLine(item)); break; case 'text': axisText.add(draw2DText(item)); } }); if (is2DInit) { return; } drawAxis2D(size, minNum); } const drawAxis2D = (size, minNum) => { if (axis2D.children.length) { axis2D.remove(...axis2D.children) } let axisList = scene2D?.children.filter(item => item.name === 'axisNumberText'); axisList && scene2D.remove(...axisList) let axisText = new THREE.Group(); const data = createAxisInfo(size, minNum); axisText.name = 'axisNumberText'; scene2D.add(axisText) axis2D.scale.set(...data[size]['set']) let list = scene2D.getObjectByName('chartsPoint') if (list) { list.scale.set(...data[size]['set']) } data[size]['prpd'].forEach(async item => { switch (item.type) { case 'line': axis2D.add(...drawLine(item)); break; case 'curveLine': axis2D.add(drawSinLine(item)); break; case 'text': axisText.add(draw2DText(item)); } }); } //绘制平面 const drawPlan = (obj) => { const { size, color } = obj; let geometry = new THREE.PlaneGeometry(size, 360); //创建一个Buffer类型几何体对象 geometry.rotateX(Math.PI / 2).translate(size/2, 0, 180); // 三角面(网格)渲染模式 let material = new THREE.MeshBasicMaterial({ color, //三角面颜色 transparent: true,//透明 opacity: 0.2, side: THREE.DoubleSide, //两面可见 }); //材质对象 let mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh mesh.name = 'plan'; //scene.add(mesh); return mesh } export { drawChartsContent, drawSinLine, drawLine, add3DText, draw2DText, drawAxis, drawAxis2D, initPoints, pointColors, drawPlan }