Three.js基础功能学习十六:智能黑板实现实例三

续上章继续实现智能黑板示例:

  使用Vue3+Elementplus+Threejs实现智能黑板,实现基础的几何图形、三维图形、手写板的元素动态绘制效果,并实现数学、物理、化学、地理、生物等课程常见的图形元素及函数图形等。

源码下载地址: 点击下载
效果演示:









一、学习视频

  https://www.bilibili.com/video/BV1JT69BUEdD/

二、二维图形绘制功能

2.1物体定义

  1. D2Mesh.ts
javascript 复制代码
import type {ToolBarMeshItem} from "@/model/ToolItem/ToolBarMeshItem";
import * as THREE from "three"

/**
 * 手写的物体对象
 */
export default class D2Mesh extends THREE.Group{
    //手写线的材质信息
    _item: ToolBarMeshItem|null;
    //绘制的平面
    _plane: THREE.Mesh;
    //当前编辑的物体
    _currentMesh:THREE.Mesh;
    //添加的子对象的数据
    _objects:THREE.Mesh[] = [];

    constructor(planGeometry: THREE.PlaneGeometry, planMaterial: THREE.Material,item?:ToolBarMeshItem|null) {
        super();

        if(item){
            this._item = item;
        }else{
            this._item = null;
        }

        this._plane = new THREE.Mesh(planGeometry, planMaterial);
        super.add(this._plane);
    }
    
    /**
     * 清空手写内容
     */
    public clear() {
        this.getChildren().forEach((item:THREE.Mesh)=>{
            item.removeFromParent();
        });
        this._objects.length = 0;
    }
    
    /**
     * 拿到所有的物体信息
     * @returns 
     */
    public getChildren() {
        let result =  (this as THREE.Group).children;
        return result.filter((item: { id: any; })=>item.id !== this.plane.id);
    }
    
    /**
     * 添加物体到场景中
     * @param mesh 要添加的物体信息
     */
    public add(mesh: THREE.Mesh) {
       super.add(mesh);
       this._objects.push(mesh);
    }

    /**
     * 创建三维物体
     * @param point 
     */
    public create(point:THREE.Vector3){
        if(!this.item || !this.item.geometry || !this.item.mesh){
            return null;
        }

        let mesh:THREE.Mesh = this.item.mesh(point);
        mesh.item = this.item;

        this.add(mesh);
        this.currentMesh = mesh;

        return mesh;
    }

    /**
     * 从上级移除
     */
    public removeFromParent() {
        super.removeFromParent();
    }
    
    /**
     * 获取指定下标的物体信息
     * @param index 
     * @returns 
     */
    public getObj(index:number): THREE.Mesh|null {
        if(index<=0||index>this._objects.length){
            return null;
        }
        return this._objects[index];
    }
    
    set plane(plane: THREE.Mesh) {
        this._plane = plane;
    }
    get plane(): THREE.Mesh {
        return this._plane;
    }

    set item(item: ToolBarMeshItem) {
        this._item = item;
    }
    get item(): ToolBarMeshItem|null {
        return this._item;
    }

    set currentMesh(currentMesh: THREE.Mesh) {
        this._currentMesh = currentMesh;
    }
    get currentMesh(): THREE.Mesh|null {
        return this._currentMesh;
    }

    set objects(objects: THREE.Mesh[]) {
        this._objects = objects;
    }
    get objects(): THREE.Mesh[] {
        return this._objects;
    }
}
  1. Base2dMeshItem.ts
javascript 复制代码
import { COMMOND_TYPE_2D_MESH } from "@/common/Constant";
import type {  ToolBarMeshItem } from "../ToolItem/ToolBarMeshItem";
import type { ToolBarItem } from "../ToolItem/ToolBartem";
import { BaseMeshItem } from "./BaseMeshItem";

export class Base2dMeshItem extends BaseMeshItem{
    constructor(
        name:string,
        icon:string,
        key:string,
        fkey?: string | undefined,
        selected?: boolean | undefined,
        status?: string[] | undefined,
        children?: ToolBarItem[] | ToolBarMeshItem[] | undefined
    ){
        super(name,icon,key,fkey,COMMOND_TYPE_2D_MESH,selected,status,children);
    }
}
  1. ArrowDownMeshItem.ts
javascript 复制代码
import { ToolBarMeshColorItemConfigItem, ToolBarMeshMaterialItemConfigItem, ToolBarMeshSizeItemConfigItem, ToolBarMeshTextureItemConfigItem } from "@/model/ToolItem/ToolBarMeshItem";
import { Base2dMeshItem } from "../Base2dMeshItem";
import * as THREE from "three"
import { useConfigStore } from "@/stores/config";

/**
 * 箭头
 */
export class ArrowDownMeshItem extends Base2dMeshItem{

    constructor(name:string,icon:string,key:string,fkey:string){
        super(name,icon,key,fkey);

        this.material = this._material;

        this.mesh = this._mesh;

        this.mouseMove = this._mouseMove;
        
        this.config = {
            currentMaterial:new ToolBarMeshMaterialItemConfigItem('select','材质',['currentMaterial', 'value'],THREE.PointsMaterial,false,false,undefined,undefined,undefined,[{ value: '',label: '纯色'}]),
           texture: new ToolBarMeshTextureItemConfigItem('select','纹理',['currentMaterial', 'value'],'',true,true,undefined,undefined,undefined,[{
                value: '',
                label: '颜色'
            }, {
                value: THREE.VideoTexture,
                label: '视频'
            }, {
                value: THREE.CanvasTexture,
                label: 'Canvas'
            }, {
                value: THREE.DataTexture,
                label: '数据'
            }, {
                value: THREE.Texture,
                label: '自定义'
            }]),
            size:new ToolBarMeshSizeItemConfigItem('slider','大小',['size', 'value'],useConfigStore()?.d3Config?.camera?.near || 0.001,true,true,0,useConfigStore()?.d3Config?.camera?.far || 1000,useConfigStore()?.d3Config?.camera?.near || 0.001),
            color:new ToolBarMeshColorItemConfigItem('color','颜色',['color', 'value'],useConfigStore()?.d3Config?.mesh?.fill?.color || new THREE.Color('#FFFfff'),true,true),
        }
    }

    private _material (){
        let that = this as Base2dMeshItem;
        if(!that.config){
            return null;
        }
        let color = (that.config && that.config.color) ? that.config.color.value : useConfigStore().d3Config.mesh.line.color;
        let lineWidth = (that.config && that.config.size) ? that.config.size.value : useConfigStore().d3Config.mesh.line.width;
        if (that.config && that.config.currentMaterial && that.config.currentMaterial.value) {
            return new that.config.currentMaterial.value({
                color: color,
                lineWidth: lineWidth
            });
        } else {
            return new THREE.LineBasicMaterial({
                color: color,
                lineWidth: lineWidth
            });
        }
    }

    protected _mesh(point:THREE.Vector3){
        const geometry = this.geometry?this.geometry():this._geometry();
        geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [
            point.x-0.1,    point.y+0.1,        point.z+0.1,
            point.x,        point.y,            point.z+0.1,
            point.x+0.1,    point.y+0.1,        point.z+0.1
        ], 3 ) );
        const material = this.material?this.material():new THREE.MeshBasicMaterial();
        return new THREE.Line(geometry, material)
    }
    protected _mouseMove(point: THREE.Vector3, mesh: THREE.Mesh,event:MouseEvent){
        mesh.geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [
            point.x-0.1,    point.y+0.1,        point.z+0.1,
            point.x,        point.y,            point.z+0.1,
            point.x+0.1,    point.y+0.1,        point.z+0.1
        ], 3 ) );
    }
}
  1. ArrowLeftMeshItem.ts
javascript 复制代码
import { ToolBarMeshColorItemConfigItem, ToolBarMeshMaterialItemConfigItem, ToolBarMeshSizeItemConfigItem, ToolBarMeshTextureItemConfigItem } from "@/model/ToolItem/ToolBarMeshItem";
import { Base2dMeshItem } from "../Base2dMeshItem";
import * as THREE from "three"
import { useConfigStore } from "@/stores/config";

/**
 * 箭头
 */
export class ArrowLeftMeshItem extends Base2dMeshItem{

    constructor(name:string,icon:string,key:string,fkey:string){
        super(name,icon,key,fkey);

        this.material = this._material;

        this.mesh = this._mesh;

        this.mouseMove = this._mouseMove;
        
        this.config = {
            currentMaterial:new ToolBarMeshMaterialItemConfigItem('select','材质',['currentMaterial', 'value'],THREE.PointsMaterial,false,false,undefined,undefined,undefined,[{ value: '',label: '纯色'}]),
           texture: new ToolBarMeshTextureItemConfigItem('select','纹理',['currentMaterial', 'value'],'',true,true,undefined,undefined,undefined,[{
                value: '',
                label: '颜色'
            }, {
                value: THREE.VideoTexture,
                label: '视频'
            }, {
                value: THREE.CanvasTexture,
                label: 'Canvas'
            }, {
                value: THREE.DataTexture,
                label: '数据'
            }, {
                value: THREE.Texture,
                label: '自定义'
            }]),
            size:new ToolBarMeshSizeItemConfigItem('slider','大小',['size', 'value'],useConfigStore()?.d3Config?.camera?.near || 0.001,true,true,0,useConfigStore()?.d3Config?.camera?.far || 1000,useConfigStore()?.d3Config?.camera?.near || 0.001),
            color:new ToolBarMeshColorItemConfigItem('color','颜色',['color', 'value'],useConfigStore()?.d3Config?.mesh?.fill?.color || new THREE.Color('#FFFfff'),true,true),
        }
    }

    private _material (){
        let that = this as Base2dMeshItem;
        if(!that.config){
            return null;
        }
        let color = (that.config && that.config.color) ? that.config.color.value : useConfigStore().d3Config.mesh.line.color;
        let lineWidth = (that.config && that.config.size) ? that.config.size.value : useConfigStore().d3Config.mesh.line.width;
        if (that.config && that.config.currentMaterial && that.config.currentMaterial.value) {
            return new that.config.currentMaterial.value({
                color: color,
                lineWidth: lineWidth
            });
        } else {
            return new THREE.LineBasicMaterial({
                color: color,
                lineWidth: lineWidth
            });
        }
    }

    protected _mesh(point:THREE.Vector3){
        const geometry = this.geometry?this.geometry():this._geometry();
        geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [
            point.x+0.1,    point.y-0.1,        point.z+0.1,
            point.x,        point.y,            point.z+0.1,
            point.x+0.1,    point.y+0.1,        point.z+0.1
        ], 3 ) );
        const material = this.material?this.material():new THREE.MeshBasicMaterial();
        return new THREE.Line(geometry, material)
    }
    protected _mouseMove(point: THREE.Vector3, mesh: THREE.Mesh,event:MouseEvent){
        mesh.geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [
            point.x+0.1,    point.y-0.1,        point.z+0.1,
            point.x,        point.y,            point.z+0.1,
            point.x+0.1,    point.y+0.1,        point.z+0.1
        ], 3 ) );
    }
}
  1. ArrowRightMeshItem.ts
javascript 复制代码
import { ToolBarMeshColorItemConfigItem, ToolBarMeshMaterialItemConfigItem, ToolBarMeshSizeItemConfigItem, ToolBarMeshTextureItemConfigItem } from "@/model/ToolItem/ToolBarMeshItem";
import { Base2dMeshItem } from "../Base2dMeshItem";
import * as THREE from "three"
import { useConfigStore } from "@/stores/config";

/**
 * 箭头
 */
export class ArrowRightMeshItem extends Base2dMeshItem{

    constructor(name:string,icon:string,key:string,fkey:string){
        super(name,icon,key,fkey);

        this.material = this._material;

        this.mesh = this._mesh;

        this.mouseMove = this._mouseMove;
        
        this.config = {
            currentMaterial:new ToolBarMeshMaterialItemConfigItem('select','材质',['currentMaterial', 'value'],THREE.PointsMaterial,false,false,undefined,undefined,undefined,[{ value: '',label: '纯色'}]),
           texture: new ToolBarMeshTextureItemConfigItem('select','纹理',['currentMaterial', 'value'],'',true,true,undefined,undefined,undefined,[{
                value: '',
                label: '颜色'
            }, {
                value: THREE.VideoTexture,
                label: '视频'
            }, {
                value: THREE.CanvasTexture,
                label: 'Canvas'
            }, {
                value: THREE.DataTexture,
                label: '数据'
            }, {
                value: THREE.Texture,
                label: '自定义'
            }]),
            size:new ToolBarMeshSizeItemConfigItem('slider','大小',['size', 'value'],useConfigStore()?.d3Config?.camera?.near || 0.001,true,true,0,useConfigStore()?.d3Config?.camera?.far || 1000,useConfigStore()?.d3Config?.camera?.near || 0.001),
            color:new ToolBarMeshColorItemConfigItem('color','颜色',['color', 'value'],useConfigStore()?.d3Config?.mesh?.fill?.color || new THREE.Color('#FFFfff'),true,true),
        }
    }

    private _material (){
        let that = this as Base2dMeshItem;
        if(!that.config){
            return null;
        }
        let color = (that.config && that.config.color) ? that.config.color.value : useConfigStore().d3Config.mesh.line.color;
        let lineWidth = (that.config && that.config.size) ? that.config.size.value : useConfigStore().d3Config.mesh.line.width;
        if (that.config && that.config.currentMaterial && that.config.currentMaterial.value) {
            return new that.config.currentMaterial.value({
                color: color,
                lineWidth: lineWidth
            });
        } else {
            return new THREE.LineBasicMaterial({
                color: color,
                lineWidth: lineWidth
            });
        }
    }

    protected _mesh(point:THREE.Vector3){
        const geometry = this.geometry?this.geometry():this._geometry();
        geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [
            point.x-0.1,    point.y-0.1,        point.z+0.1,
            point.x,        point.y,            point.z+0.1,
            point.x-0.1,    point.y+0.1,        point.z+0.1
        ], 3 ) );
        const material = this.material?this.material():new THREE.MeshBasicMaterial();
        return new THREE.Line(geometry, material)
    }
    protected _mouseMove(point: THREE.Vector3, mesh: THREE.Mesh,event:MouseEvent){
        mesh.geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [
            point.x-0.1,    point.y-0.1,        point.z+0.1,
            point.x,        point.y,            point.z+0.1,
            point.x-0.1,    point.y+0.1,        point.z+0.1
        ], 3 ) );
    }
}
  1. ArrowUpMeshItem.ts
javascript 复制代码
import { ToolBarMeshColorItemConfigItem, ToolBarMeshMaterialItemConfigItem, ToolBarMeshSizeItemConfigItem, ToolBarMeshTextureItemConfigItem } from "@/model/ToolItem/ToolBarMeshItem";
import { Base2dMeshItem } from "../Base2dMeshItem";
import * as THREE from "three"
import { useConfigStore } from "@/stores/config";

/**
 * 箭头
 */
export class ArrowUpMeshItem extends Base2dMeshItem{

    constructor(name:string,icon:string,key:string,fkey:string){
        super(name,icon,key,fkey);

        this.material = this._material;

        this.mesh = this._mesh;

        this.mouseMove = this._mouseMove;
        
        this.config = {
            currentMaterial:new ToolBarMeshMaterialItemConfigItem('select','材质',['currentMaterial', 'value'],THREE.PointsMaterial,false,false,undefined,undefined,undefined,[{ value: '',label: '纯色'}]),
           texture: new ToolBarMeshTextureItemConfigItem('select','纹理',['currentMaterial', 'value'],'',true,true,undefined,undefined,undefined,[{
                value: '',
                label: '颜色'
            }, {
                value: THREE.VideoTexture,
                label: '视频'
            }, {
                value: THREE.CanvasTexture,
                label: 'Canvas'
            }, {
                value: THREE.DataTexture,
                label: '数据'
            }, {
                value: THREE.Texture,
                label: '自定义'
            }]),
            size:new ToolBarMeshSizeItemConfigItem('slider','大小',['size', 'value'],useConfigStore()?.d3Config?.camera?.near || 0.001,true,true,0,useConfigStore()?.d3Config?.camera?.far || 1000,useConfigStore()?.d3Config?.camera?.near || 0.001),
            color:new ToolBarMeshColorItemConfigItem('color','颜色',['color', 'value'],useConfigStore()?.d3Config?.mesh?.fill?.color || new THREE.Color('#FFFfff'),true,true),
        }
    }

    private _material (){
        let that = this as Base2dMeshItem;
        if(!that.config){
            return null;
        }
        let color = (that.config && that.config.color) ? that.config.color.value : useConfigStore().d3Config.mesh.line.color;
        let lineWidth = (that.config && that.config.size) ? that.config.size.value : useConfigStore().d3Config.mesh.line.width;
        if (that.config && that.config.currentMaterial && that.config.currentMaterial.value) {
            return new that.config.currentMaterial.value({
                color: color,
                lineWidth: lineWidth
            });
        } else {
            return new THREE.LineBasicMaterial({
                color: color,
                lineWidth: lineWidth
            });
        }
    }

    protected _mesh(point:THREE.Vector3){
        const geometry = this.geometry?this.geometry():this._geometry();
        geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [
            point.x-0.1,    point.y-0.1,        point.z+0.1,
            point.x,        point.y,            point.z+0.1,
            point.x+0.1,    point.y-0.1,        point.z+0.1
        ], 3 ) );
        const material = this.material?this.material():new THREE.MeshBasicMaterial();
        return new THREE.Line(geometry, material)
    }

    protected _mouseMove(point: THREE.Vector3, mesh: THREE.Mesh,event:MouseEvent){
        mesh.geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [
            point.x-0.1,    point.y-0.1,        point.z+0.1,
            point.x,        point.y,            point.z+0.1,
            point.x+0.1,    point.y-0.1,        point.z+0.1
        ], 3 ) );
    }
}
  1. ChalkMeshItem.ts
javascript 复制代码
import { COMMOND_TYPE_2D_MESH } from "@/common/Constant";
import { Base2dMeshItem } from "../Base2dMeshItem";
import * as THREE from "three"
import { useConfigStore } from "@/stores/config";
import { ToolBarMeshColorItemConfigItem, ToolBarMeshMaterialItemConfigItem, ToolBarMeshSizeItemConfigItem} from "@/model/ToolItem/ToolBarMeshItem";

/**
 * 点的类型
 */
export class ChalkMeshItem extends Base2dMeshItem{
    constructor(name:string,icon:string,key:string,fkey:string){
        super(name,icon,key,fkey);

        this.material = this._material;

        this.mesh = this._mesh

        this.mouseMove = this._mouseMove;
      
        this.config = {
           currentMaterial: new ToolBarMeshMaterialItemConfigItem('select','材质',['currentMaterial', 'value'],THREE.LineBasicMaterial,true,true,undefined,undefined,undefined,[{
                value: THREE.LineBasicMaterial,
                label: '实线'
            }, {
                value: THREE.LineDashedMaterial,
                label: '虚线'
            }]),
            size:new ToolBarMeshSizeItemConfigItem('slider','大小',['size', 'value'],useConfigStore()?.d3Config?.camera?.near || 0.001,true,true,0,useConfigStore()?.d3Config?.maxSize||8,useConfigStore()?.d3Config?.camera?.near || 0.001),
            color:new ToolBarMeshColorItemConfigItem('color','颜色',['color', 'value'],useConfigStore()?.d3Config?.mesh?.fill?.color || new THREE.Color('#FFFfff'),true,true),
        }
    }

    private _material (){
        let that = this as Base2dMeshItem;
        if(!that.config){
            return null;
        }

        let color = (that.config && that.config.color) ? that.config.color.value : useConfigStore().d3Config.mesh.line.color;
        let lineWidth = (that.config && that.config.size) ? that.config.size.value : useConfigStore().d3Config.mesh.line.width;
        if (that.config && that.config.currentMaterial && that.config.currentMaterial.value) {
            return new that.config.currentMaterial.value({
                color: color,
                lineWidth: lineWidth
            });
        } else {
            return new THREE.LineBasicMaterial({
                color: color,
                lineWidth: lineWidth
            });
        }
    }

    protected _mesh(point:THREE.Vector3){
        const geometry = this.geometry?this.geometry():this._geometry();
        geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [point.x,point.y,point.z+0.1], 3 ) );
        const material = this.material?this.material():new THREE.MeshBasicMaterial();
        return new THREE.Line(geometry, material)
    }

    protected _mouseMove(point: THREE.Vector3, mesh: THREE.Mesh,event:MouseEvent){
        let positions = [...mesh.geometry.getAttribute('position').array];

        // if (positions.length < 3) {
        //     positions.push(point.x, point.y, point.z);
        // } else {
        //     positions[3] = point.x;
        //     positions[4] = point.y;
        //     positions[5] = point.z;
        // }
        positions.push(point.x, point.y, point.z+0.1);

        mesh.geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
    }
}
  1. CircleMeshItem.ts
javascript 复制代码
import { ToolBarMeshColorItemConfigItem, ToolBarMeshMaterialItemConfigItem, ToolBarMeshRadiusItemConfigItem, ToolBarMeshSizeItemConfigItem, ToolBarMeshTextureItemConfigItem } from "@/model/ToolItem/ToolBarMeshItem";
import { Base2dMeshItem } from "../Base2dMeshItem";
import * as THREE from "three"
import { useConfigStore } from "@/stores/config";

/**
 * 圆
 */
export class CircleMeshItem extends Base2dMeshItem {

    constructor(name: string, icon: string, key: string, fkey: string) {
        super(name, icon, key, fkey);

        this.geometry = this._geometry;

        this.material = this._material;

        this.mouseMove = this._mouseMove;

        this.config = {
            currentMaterial: new ToolBarMeshMaterialItemConfigItem('select', '材质', ['currentMaterial', 'value'], THREE.MeshBasicMaterial, false, false, undefined, undefined, undefined, [{ value: '', label: '纯色' }]),
            texture: new ToolBarMeshTextureItemConfigItem('select', '纹理', ['currentMaterial', 'value'], '', true, true, undefined, undefined, undefined, [{
                value: '',
                label: '颜色'
            }, {
                value: THREE.VideoTexture,
                label: '视频'
            }, {
                value: THREE.CanvasTexture,
                label: 'Canvas'
            }, {
                value: THREE.DataTexture,
                label: '数据'
            }, {
                value: THREE.Texture,
                label: '自定义'
            }]),
            size: new ToolBarMeshRadiusItemConfigItem('slider', '大小', ['size', 'value'], 0.1, true, true, 0, useConfigStore()?.d3Config?.maxSize||8, useConfigStore()?.d3Config?.camera?.near || 0.001),
            color: new ToolBarMeshColorItemConfigItem('color', '颜色', ['color', 'value'], useConfigStore()?.d3Config?.mesh?.fill?.color || new THREE.Color('#FFFfff'), true, true),
        }
    }

    protected _geometry() {
        let that = this as Base2dMeshItem;
        let size = (that.config && that.config.size) ? that.config.size.value : useConfigStore().d3Config.camera.near;
        return new THREE.CircleGeometry(size, 132);
    }

    private _material() {
        let that = this as Base2dMeshItem;
        if (!that.config) {
            return null;
        }
        let color = (that.config && that.config.color) ? that.config.color.value : useConfigStore().d3Config.mesh.line.color;
        let lineWidth = (that.config && that.config.size) ? that.config.size.value : useConfigStore().d3Config.mesh.line.width;
        if (that.config && that.config.currentMaterial && that.config.currentMaterial.value) {
            return new that.config.currentMaterial.value({
                color: color,
                lineWidth: lineWidth
            });
        } else {
            return new THREE.MeshBasicMaterial({
                color: color,
                lineWidth: lineWidth
            });
        }
    }
    protected _mouseMove(point: THREE.Vector3, mesh: THREE.Mesh,event:MouseEvent) {
        if(!mesh){
            return;
        }
        point.z += 0.1;
        mesh.position.copy(point);
    }
}
  1. EquilateralTriangleMeshItem.ts
javascript 复制代码
import { ToolBarMeshColorItemConfigItem, ToolBarMeshItemConfigItem, ToolBarMeshMaterialItemConfigItem, ToolBarMeshSizeItemConfigItem, ToolBarMeshTextureItemConfigItem } from "@/model/ToolItem/ToolBarMeshItem";
import { Base2dMeshItem } from "../Base2dMeshItem";
import * as THREE from "three"
import { useConfigStore } from "@/stores/config";
import type { OptionData } from "@/model/OptionData";

export class  ToolBarMeshWidthItemConfigItem  extends ToolBarMeshItemConfigItem<number>{
    constructor(
        type: string,
        name: string,
        modelPath: string[],
        value: number,
        auto: boolean= false,
        form: boolean = false,
        min?: number,
        max?: number,
        step?: number,
        options?: OptionData[]
    ){
        super(type,
        name,
        modelPath,
        value,
        auto,
        form,
        min,
        max,
        step,
        options);
    }
    updateConfig(mesh:THREE.Mesh, value:number) {
        let width = value;
        let points = mesh.geometry.getAttribute('position');
        let a = new THREE.Vector3(points[0],points[1],points[2]);
        let b = new THREE.Vector3(points[3],points[4],points[5]);
        let c = new THREE.Vector3(points[6],points[7],points[8]);

        let center = new THREE.Vector3((a.x+b.x+c.x)/3,(a.y+b.y+c.y)/3,a.z);
        const vertices = [
            // 左下角
            center.x, center.y+ width/Math.sqrt(3), center.z + 0.1,
            // 右下角
            center.x- width/2, center.y-width/Math.sqrt(3), center.z + 0.1,
            // 右上角
            center.x+width/2, center.y-width/Math.sqrt(3), center.z + 0.1
        ];
        mesh.geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
    }
}

/**
 * 三角形
 */
export class EquilateralTriangleMeshItem extends Base2dMeshItem{

    constructor(name:string,icon:string,key:string,fkey:string){
        super(name,icon,key,fkey);

        this.material = this._material;

        this.mesh = this._mesh;

        this.mouseMove = this._mouseMove;
        
        this.config = {
            currentMaterial:new ToolBarMeshMaterialItemConfigItem('select','材质',['currentMaterial', 'value'],THREE.MeshBasicMaterial,false,false,undefined,undefined,undefined,[{ value: '',label: '纯色'}]),
           texture: new ToolBarMeshTextureItemConfigItem('select','纹理',['currentMaterial', 'value'],'',true,true,undefined,undefined,undefined,[{
                value: '',
                label: '颜色'
            }, {
                value: THREE.VideoTexture,
                label: '视频'
            }, {
                value: THREE.CanvasTexture,
                label: 'Canvas'
            }, {
                value: THREE.DataTexture,
                label: '数据'
            }, {
                value: THREE.Texture,
                label: '自定义'
            }]),
            size:new ToolBarMeshSizeItemConfigItem('slider','线条大小',['size', 'value'],useConfigStore()?.d3Config?.camera?.near || 0.001,true,true,0,useConfigStore()?.d3Config?.maxSize||8,useConfigStore()?.d3Config?.camera?.near || 0.001),
            width: new ToolBarMeshWidthItemConfigItem('slider', '边长', ['width', 'value'], 2, true, true, 0, useConfigStore()?.d3Config?.maxSize||8, useConfigStore()?.d3Config?.camera?.near || 0.001),
            color:new ToolBarMeshColorItemConfigItem('color','颜色',['color', 'value'],useConfigStore()?.d3Config?.mesh?.fill?.color || new THREE.Color('#FFFfff'),true,true),
        }
    }

    private _material (){
        let that = this as Base2dMeshItem;
        if(!that.config){
            return null;
        }
        let color = (that.config && that.config.color) ? that.config.color.value : useConfigStore().d3Config.mesh.line.color;
        let lineWidth = (that.config && that.config.size) ? that.config.size.value : useConfigStore().d3Config.mesh.line.width;
        if (that.config && that.config.currentMaterial && that.config.currentMaterial.value) {
            return new that.config.currentMaterial.value({
                color: color,
                lineWidth: lineWidth
            });
        } else {
            return new THREE.MeshBasicMaterial({
                color: color,
                lineWidth: lineWidth
            });
        }
    }

    protected _mesh(point:THREE.Vector3){
        let that = this as Base2dMeshItem;

        const geometry = this.geometry?this.geometry():this._geometry();
        
        let width = (that.config && that.config.width) ? that.config.width.value : useConfigStore().d3Config.camera.near;

        const vertices = [
            // 左下角
            point.x, point.y+ width/Math.sqrt(3), point.z + 0.1,
            // 右下角
            point.x- width/2, point.y-width/Math.sqrt(3), point.z + 0.1,
            // 右上角
            point.x+width/2, point.y-width/Math.sqrt(3), point.z + 0.1
        ];
        geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));

        const material = this.material?this.material():new THREE.MeshBasicMaterial();
        return new THREE.Mesh(geometry, material)
    }

    protected _mouseMove(point: THREE.Vector3, mesh: THREE.Mesh,event:MouseEvent){
        if(!mesh){
            return;
        }
        // point.z += 0.1;
        // mesh.position.copy(point);
        let that = this as Base2dMeshItem;
        let width = (that.config && that.config.width) ? that.config.width.value : useConfigStore().d3Config.camera.near;
        const vertices = [
            // 左下角
            point.x, point.y+ width/Math.sqrt(3), point.z + 0.1,
            // 右下角
            point.x- width/2, point.y-width/Math.sqrt(3), point.z + 0.1,
            // 右上角
            point.x+width/2, point.y-width/Math.sqrt(3), point.z + 0.1
        ];
        mesh.geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
    }
}
  1. LineMeshItem.ts
javascript 复制代码
import { COMMOND_TYPE_2D_MESH } from "@/common/Constant";
import { Base2dMeshItem } from "../Base2dMeshItem";
import * as THREE from "three"
import { useConfigStore } from "@/stores/config";
import { ToolBarMeshColorItemConfigItem, ToolBarMeshMaterialItemConfigItem, ToolBarMeshSizeItemConfigItem} from "@/model/ToolItem/ToolBarMeshItem";

/**
 * 点的类型
 */
export class LineMeshItem extends Base2dMeshItem{
    constructor(name:string,icon:string,key:string,fkey:string){
        super(name,icon,key,fkey);

        this.material = this._material;

        this.mesh = this._mesh

        this.mouseMove = this._mouseMove;
      
        this.config = {
           currentMaterial: new ToolBarMeshMaterialItemConfigItem('select','材质',['currentMaterial', 'value'],THREE.LineBasicMaterial,true,true,undefined,undefined,undefined,[{
                value: THREE.LineBasicMaterial,
                label: '实线'
            }, {
                value: THREE.LineDashedMaterial,
                label: '虚线'
            }]),
            size:new ToolBarMeshSizeItemConfigItem('slider','大小',['size', 'value'],useConfigStore()?.d3Config?.camera?.near || 0.001,true,true,0,useConfigStore()?.d3Config?.maxSize||8,useConfigStore()?.d3Config?.camera?.near || 0.001),
            color:new ToolBarMeshColorItemConfigItem('color','颜色',['color', 'value'],useConfigStore()?.d3Config?.mesh?.fill?.color || new THREE.Color('#FFFfff'),true,true),
        }
    }

    private _material (){
        let that = this as Base2dMeshItem;
        if(!that.config){
            return null;
        }

        let color = (that.config && that.config.color) ? that.config.color.value : useConfigStore().d3Config.mesh.line.color;
        let lineWidth = (that.config && that.config.size) ? that.config.size.value : useConfigStore().d3Config.mesh.line.width;
        if (that.config && that.config.currentMaterial && that.config.currentMaterial.value) {
            return new that.config.currentMaterial.value({
                color: color,
                lineWidth: lineWidth
            });
        } else {
            return new THREE.LineBasicMaterial({
                color: color,
                lineWidth: lineWidth
            });
        }
    }

    protected _mesh(point:THREE.Vector3){
        const geometry = this.geometry?this.geometry():this._geometry();
        geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [point.x,point.y,point.z+0.1], 3 ) );
        const material = this.material?this.material():new THREE.MeshBasicMaterial();
        return new THREE.Line(geometry, material)
    }

    protected _mouseMove(point: THREE.Vector3, mesh: THREE.Mesh,event:MouseEvent){
        let positions = [...mesh.geometry.getAttribute('position').array];

        if (positions.length < 3) {
            positions.push(point.x, point.y, point.z);
        } else {
            positions[3] = point.x;
            positions[4] = point.y;
            positions[5] = point.z;
        }

        mesh.geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
    }
}
  1. LineSegmentMeshItem.ts
javascript 复制代码
import { COMMOND_TYPE_2D_MESH } from "@/common/Constant";
import { Base2dMeshItem } from "../Base2dMeshItem";
import * as THREE from "three"
import { useConfigStore } from "@/stores/config";
import { ToolBarMeshColorItemConfigItem, ToolBarMeshMaterialItemConfigItem, ToolBarMeshSizeItemConfigItem} from "@/model/ToolItem/ToolBarMeshItem";

/**
 * 点的类型
 */
export class LineSegmentMeshItem extends Base2dMeshItem{
    constructor(name:string,icon:string,key:string,fkey:string){
        super(name,icon,key,fkey);

        this.material = this._material;

        this.mesh = this._mesh

        this.mouseMove = this._mouseMove;
      
        this.config = {
           currentMaterial: new ToolBarMeshMaterialItemConfigItem('select','材质',['currentMaterial', 'value'],THREE.LineDashedMaterial,false,true,undefined,undefined,undefined,[]),
            size:new ToolBarMeshSizeItemConfigItem('slider','大小',['size', 'value'],useConfigStore()?.d3Config?.camera?.near || 0.001,true,true,0,useConfigStore()?.d3Config?.maxSize||8,useConfigStore()?.d3Config?.camera?.near || 0.001),
            color:new ToolBarMeshColorItemConfigItem('color','颜色',['color', 'value'],useConfigStore()?.d3Config?.mesh?.fill?.color || new THREE.Color('#FFFfff'),true,true),
        }
    }

    private _material (){
        let that = this as Base2dMeshItem;
        if(!that.config){
            return null;
        }

        let color = (that.config && that.config.color) ? that.config.color.value : useConfigStore().d3Config.mesh.line.color;
        let lineWidth = (that.config && that.config.size) ? that.config.size.value : useConfigStore().d3Config.mesh.line.width;
        if (that.config && that.config.currentMaterial && that.config.currentMaterial.value) {
            return new that.config.currentMaterial.value({
                color: color,
                lineWidth: lineWidth, dashSize: 3, gapSize: 1,
                linecap: 'round', //ignored by WebGLRenderer
	            linejoin:  'round' //ignored by WebGLRenderer
            });
        } else {
            return new THREE.LineDashedMaterial({
                color: color,
                lineWidth: lineWidth, dashSize: 3, gapSize: 1,
                linecap: 'round', //ignored by WebGLRenderer
	            linejoin:  'round' //ignored by WebGLRenderer
            });
        }
    }

    protected _mesh(point:THREE.Vector3){
        const geometry = this.geometry?this.geometry():this._geometry();
        geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [point.x,point.y,point.z+0.1], 3 ) );
        const material = this.material?this.material():new THREE.MeshBasicMaterial();
        return new THREE.LineSegments(geometry, material)
    }

    protected _mouseMove(point: THREE.Vector3, mesh: THREE.Mesh,event:MouseEvent){
        let positions = [...mesh.geometry.getAttribute('position').array];

        if (positions.length < 3) {
            positions.push(point.x, point.y, point.z);
        } else {
            positions[3] = point.x;
            positions[4] = point.y;
            positions[5] = point.z;
        }
        // positions.push(point.x, point.y, point.z);
        mesh.geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
    }
}
  1. PointMeshItem.ts
javascript 复制代码
import { Base2dMeshItem } from "../Base2dMeshItem";
import * as THREE from "three"
import { ToolBarMeshColorItemConfigItem, ToolBarMeshMaterialItemConfigItem, ToolBarMeshSizeItemConfigItem, ToolBarMeshTextureItemConfigItem, type ToolBarMeshItem } from "@/model/ToolItem/ToolBarMeshItem";
import { useConfigStore } from "@/stores/config";

/**
 * 点的类型
 */
export class PointMeshItem extends Base2dMeshItem{
    constructor(name:string,icon:string,key:string,fkey:string){
        super(name,icon,key,fkey);

        this.material = this._material;

        this.mesh = this._mesh;

        this.mouseMove = this._mouseMove;
        
        this.config = {
            currentMaterial:new ToolBarMeshMaterialItemConfigItem('select','材质',['currentMaterial', 'value'],THREE.PointsMaterial,false,false,undefined,undefined,undefined,[{ value: '',label: '纯色'}]),
            texture:new ToolBarMeshTextureItemConfigItem('select','纹理',['currentMaterial', 'value'],'',true,true,undefined,undefined,undefined,[{
                value: '',
                label: '颜色'
            }, {
                value: THREE.VideoTexture,
                label: '视频'
            }, {
                value: THREE.CanvasTexture,
                label: 'Canvas'
            }, {
                value: THREE.DataTexture,
                label: '数据'
            }, {
                value: THREE.Texture,
                label: '自定义'
            }]),
            size:new ToolBarMeshSizeItemConfigItem('slider','大小',['size', 'value'],useConfigStore()?.d3Config?.camera?.near || 0.001,true,true,0,useConfigStore()?.d3Config?.maxSize||8,useConfigStore()?.d3Config?.camera?.near || 0.001),
            color:new ToolBarMeshColorItemConfigItem('color','颜色',['color', 'value'],useConfigStore()?.d3Config?.mesh?.fill?.color || new THREE.Color('#FFFfff'),true,true),
        }
    }

    private _material (){
        let that = this as ToolBarMeshItem;
        let color = (that.config && that.config.color) ? that.config.color.value : new THREE.Color('#ffffff');
        let size = (that.config && that.config.size) ? that.config.size.value : useConfigStore().d3Config.camera.near;
        if (that.config && that.config.currentMaterial) {
            return new that.config.currentMaterial.value({ color: color, size: size });
        } else {
            return new THREE.PointsMaterial({ color: color, size: size });
        }
    }

    protected _mesh(point:THREE.Vector3){
        const geometry = this.geometry?this.geometry():this._geometry();
        geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [point.x,point.y,point.z+0.1], 3 ) );
        const material = this.material?this.material():new THREE.PointsMaterial();
        return new THREE.Points(geometry, material)
    }
}
  1. PolygonMeshItem.ts
javascript 复制代码
import { ToolBarMeshColorItemConfigItem, ToolBarMeshMaterialItemConfigItem, ToolBarMeshSizeItemConfigItem, ToolBarMeshTextureItemConfigItem, type EndDrawFunction } from "@/model/ToolItem/ToolBarMeshItem";
import { Base2dMeshItem } from "../Base2dMeshItem";
import * as THREE from "three"
import { useConfigStore } from "@/stores/config";

/**
 * 多边形
 */
export class PolygonMeshItem extends Base2dMeshItem{

    constructor(name:string,icon:string,key:string,fkey:string){
        super(name,icon,key,fkey);

        this.material = this._material;

        this.mesh = this._mesh;

        this.mouseMove = this._mouseMove;
        
        this.config = {
            currentMaterial:new ToolBarMeshMaterialItemConfigItem('select','材质',['currentMaterial', 'value'],THREE.LineBasicMaterial,false,false,undefined,undefined,undefined,[{ value: '',label: '纯色'}]),
            texture: new ToolBarMeshTextureItemConfigItem('select','纹理',['currentMaterial', 'value'],'',true,true,undefined,undefined,undefined,[{
                value: '',
                label: '颜色'
            }, {
                value: THREE.VideoTexture,
                label: '视频'
            }, {
                value: THREE.CanvasTexture,
                label: 'Canvas'
            }, {
                value: THREE.DataTexture,
                label: '数据'
            }, {
                value: THREE.Texture,
                label: '自定义'
            }]),
            size:new ToolBarMeshSizeItemConfigItem('slider','大小',['size', 'value'],useConfigStore()?.d3Config?.camera?.near || 0.001,true,true,0,useConfigStore()?.d3Config?.maxSize||8,useConfigStore()?.d3Config?.camera?.near || 0.001),
            color:new ToolBarMeshColorItemConfigItem('color','颜色',['color', 'value'],useConfigStore()?.d3Config?.mesh?.fill?.color || new THREE.Color('#FFFfff'),true,true),
        }
    }

    private _material (){
        let that = this as Base2dMeshItem;
        if(!that.config){
            return null;
        }
        let color = (that.config && that.config.color) ? that.config.color.value : useConfigStore().d3Config.mesh.line.color;
        let lineWidth = (that.config && that.config.size) ? that.config.size.value : useConfigStore().d3Config.mesh.line.width;
        if (that.config && that.config.currentMaterial && that.config.currentMaterial.value) {
            return new that.config.currentMaterial.value({
                color: color,
                lineWidth: lineWidth
            });
        } else {
            return new THREE.LineBasicMaterial({
                color: color,
                lineWidth: lineWidth
            });
        }
    }

    protected _mesh(point:THREE.Vector3){
        const geometry = this.geometry?this.geometry():this._geometry();
        geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [point.x,point.y,point.z+0.1], 3 ) );
        const material = this.material?this.material():new THREE.LineBasicMaterial();
        return new THREE.LineLoop(geometry, material)
    }

    protected _mouseMove(point: THREE.Vector3, mesh: THREE.Mesh,event:MouseEvent){
        let positions = [...mesh.geometry.getAttribute('position').array];

        if(event.type == 'mousemove'){
            positions[positions.length-3] = point.x;
            positions[positions.length-2] = point.y;
            positions[positions.length-1] = point.z+0.1;
        }else{
            positions.push(point.x, point.y, point.z+0.1);
        }

        mesh.geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
    }
}
  1. PolylineMeshItem.ts
javascript 复制代码
import { ToolBarMeshColorItemConfigItem, ToolBarMeshMaterialItemConfigItem, ToolBarMeshSizeItemConfigItem, ToolBarMeshTextureItemConfigItem } from "@/model/ToolItem/ToolBarMeshItem";
import { Base2dMeshItem } from "../Base2dMeshItem";
import * as THREE from "three"
import { useConfigStore } from "@/stores/config";

/**
 * 折线
 */
export class PolyLineMeshItem extends Base2dMeshItem{

    constructor(name:string,icon:string,key:string,fkey:string){
        super(name,icon,key,fkey);

        this.material = this._material;

        this.mesh = this._mesh;

        this.mouseMove = this._mouseMove;
        
        this.config = {
            currentMaterial:new ToolBarMeshMaterialItemConfigItem('select','材质',['currentMaterial', 'value'],THREE.PointsMaterial,false,false,undefined,undefined,undefined,[{ value: '',label: '纯色'}]),
           texture: new ToolBarMeshTextureItemConfigItem('select','纹理',['currentMaterial', 'value'],'',true,true,undefined,undefined,undefined,[{
                value: '',
                label: '颜色'
            }, {
                value: THREE.VideoTexture,
                label: '视频'
            }, {
                value: THREE.CanvasTexture,
                label: 'Canvas'
            }, {
                value: THREE.DataTexture,
                label: '数据'
            }, {
                value: THREE.Texture,
                label: '自定义'
            }]),
            size:new ToolBarMeshSizeItemConfigItem('slider','大小',['size', 'value'],useConfigStore()?.d3Config?.camera?.near || 0.001,true,true,0,useConfigStore()?.d3Config?.maxSize||8,useConfigStore()?.d3Config?.camera?.near || 0.001),
            color:new ToolBarMeshColorItemConfigItem('color','颜色',['color', 'value'],useConfigStore()?.d3Config?.mesh?.fill?.color || new THREE.Color('#FFFfff'),true,true),
        }
    }

    private _material (){
        let that = this as Base2dMeshItem;
        if(!that.config){
            return null;
        }
        let color = (that.config && that.config.color) ? that.config.color.value : useConfigStore().d3Config.mesh.line.color;
        let lineWidth = (that.config && that.config.size) ? that.config.size.value : useConfigStore().d3Config.mesh.line.width;
        if (that.config && that.config.currentMaterial && that.config.currentMaterial.value) {
            return new that.config.currentMaterial.value({
                color: color,
                lineWidth: lineWidth
            });
        } else {
            return new THREE.LineBasicMaterial({
                color: color,
                lineWidth: lineWidth
            });
        }
    }

    protected _mesh(point:THREE.Vector3){
        const geometry = this.geometry?this.geometry():this._geometry();
        geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [point.x,point.y,point.z+0.1], 3 ) );
        const material = this.material?this.material():new THREE.MeshBasicMaterial();
        return new THREE.Line(geometry, material)
    }

    protected _mouseMove(point: THREE.Vector3, mesh: THREE.Mesh,event:MouseEvent){
        let positions = [...mesh.geometry.getAttribute('position').array];

        if(event.type == 'mousemove'){
            positions[positions.length-3] = point.x;
            positions[positions.length-2] = point.y;
            positions[positions.length-1] = point.z+0.1;
        }else{
            positions.push(point.x, point.y, point.z+0.1);
        }

        mesh.geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
    }
}
  1. RightTriangleMeshItem.ts
javascript 复制代码
import { ToolBarMeshColorItemConfigItem, ToolBarMeshItemConfigItem, ToolBarMeshMaterialItemConfigItem, ToolBarMeshSizeItemConfigItem, ToolBarMeshTextureItemConfigItem } from "@/model/ToolItem/ToolBarMeshItem";
import { Base2dMeshItem } from "../Base2dMeshItem";
import * as THREE from "three"
import { useConfigStore } from "@/stores/config";
import type { OptionData } from "@/model/OptionData";

export class  ToolBarMeshWidthItemConfigItem  extends ToolBarMeshItemConfigItem<number>{
    constructor(
        type: string,
        name: string,
        modelPath: string[],
        value: number,
        auto: boolean= false,
        form: boolean = false,
        min?: number,
        max?: number,
        step?: number,
        options?: OptionData[]
    ){
        super(type,
        name,
        modelPath,
        value,
        auto,
        form,
        min,
        max,
        step,
        options);
    }
    updateConfig(mesh:THREE.Mesh, value:number) {
        let width = value;
        let points = mesh.geometry.getAttribute('position');
        let point = new THREE.Vector3(points[0],points[1],points[2]);
        const vertices = [
            // 左下角
            point.x, point.y, point.z + 0.1,
            // 右下角
            point.x + width, point.y, point.z + 0.1,
            // 右上角
            point.x, point.y+width, point.z + 0.1
        ];
        mesh.geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
    }
}

/**
 * 三角形
 */
export class RightTriangleMeshItem extends Base2dMeshItem{

    constructor(name:string,icon:string,key:string,fkey:string){
        super(name,icon,key,fkey);

        this.material = this._material;

        this.mesh = this._mesh;

        this.mouseMove = this._mouseMove;
        
        this.config = {
            currentMaterial:new ToolBarMeshMaterialItemConfigItem('select','材质',['currentMaterial', 'value'],THREE.MeshBasicMaterial,false,false,undefined,undefined,undefined,[{ value: '',label: '纯色'}]),
           texture: new ToolBarMeshTextureItemConfigItem('select','纹理',['currentMaterial', 'value'],'',true,true,undefined,undefined,undefined,[{
                value: '',
                label: '颜色'
            }, {
                value: THREE.VideoTexture,
                label: '视频'
            }, {
                value: THREE.CanvasTexture,
                label: 'Canvas'
            }, {
                value: THREE.DataTexture,
                label: '数据'
            }, {
                value: THREE.Texture,
                label: '自定义'
            }]),
            size:new ToolBarMeshSizeItemConfigItem('slider','线条大小',['size', 'value'],useConfigStore()?.d3Config?.camera?.near || 0.001,true,true,0,useConfigStore()?.d3Config?.maxSize||8,useConfigStore()?.d3Config?.camera?.near || 0.001),
            width: new ToolBarMeshWidthItemConfigItem('slider', '地边长', ['width', 'value'], 1, true, true, 0, useConfigStore()?.d3Config?.maxSize||8, useConfigStore()?.d3Config?.camera?.near || 0.001),
            color:new ToolBarMeshColorItemConfigItem('color','颜色',['color', 'value'],useConfigStore()?.d3Config?.mesh?.fill?.color || new THREE.Color('#FFFfff'),true,true),
        }
    }

    private _material (){
        let that = this as Base2dMeshItem;
        if(!that.config){
            return null;
        }
        let color = (that.config && that.config.color) ? that.config.color.value : useConfigStore().d3Config.mesh.line.color;
        let lineWidth = (that.config && that.config.size) ? that.config.size.value : useConfigStore().d3Config.mesh.line.width;
        if (that.config && that.config.currentMaterial && that.config.currentMaterial.value) {
            return new that.config.currentMaterial.value({
                color: color,
                lineWidth: lineWidth
            });
        } else {
            return new THREE.MeshBasicMaterial({
                color: color,
                lineWidth: lineWidth
            });
        }
    }

    protected _mesh(point:THREE.Vector3){
        let that = this as Base2dMeshItem;

        const geometry = this.geometry?this.geometry():this._geometry();
        
        let width = (that.config && that.config.width) ? that.config.width.value : useConfigStore().d3Config.camera.near;

        const vertices = [
            // 左下角
            point.x, point.y, point.z + 0.1,
            // 右下角
            point.x + width, point.y, point.z + 0.1,
            // 右上角
            point.x, point.y+width, point.z + 0.1
        ];
        geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));

        const material = this.material?this.material():new THREE.MeshBasicMaterial();
        return new THREE.Mesh(geometry, material)
    }

    protected _mouseMove(point: THREE.Vector3, mesh: THREE.Mesh,event:MouseEvent){
        if(!mesh){
            return;
        }
        let that = this as Base2dMeshItem;
        let width = (that.config && that.config.width) ? that.config.width.value : useConfigStore().d3Config.camera.near;
        const vertices = [
            // 左下角
            point.x, point.y, point.z + 0.1,
            // 右下角
            point.x + width, point.y, point.z + 0.1,
            // 右上角
            point.x, point.y+width, point.z + 0.1
        ];
        mesh.geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
    }
}
  1. RingMeshItem.ts
javascript 复制代码
import { ToolBarMeshColorItemConfigItem, ToolBarMeshItemConfigItem, ToolBarMeshMaterialItemConfigItem, ToolBarMeshRadiusItemConfigItem, ToolBarMeshSizeItemConfigItem, ToolBarMeshTextureItemConfigItem } from "@/model/ToolItem/ToolBarMeshItem";
import { Base2dMeshItem } from "../Base2dMeshItem";
import * as THREE from "three"
import { useConfigStore } from "@/stores/config";
import type { OptionData } from "@/model/OptionData";

class ToolBarMeshRingRadiusItemConfigItem  extends ToolBarMeshItemConfigItem<number>{
    constructor(
        type: string,
        name: string,
        modelPath: string[],
        value: number,
        auto: boolean= false,
        form: boolean = false,
        min?: number,
        max?: number,
        step?: number,
        options?: OptionData[]
    ){
        super(type,
        name,
        modelPath,
        value,
        auto,
        form,
        min,
        max,
        step,
        options);
    }
    updateConfig(mesh:THREE.Mesh, value:number) {
        mesh.geometry = new THREE.RingGeometry(value,mesh.geometry.parameters.outerRadius,132);
    }
}
class ToolBarMeshRingMaxRadiusItemConfigItem  extends ToolBarMeshItemConfigItem<number>{
    constructor(
        type: string,
        name: string,
        modelPath: string[],
        value: number,
        auto: boolean= false,
        form: boolean = false,
        min?: number,
        max?: number,
        step?: number,
        options?: OptionData[]
    ){
        super(type,
        name,
        modelPath,
        value,
        auto,
        form,
        min,
        max,
        step,
        options);
    }
    updateConfig(mesh:THREE.Mesh, value:number) {
        mesh.geometry = new THREE.RingGeometry(mesh.geometry.parameters.innerRadius,value,132);
    }
}
/**
 * 圆环
 */
export class RingMeshItem extends Base2dMeshItem {

    constructor(name: string, icon: string, key: string, fkey: string) {
        super(name, icon, key, fkey);

        this.geometry = this._geometry;

        this.material = this._material;

        this.mouseMove = this._mouseMove;

        this.config = {
            currentMaterial: new ToolBarMeshMaterialItemConfigItem('select', '材质', ['currentMaterial', 'value'], THREE.MeshBasicMaterial, false, false, undefined, undefined, undefined, [{ value: '', label: '纯色' }]),
            texture: new ToolBarMeshTextureItemConfigItem('select', '纹理', ['currentMaterial', 'value'], '', true, true, undefined, undefined, undefined, [{
                value: '',
                label: '颜色'
            }, {
                value: THREE.VideoTexture,
                label: '视频'
            }, {
                value: THREE.CanvasTexture,
                label: 'Canvas'
            }, {
                value: THREE.DataTexture,
                label: '数据'
            }, {
                value: THREE.Texture,
                label: '自定义'
            }]),
            size1: new ToolBarMeshRingMaxRadiusItemConfigItem('slider', '外部半径', ['size1', 'value'], 0.2, true, true, 0, useConfigStore()?.d3Config?.maxSize||8, useConfigStore()?.d3Config?.camera?.near || 0.001),
            size: new ToolBarMeshRingRadiusItemConfigItem('slider', '内部半径', ['size', 'value'], 0.1, true, true, 0, useConfigStore()?.d3Config?.maxSize||8, useConfigStore()?.d3Config?.camera?.near || 0.001),
            color: new ToolBarMeshColorItemConfigItem('color', '颜色', ['color', 'value'], useConfigStore()?.d3Config?.mesh?.fill?.color || new THREE.Color('#FFFfff'), true, true),
        }
    }

    protected _geometry() {
        let that = this as Base2dMeshItem;
        let size = (that.config && that.config.size) ? that.config.size.value : useConfigStore().d3Config.camera.near;
        let size1 = (that.config && that.config.size1) ? that.config.size1.value : useConfigStore().d3Config.camera.near;
        return new THREE.RingGeometry(size, size1,132);
    }

    private _material() {
        let that = this as Base2dMeshItem;
        if (!that.config) {
            return null;
        }
        let color = (that.config && that.config.color) ? that.config.color.value : useConfigStore().d3Config.mesh.line.color;
        let lineWidth = (that.config && that.config.size) ? that.config.size.value : useConfigStore().d3Config.mesh.line.width;
        if (that.config && that.config.currentMaterial && that.config.currentMaterial.value) {
            return new that.config.currentMaterial.value({
                color: color,
                lineWidth: lineWidth
            });
        } else {
            return new THREE.MeshBasicMaterial({
                color: color,
                lineWidth: lineWidth
            });
        }
    }
    protected _mouseMove(point: THREE.Vector3, mesh: THREE.Mesh,event:MouseEvent) {
        if(!mesh){
            return;
        }
        point.z += 0.1;
        mesh.position.copy(point);
    }
}
  1. SectorMeshItem.ts
javascript 复制代码
import { ToolBarMeshColorItemConfigItem, ToolBarMeshItemConfigItem, ToolBarMeshMaterialItemConfigItem, ToolBarMeshRadiusItemConfigItem, ToolBarMeshSizeItemConfigItem, ToolBarMeshTextureItemConfigItem } from "@/model/ToolItem/ToolBarMeshItem";
import { Base2dMeshItem } from "../Base2dMeshItem";
import * as THREE from "three"
import { useConfigStore } from "@/stores/config";
import type { OptionData } from "@/model/OptionData";

class ToolBarMeshSectorRaiusItemConfigItem  extends ToolBarMeshItemConfigItem<number>{
    constructor(
        type: string,
        name: string,
        modelPath: string[],
        value: number,
        auto: boolean= false,
        form: boolean = false,
        min?: number,
        max?: number,
        step?: number,
        options?: OptionData[]
    ){
        super(type,
        name,
        modelPath,
        value,
        auto,
        form,
        min,
        max,
        step,
        options);
    }
    updateConfig(mesh:THREE.Mesh, value:number) {
        mesh.geometry = new THREE.CircleGeometry(value,132,mesh.geometry.parameters.thetaStart,mesh.geometry.parameters.thetaLength);
    }
}

class ToolBarMeshThetaStartItemConfigItem  extends ToolBarMeshItemConfigItem<number>{
    constructor(
        type: string,
        name: string,
        modelPath: string[],
        value: number,
        auto: boolean= false,
        form: boolean = false,
        min?: number,
        max?: number,
        step?: number,
        options?: OptionData[]
    ){
        super(type,
        name,
        modelPath,
        value,
        auto,
        form,
        min,
        max,
        step,
        options);
    }
    updateConfig(mesh:THREE.Mesh, value:number) {
        mesh.geometry = new THREE.CircleGeometry(mesh.geometry.parameters.radius,132,value,mesh.geometry.parameters.thetaLength);
    }
}

class ToolBarMeshThetaLengthItemConfigItem  extends ToolBarMeshItemConfigItem<number>{
    constructor(
        type: string,
        name: string,
        modelPath: string[],
        value: number,
        auto: boolean= false,
        form: boolean = false,
        min?: number,
        max?: number,
        step?: number,
        options?: OptionData[]
    ){
        super(type,
        name,
        modelPath,
        value,
        auto,
        form,
        min,
        max,
        step,
        options);
    }
    updateConfig(mesh:THREE.Mesh, value:number) {
        mesh.geometry = new THREE.CircleGeometry(mesh.geometry.parameters.radius,132,mesh.geometry.parameters.thetaStart,value);
    }
}
/**
 * 扇形
 */
export class SectorMeshItem extends Base2dMeshItem {

    constructor(name: string, icon: string, key: string, fkey: string) {
        super(name, icon, key, fkey);

        this.geometry = this._geometry;

        this.material = this._material;

        this.mouseMove = this._mouseMove;

        this.config = {
            currentMaterial: new ToolBarMeshMaterialItemConfigItem('select', '材质', ['currentMaterial', 'value'], THREE.MeshBasicMaterial, false, false, undefined, undefined, undefined, [{ value: '', label: '纯色' }]),
            texture: new ToolBarMeshTextureItemConfigItem('select', '纹理', ['currentMaterial', 'value'], '', true, true, undefined, undefined, undefined, [{
                value: '',
                label: '颜色'
            }, {
                value: THREE.VideoTexture,
                label: '视频'
            }, {
                value: THREE.CanvasTexture,
                label: 'Canvas'
            }, {
                value: THREE.DataTexture,
                label: '数据'
            }, {
                value: THREE.Texture,
                label: '自定义'
            }]),
            size: new ToolBarMeshSectorRaiusItemConfigItem('slider', '大小', ['size', 'value'], 0.1, true, true, 0, useConfigStore()?.d3Config?.maxSize||8, useConfigStore()?.d3Config?.camera?.near || 0.001),

            thetaStart: new ToolBarMeshThetaStartItemConfigItem('slider', '起始角度', ['thetaStart', 'value'], 0, true, true, 0, 2*Math.PI, 2*Math.PI/10),
            thetaLength: new ToolBarMeshThetaLengthItemConfigItem('slider', '中心角', ['thetaLength', 'value'], Math.PI, true, true, 0, 2*Math.PI, 2*Math.PI/10),

            color: new ToolBarMeshColorItemConfigItem('color', '颜色', ['color', 'value'], useConfigStore()?.d3Config?.mesh?.fill?.color || new THREE.Color('#FFFfff'), true, true),
        }
    }

    protected _geometry() {
        let that = this as Base2dMeshItem;
        let size = (that.config && that.config.size) ? that.config.size.value : useConfigStore().d3Config.camera.near;
        let thetaStart = (that.config && that.config.thetaStart) ? that.config.thetaStart.value : 0;
        let thetaLength = (that.config && that.config.thetaLength) ? that.config.thetaLength.value : Math.PI;
        return new THREE.CircleGeometry(size, 132,thetaStart,thetaLength);
    }

    private _material() {
        let that = this as Base2dMeshItem;
        if (!that.config) {
            return null;
        }
        let color = (that.config && that.config.color) ? that.config.color.value : useConfigStore().d3Config.mesh.line.color;
        let lineWidth = (that.config && that.config.size) ? that.config.size.value : useConfigStore().d3Config.mesh.line.width;
        if (that.config && that.config.currentMaterial && that.config.currentMaterial.value) {
            return new that.config.currentMaterial.value({
                color: color,
                lineWidth: lineWidth
            });
        } else {
            return new THREE.MeshBasicMaterial({
                color: color,
                lineWidth: lineWidth
            });
        }
    }
    protected _mouseMove(point: THREE.Vector3, mesh: THREE.Mesh,event:MouseEvent) {
        if(!mesh){
            return;
        }
        point.z += 0.1;
        mesh.position.copy(point);
    }
}
  1. SquareMeshItem.ts
javascript 复制代码
import { ToolBarMeshColorItemConfigItem, ToolBarMeshMaterialItemConfigItem, ToolBarMeshRadiusItemConfigItem, ToolBarMeshSizeItemConfigItem, ToolBarMeshTextureItemConfigItem } from "@/model/ToolItem/ToolBarMeshItem";
import { Base2dMeshItem } from "../Base2dMeshItem";
import * as THREE from "three"
import { useConfigStore } from "@/stores/config";
import type { OptionData } from "@/model/OptionData";

export class  ToolBarMeshSquareItemConfigItem  extends ToolBarMeshSizeItemConfigItem{
    constructor(
        type: string,
        name: string,
        modelPath: string[],
        value: number,
        auto: boolean= false,
        form: boolean = false,
        min?: number,
        max?: number,
        step?: number,
        options?: OptionData[]
    ){
        super(type,
        name,
        modelPath,
        value,
        auto,
        form,
        min,
        max,
        step,
        options);
    }
    updateConfig(mesh:THREE.Mesh, value:number) {
        mesh.geometry = new THREE.PlaneGeometry(value,value,32);
    }
}

/**
 * 正方形
 */
export class SquareMeshItem extends Base2dMeshItem {

    constructor(name: string, icon: string, key: string, fkey: string) {
        super(name, icon, key, fkey);

        this.geometry = this._geometry;

        this.material = this._material;

        this.mouseMove = this._mouseMove;

        this.config = {
            currentMaterial: new ToolBarMeshMaterialItemConfigItem('select', '材质', ['currentMaterial', 'value'], THREE.MeshBasicMaterial, false, false, undefined, undefined, undefined, [{ value: '', label: '纯色' }]),
            texture: new ToolBarMeshTextureItemConfigItem('select', '纹理', ['currentMaterial', 'value'], '', true, true, undefined, undefined, undefined, [{
                value: '',
                label: '颜色'
            }, {
                value: THREE.VideoTexture,
                label: '视频'
            }, {
                value: THREE.CanvasTexture,
                label: 'Canvas'
            }, {
                value: THREE.DataTexture,
                label: '数据'
            }, {
                value: THREE.Texture,
                label: '自定义'
            }]),
            size: new ToolBarMeshSquareItemConfigItem('slider', '大小', ['size', 'value'], 1, true, true, 0, useConfigStore()?.d3Config?.maxSize||8, useConfigStore()?.d3Config?.camera?.near || 0.001),
            color: new ToolBarMeshColorItemConfigItem('color', '颜色', ['color', 'value'], useConfigStore()?.d3Config?.mesh?.fill?.color || new THREE.Color('#FFFfff'), true, true),
        }
    }

    protected _geometry() {
        let that = this as Base2dMeshItem;
        let size = (that.config && that.config.size) ? that.config.size.value : useConfigStore().d3Config.camera.near;
        return new THREE.PlaneGeometry(size,size, 132);
    }

    private _material() {
        let that = this as Base2dMeshItem;
        if (!that.config) {
            return null;
        }
        let color = (that.config && that.config.color) ? that.config.color.value : useConfigStore().d3Config.mesh.line.color;
        let lineWidth = (that.config && that.config.size) ? that.config.size.value : useConfigStore().d3Config.mesh.line.width;
        if (that.config && that.config.currentMaterial && that.config.currentMaterial.value) {
            return new that.config.currentMaterial.value({
                color: color,
                lineWidth: lineWidth
            });
        } else {
            return new THREE.MeshBasicMaterial({
                color: color,
                lineWidth: lineWidth
            });
        }
    }
    protected _mouseMove(point: THREE.Vector3, mesh: THREE.Mesh,event:MouseEvent) {
        if(!mesh){
            return;
        }
        point.z += 0.1;
        mesh.position.copy(point);
    }
}
  1. TriangleMeshItem.ts
javascript 复制代码
import { ToolBarMeshColorItemConfigItem, ToolBarMeshItemConfigItem, ToolBarMeshMaterialItemConfigItem, ToolBarMeshSizeItemConfigItem, ToolBarMeshTextureItemConfigItem } from "@/model/ToolItem/ToolBarMeshItem";
import { Base2dMeshItem } from "../Base2dMeshItem";
import * as THREE from "three"
import { useConfigStore } from "@/stores/config";
import type { OptionData } from "@/model/OptionData";

export class  ToolBarMeshWidthItemConfigItem  extends ToolBarMeshItemConfigItem<number>{
    constructor(
        type: string,
        name: string,
        modelPath: string[],
        value: number,
        auto: boolean= false,
        form: boolean = false,
        min?: number,
        max?: number,
        step?: number,
        options?: OptionData[]
    ){
        super(type,
        name,
        modelPath,
        value,
        auto,
        form,
        min,
        max,
        step,
        options);
    }
    updateConfig(mesh:THREE.Mesh, value:number) {
        let points = mesh.geometry.getAttribute('position');
        let point = new THREE.Vector3(points[0],points[1],points[2]);

        let width = value;
        let that = mesh.item;
        let height = (that.config && that.config.height) ? that.config.height.value : useConfigStore().d3Config.camera.near;
        const tiltAngle = (that.config && that.config.thetaStart) ? that.config.thetaStart.value : 30 ;

        const c = width;
        const b = height;
        const vertices = [
            // 左下角
            point.x , point.y, point.z + 0.1,
            // 右下角
            point.x + c, point.y, point.z + 0.1,
            // 右上角
            point.x+b * Math.cos(tiltAngle), point.y+b*Math.sign(tiltAngle), point.z + 0.1
        ];
        mesh.geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
    }
}

export class  ToolBarMeshHeightItemConfigItem  extends ToolBarMeshItemConfigItem<number>{
    constructor(
        type: string,
        name: string,
        modelPath: string[],
        value: number,
        auto: boolean= false,
        form: boolean = false,
        min?: number,
        max?: number,
        step?: number,
        options?: OptionData[]
    ){
        super(type,
        name,
        modelPath,
        value,
        auto,
        form,
        min,
        max,
        step,
        options);
    }
    updateConfig(mesh:THREE.Mesh, value:number) {
        let points = mesh.geometry.getAttribute('position');
        let point = new THREE.Vector3(points[0],points[1],points[2]);
        let that = mesh.item;

        let width = (that.config && that.config.width) ? that.config.width.value : useConfigStore().d3Config.camera.near;
        let height = value;
        const tiltAngle = (that.config && that.config.thetaStart) ? that.config.thetaStart.value : 30 ;

        const c = width;
        const b = height;
        const vertices = [
            // 左下角
            point.x , point.y, point.z + 0.1,
            // 右下角
            point.x + c, point.y, point.z + 0.1,
            // 右上角
            point.x+b * Math.cos(tiltAngle), point.y+b*Math.sign(tiltAngle), point.z + 0.1
        ];
        mesh.geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
    }
}

export class  ToolBarMeshThetaStartItemConfigItem  extends ToolBarMeshItemConfigItem<number>{
    constructor(
        type: string,
        name: string,
        modelPath: string[],
        value: number,
        auto: boolean= false,
        form: boolean = false,
        min?: number,
        max?: number,
        step?: number,
        options?: OptionData[]
    ){
        super(type,
        name,
        modelPath,
        value,
        auto,
        form,
        min,
        max,
        step,
        options);
    }
    updateConfig(mesh:THREE.Mesh, value:number) {
        let points = mesh.geometry.getAttribute('position');
        let point = new THREE.Vector3(points[0],points[1],points[2]);
        let that = mesh.item;

        let width = (that.config && that.config.width) ? that.config.width.value : useConfigStore().d3Config.camera.near;
        let height = (that.config && that.config.height) ? that.config.height.value : useConfigStore().d3Config.camera.near;
        const tiltAngle = value ;

        const c = width;
        const b = height;
        const vertices = [
            // 左下角
            point.x , point.y, point.z + 0.1,
            // 右下角
            point.x + c, point.y, point.z + 0.1,
            // 右上角
            point.x+b * Math.cos(tiltAngle), point.y+b*Math.sign(tiltAngle), point.z + 0.1
        ];
        mesh.geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
    }
}
/**
 * 三角形
 */
export class TriangleMeshItem extends Base2dMeshItem{

    constructor(name:string,icon:string,key:string,fkey:string){
        super(name,icon,key,fkey);

        this.material = this._material;

        this.mesh = this._mesh;

        this.mouseMove = this._mouseMove;
        
        this.config = {
            currentMaterial:new ToolBarMeshMaterialItemConfigItem('select','材质',['currentMaterial', 'value'],THREE.MeshBasicMaterial,false,false,undefined,undefined,undefined,[{ value: '',label: '纯色'}]),
           texture: new ToolBarMeshTextureItemConfigItem('select','纹理',['currentMaterial', 'value'],'',true,true,undefined,undefined,undefined,[{
                value: '',
                label: '颜色'
            }, {
                value: THREE.VideoTexture,
                label: '视频'
            }, {
                value: THREE.CanvasTexture,
                label: 'Canvas'
            }, {
                value: THREE.DataTexture,
                label: '数据'
            }, {
                value: THREE.Texture,
                label: '自定义'
            }]),
            size:new ToolBarMeshSizeItemConfigItem('slider','大小',['size', 'value'],useConfigStore()?.d3Config?.camera?.near || 0.001,true,true,0,useConfigStore()?.d3Config?.maxSize||8,useConfigStore()?.d3Config?.camera?.near || 0.001),
            width: new ToolBarMeshWidthItemConfigItem('slider', '边AB', ['width', 'value'], 1, true, true, 0, useConfigStore()?.d3Config?.maxSize||8, useConfigStore()?.d3Config?.camera?.near || 0.001),
            height: new ToolBarMeshHeightItemConfigItem('slider', '边AC', ['height', 'value'], 2, true, true, 0, useConfigStore()?.d3Config?.maxSize||8, useConfigStore()?.d3Config?.camera?.near || 0.001),
            thetaStart: new ToolBarMeshThetaStartItemConfigItem('slider', '角度ABC', ['thetaStart', 'value'], 90, true, true, 0, 180, useConfigStore()?.d3Config?.camera?.near || 0.001),
            color:new ToolBarMeshColorItemConfigItem('color','颜色',['color', 'value'],useConfigStore()?.d3Config?.mesh?.fill?.color || new THREE.Color('#FFFfff'),true,true),
        }
    }

    private _material (){
        let that = this as Base2dMeshItem;
        if(!that.config){
            return null;
        }
        let color = (that.config && that.config.color) ? that.config.color.value : useConfigStore().d3Config.mesh.line.color;
        let lineWidth = (that.config && that.config.size) ? that.config.size.value : useConfigStore().d3Config.mesh.line.width;
        if (that.config && that.config.currentMaterial && that.config.currentMaterial.value) {
            return new that.config.currentMaterial.value({
                color: color,
                lineWidth: lineWidth
            });
        } else {
            return new THREE.MeshBasicMaterial({
                color: color,
                lineWidth: lineWidth
            });
        }
    }

    protected _mesh(point:THREE.Vector3){
        let that = this as Base2dMeshItem;

        const geometry = this.geometry?this.geometry():this._geometry();
        
        let width = (that.config && that.config.width) ? that.config.width.value : useConfigStore().d3Config.camera.near;
        let height = (that.config && that.config.height) ? that.config.height.value : useConfigStore().d3Config.camera.near;
        const tiltAngle = (that.config && that.config.thetaStart) ? that.config.thetaStart.value : 30 ;

        const c = width;
        const b = height;
        const vertices = [
            // 左下角
            point.x , point.y, point.z + 0.1,
            // 右下角
            point.x + b, point.y, point.z + 0.1,
            // 右上角
            point.x+ c * Math.cos(tiltAngle), point.y + c*Math.sign(tiltAngle), point.z + 0.1
        ];
        geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
        
        const material = this.material?this.material():new THREE.MeshBasicMaterial();
        return new THREE.Mesh(geometry, material)
    }

    protected _mouseMove(point: THREE.Vector3, mesh: THREE.Mesh,event:MouseEvent){
        if(!mesh){
            return;
        }
        // point.z += 0.1;
        // mesh.position.copy(point);

        let that = this as Base2dMeshItem;
        let width = (that.config && that.config.width) ? that.config.width.value : useConfigStore().d3Config.camera.near;
        let height = (that.config && that.config.height) ? that.config.height.value : useConfigStore().d3Config.camera.near;
        const tiltAngle = (that.config && that.config.thetaStart) ? that.config.thetaStart.value : 30 ;
        const c = width;
        const b = height;
        const vertices = [
            // 左下角
            point.x , point.y, point.z + 0.1,
            // 右下角
            point.x + c, point.y, point.z + 0.1,
            // 右上角
            point.x+b * Math.cos(tiltAngle), point.y+b*Math.sign(tiltAngle), point.z + 0.1
        ];
        mesh.geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
    }
}

2.2逻辑控制

  1. D2Control.ts
javascript 复制代码
import * as THREE from "three"
import type D2Mesh from "../mesh/D2Mesh";
import type { ThreeMode } from "../model/ThreeModel";
import { BaseControl } from "./BaseControl";
import { COMMOND_TYPE_MESH_SELECTED } from "@/common/Constant";
import EventBus from "@/utils/EventBus";
import { useStateStore } from "@/stores/state";
import { MouseStatus } from "@/model/MouseStatus";
import { FillType } from "@/model/D3Config";
import { useConfigStore } from "@/stores/config";
/**
 * 二维模型
 */
export class D2Control extends BaseControl<D2Mesh> {
    constructor(ele: Element, threeMode: ThreeMode, mesh: D2Mesh) {
        super(ele, threeMode, mesh);
    }

    /**
     * 鼠标按下的事件
     * @param event 事件值
     */
    protected mousedown(event: Event) {
        // 0‌:表示‌左键‌被按下。
        // ‌1‌:表示中间键(滚轮)被按下。
        // ‌2‌:表示‌右键‌被按下。
        if((event as MouseEvent).button == 1){
            return;
        }

        // 阻止窗口滚动行为
        event.preventDefault();
        event.stopPropagation();

        //如果开启了轨道控制器,则不能手写
        if (this.threeMode.control.enabled) {
            return;
        }
        if (!this.mesh.item) {//没有选中要绘制的图形,直接结束
            return;
        }

        if((event as MouseEvent).button == 2){//按下的是右键
            if(this.mesh.item.key === 'polyline' || this.mesh.item?.key === 'polygon'){//折线的情况需要做特殊处理
                this.currentState = false;
                this.mesh.currentMesh = null;
                // useStateStore().currentMesh = null;
                useStateStore().currentStatus = MouseStatus.None;
                return;
            }
            return;
        }
        if(this.currentState){
            return;
        }
        this.currentState = true;
        const intersects = this.getMousePoint([], MouseStatus.Create);
        if (intersects.length > 0) {//创建黑板擦,并添加到场景中去
            const point = intersects[0].point;
            //创建新的物体信息
            useStateStore().currentMesh = this.mesh.create(point);

            EventBus.emit(COMMOND_TYPE_MESH_SELECTED, (useStateStore().currentMesh as D2Mesh).item);
        }
    }

    /**
     * 鼠标抬起的事件
     * @param event 事件值
     */
    protected mouseup(event: Event) {
        // 阻止窗口滚动行为
        event.preventDefault();
        event.stopPropagation();

        if(this.mesh.item?.key === 'polyline' || this.mesh.item?.key === 'polygon'){//折线的情况需要做特殊处理
            if (!this.currentState) {
                return;
            }
            const intersects = this.getMousePoint([], MouseStatus.Create);
            if (intersects.length > 0) {
                const point = intersects[0].point;
                if (this.mesh.item && this.mesh.item.mouseMove && this.mesh.currentMesh) {
                    this.mesh.item.mouseMove(point, this.mesh.currentMesh,event as MouseEvent);
                }
            }
            return;
        }
        this.currentState = false;
        this.mesh.currentMesh = null;
        // useStateStore().currentMesh = null;
        useStateStore().currentStatus = MouseStatus.None;
    }

    /**
     * 鼠标移动的事件
     * @param event 事件值
     */
    protected mousemove(event: Event) {
        if (!this.currentState) {
            return;
        }
        // 阻止窗口滚动行为
        event.preventDefault();
        event.stopPropagation();
        const intersects = this.getMousePoint([], MouseStatus.Create);
        if (intersects.length > 0) {
            const point = intersects[0].point;
            if (this.mesh.item && this.mesh.item.mouseMove && this.mesh.currentMesh) {
                this.mesh.item.mouseMove(point, this.mesh.currentMesh,event as MouseEvent);
            }
        }
    }

    public getChildren() {
        return this.mesh.getChildren();
    }

    public clear() {
        this.mesh.clear();
    }


    /**
     * 修改二维背景的颜色
     */
    public setMeshD2PlanColor(newVal: THREE.Color) {
        this.mesh.plane.material.color.copy(newVal);
    }
    /**
     * 修改物体描边的颜色
     * @param newVal 
     */
    public setMeshLineColor(newVal: THREE.Color) {
        if (this.mesh.currentMesh) {
            this.mesh.currentMesh.material.color.copy(newVal);
        }
    }
    /**
     * 修改物体描边的尺寸
     * @param newVal 
     */
    public setMeshLineWidth(newVal: number) {
        if (this.mesh.currentMesh) {
            this.mesh.currentMesh.material.width = newVal;
        }
    }
    /**
     * 修改物体填充的类型
     * @param newVal 
     */
    public setMeshFillType(newVal: FillType) {
        switch (newVal) {
            case FillType.Color:
                if (this.mesh.currentMesh) {
                    this.mesh.currentMesh.material.color.copy(useConfigStore().d3Config.mesh.fill.color);
                }
                break
            case FillType.Texture:
                break
            case FillType.GradientColor:
                break
            case FillType.Customer:
                break
        }
    }

    /**
     * 修改物体填充的颜色
     * @param newVal 
     */
    public setMeshFillColor(newVal: THREE.Color) {
        if (this.mesh.currentMesh) {
            this.mesh.currentMesh.material.color.copy(newVal);
        }
    }
    /**
     * 设置二维背景板的透明度
     * @param newVal 
     */
    public setMeshD2PlanOpacity(newVal: number) {
        this.mesh.plane.material.opacity = newVal;
    }
    /**
     * 设置二维背景板的纹理信息
     * @param newVal 
     */
    public setMeshD2PlanTexture(textureLoader: THREE.TextureLoader, newVal: string) {
        let material = new THREE.MeshBasicMaterial();
        material.copy(this.mesh.plane.material);
        material.map = textureLoader.load(newVal);
        this.mesh.plane.material = material;
    }
}

2.3 按钮定义

  1. routineTools.ts
javascript 复制代码
import { PointMeshItem } from "@/model/MeshToolItem/2d/PointMeshItem";
import { LineMeshItem } from "@/model/MeshToolItem/2d/LineMeshItem";
import { SphereMeshItem } from "@/model/MeshToolItem/3d/SphereMeshItem";
import { PolyLineMeshItem } from "@/model/MeshToolItem/2d/PolylineMeshItem";
import { PolygonMeshItem } from "@/model/MeshToolItem/2d/PolygonMeshItem";
import { CircleMeshItem } from "@/model/MeshToolItem/2d/CircleMeshItem";
import { TriangleMeshItem } from "@/model/MeshToolItem/2d/triangleMeshItem";
import { ChalkMeshItem } from "@/model/MeshToolItem/2d/ChalkMeshItem";
import { ArrowDownMeshItem } from "@/model/MeshToolItem/2d/ArrowDownMeshItem";
import { ArrowLeftMeshItem } from "@/model/MeshToolItem/2d/ArrowLeftMeshItem";
import { ArrowRightMeshItem } from "@/model/MeshToolItem/2d/ArrowRightMeshItem";
import { ArrowUpMeshItem } from "@/model/MeshToolItem/2d/ArrowUpMeshItem";
import { RingMeshItem } from "@/model/MeshToolItem/2d/RingMeshItem";
import { SectorMeshItem } from "@/model/MeshToolItem/2d/SectorMeshItem";
import { SquareMeshItem } from "@/model/MeshToolItem/2d/SquareMeshItem";
import { RectangleMeshItem } from "./RectangleMeshItem";
import { RightTriangleMeshItem } from "@/model/MeshToolItem/2d/RightTriangleMeshItem";
import { EquilateralTriangleMeshItem } from "@/model/MeshToolItem/2d/EquilateralTriangleMeshItem";
import { LineSegmentMeshItem } from "@/model/MeshToolItem/2d/LineSegmentMeshItem";
import { Rectangle3DMeshItem } from "@/model/MeshToolItem/3d/Rectangle3DMeshItem";
import { Square3DMeshItem } from "@/model/MeshToolItem/3d/Square3DMeshItem";
import { TetrahedronMeshItem } from "@/model/MeshToolItem/3d/TetrahedronMeshItem";
import { Tetrahedron8MeshItem } from "@/model/MeshToolItem/3d/Tetrahedron8MeshItem";
import { Tetrahedron12MeshItem } from "@/model/MeshToolItem/3d/Tetrahedron12MeshItem";
import { Tetrahedron20MeshItem } from "@/model/MeshToolItem/3d/Tetrahedron20MeshItem";
import { TetrahedronXMeshItem } from "@/model/MeshToolItem/3d/TetrahedronXMeshItem";
import { TorusMeshItem } from "@/model/MeshToolItem/3d/TorusMeshItem";
import { CylinderMeshItem } from "@/model/MeshToolItem/3d/CylinderMeshItem";
import { CapsuleMeshItem } from "@/model/MeshToolItem/3d/CapsuleMeshItem";
import { ConeMeshItem } from "@/model/MeshToolItem/3d/ConeMeshItem";

/**
 * 常规图形的定义
 */
export default ()=>{
    return [{
        name: '二维图形',
        icon: '',
        commond: '3d',
        key: '2d',
        fkey:'2d',
        children: [
            new ChalkMeshItem('手写','chalk.svg','chalk','math'),
            
            new ArrowRightMeshItem('向右箭头','arrow_right.svg','arrow_right','math'),
            new ArrowLeftMeshItem('向左箭头','arrow_left.svg','arrow_left','math'),
            new ArrowUpMeshItem('向上箭头','arrow_up.svg','arrow_up','math'),
            new ArrowDownMeshItem('向下箭头','arrow_down.svg','arrow_down','math'),

            new PointMeshItem('点','point.svg','point','math'),
            new LineMeshItem('直线','line.svg','line','math'),
            new PolyLineMeshItem('折线','polyline.svg','polyline','math'),
            new LineSegmentMeshItem('线段','line_segment.svg','line_segment','math'),

            new CircleMeshItem('圆','circle.svg','circle','math'),
            new SectorMeshItem('扇形','sector.svg','sector','math'),
            new RingMeshItem('环形','ring.svg','ring','math'),

            new SquareMeshItem('正方形','square.svg','square','math'),
            new RectangleMeshItem('长方形','rectangle.svg','rectangle','math'),
            new PolygonMeshItem('多边形','polygon.svg','polygon','math'),

            new TriangleMeshItem('三角形','triangle.svg','triangle','math'),
            new RightTriangleMeshItem('直角三角形','right_triangle.svg','right_triangle','math'),
            new EquilateralTriangleMeshItem('等边三角形','equilateral_triangle.svg','equilateral_triangle','math')
        ]
    }, {
        name: '三维图形',
        icon: '',
        commond: '3d',
        key: '3d',
        fkey:'3d',
        children: [
            // name:string,icon:string,key:string,fkey:string
            // new SphereMeshItem('坐标轴','d3_axis.svg','d3_axis','math'),

            new Square3DMeshItem('正方体','cube.svg','cube','math'),
            new Rectangle3DMeshItem('长方体','cuboid.svg','cuboid','math'),
            new TetrahedronMeshItem('四面体','tetrahedron.svg','tetrahedron','math'),
            new Tetrahedron8MeshItem('八面体','tetrahedron8.svg','tetrahedron8','math'),
            new Tetrahedron12MeshItem('十二面体','tetrahedron12.svg','tetrahedron12','math'),
            new Tetrahedron20MeshItem('二十面体','tetrahedron20.svg','tetrahedron20','math'),
            new TetrahedronXMeshItem('多面体','tetrahedronx.svg','tetrahedronx','math'),

            new SphereMeshItem('球体','sphere.svg','sphere','math'),
            new TorusMeshItem('圆环','3d_ring.svg','3d_ring','math'),

            new CylinderMeshItem('圆柱','cylinder.svg','cylinder','math'),
            new CapsuleMeshItem('胶囊','capsule.svg','capsule','math'),

            new ConeMeshItem('锥体','cone.svg','cone','math'),
        ]
    }]
}
相关推荐
集智飞行20 分钟前
解决mavros2 ros2版本cpu占用高的问题
java·服务器·前端
w2sfot1 小时前
【JS加密在线】jsjiami.online(让JavaScript 更安全!)
开发语言·javascript·安全
HSunR1 小时前
ruoyi 若依 自定义注解 参数校验
java·前端·数据库
知野小兔1 小时前
Vuex和Pinia状态管理
vue.js
拆房老料2 小时前
ONLYOFFICE也能像Microsoft Word和WPS一样分别设置中西文字体
前端·html·word·开源软件·wps
足球中国2 小时前
3D STEP文件编程
3d
VX_bysjlw9852 小时前
数码设备销售网站设计与实现39138-计算机毕设原创(免费领源码+带部署教程)
java·vue.js·spring boot·mysql·tomcat·mybatis·idea
Solis程序员3 小时前
Stripe 幂等表:把「不确定的重试」变成「查表返回」
前端·安全·bootstrap·php·agent
时空节拍AI数字人3 小时前
数字文旅补贴来了,景区申报要注意什么?
大数据·人工智能·百度·3d·ai·架构·aigc
Martina_03213 小时前
AI生成3D模型导入后只剩一个大网格?用6步完成微缩场景拆分与优化
人工智能·游戏·数学建模·3d·ai·自然语言处理·aigc