You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

280 lines
9.7 KiB
JavaScript

9 months ago
import { scene, axis, meshList, pointsList, axis2D, scene2D } from './index.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 }