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'),
        ]
    }]
}
相关推荐
海上彼尚2 小时前
SVG矢量图形快速入门
前端·html5
嗷o嗷o2 小时前
Android App Functions 深入理解
前端
qq_20815408852 小时前
瑞树6代流程分析
javascript·python
UXbot2 小时前
AI原型设计工具评测:从创意到交互式Demo,5款产品全面解析
前端·ui·设计模式·ai·ai编程·原型模式
落魄江湖行2 小时前
硅基同事埋的坑,我用2小时才填平:Nuxt 4 路由踩坑:可选参数 [[id]] 与 [id] 的区别
前端
一勺菠萝丶2 小时前
管理后台使用手册在线预览与首次登录引导弹窗实现
java·前端·数据库
军军君012 小时前
Three.js基础功能学习十四:智能黑板实现实例一
前端·javascript·css·typescript·前端框架·threejs·智能黑板
小村儿2 小时前
连载05-Claude Skill 不是抄模板:真正管用的 Skill,都是从实战里提炼出来的
前端·后端·ai编程
xiaotao1312 小时前
JS new 操作符完整执行过程
开发语言·前端·javascript·原型模式