国内某VR、AR企业笔试题分享!canvas写字效果及代码实现

网安智编 厦门萤点网络科技 2025-08-31 00:08 102 0
本篇文章来源于一道国内做vr,ar的企业的笔试题(算是小独角兽那种)。是我今年三月实习的时候摸鱼做的一道题目。内容大概是这样的. 采用h5的canvas 1. 2d部分,画墙,注意测量部分; 2. 3d部分,根据2d部分传过来的数据,显示3...

本篇文章来源于一道国内做vr,ar的企业的笔试题(算是小独角兽那种)。是我今年三月实习的时候摸鱼做的一道题目。内容大概是这样的.

采用h5canvas
1. 2d部分,画墙,注意测量部分;
2. 3d部分,根据2d部分传过来的数据,显示3d墙。建议使用:three.js引擎

最后花了一个小时搞定了。感觉还是挺有意思的。分享一下

微信图片_20231113141142.jpg

最后我实现的效果在下图。上面有个写字的地方,你在上面写字然后three就会在下面的画布渲染出来。并且生成的3d内容支持鼠标拖拽

废话少说,我们直接开始。

在线演示地址:.gitee.io/front-css-p…

代码完整地址://…

总体思路

核心

原来的3维坐标系中 根据canvas的
轨迹 新建 3d 的 1 * 1 的方块
并且根据 canvas 的位置进行放置

1. 部分思路

先讲一下基础思路,我们首先需要实现一个可写的画布,即是 手写板之类的东西

首先是

初始化基础变量:const ctx = cvs.('2d');:获取的2D绘图上下文,这是实际进行绘图操作的对象 。 let = false;:标志变量,用于表示是否处于绘图状态。 let = null; 和 let = null;:记录绘图的起始点和结束点的变量。

添加落笔事件:cvs.('', (e) => {...});:给添加鼠标按下事件监听器。当鼠标按下时,将触发这个事件处理函数,其中:

添加笔触移动事件: cvs.('', (e) => {...});:给添加鼠标移动事件监听器。当鼠标移动时,将触发这个事件处理函数,其中:

添加提笔事件:cvs.('', (e) => {...});:给添加鼠标释放事件监听器。当鼠标释放时,将触发这个事件处理函数,其中:

抽象函数

经过上面的分析,我们就可以很轻松抽象出一个函数

可以看到,我在下面的代码中有一个 wirte函数,里面传入 你的元素就可以让这块区域变成一个手绘板并且保存变量

html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
head>
<body>
  
    <canvas id="test" width="600" height="200">canvas>
    <script>
         function write(dom) {
            const cvs = dom;
            const ctx = cvs.getContext('2d');
            let isDraw = false;
            let startPos = null
            let endPos = null
            cvs.addEventListener('mousedown', (e) => {
                dataArray  = []
                e = e || window.event;
                isDraw = true;
                ctx.moveTo(e.pageX, e.pageY)
                // console.log("start:",e.pageX, e.pageY)
                dataArray.push([e.pageX, e.pageY])
            })
            cvs.addEventListener('mousemove', (e) => {
                e = e || window.event;
       
                if (isDraw) {
                    ctx.lineTo(e.pageX, e.pageY);
                    ctx.stroke();
                    dataArray.push([e.pageX, e.pageY])
                }
                
            })
            cvs.addEventListener('mouseup', (e) => {
                isDraw = false;
                // console.log("end:",e.pageX, e.pageY)
                console.log(dataArray)
               
                dataArray.push([e.pageX, e.pageY])
                // three.initObject(dataArray)
            })
        }
        write(document.querySelector("#test"))
    script>
body>
html>

2.思路

构造一个3d场景需要 ,scene,light,, 这些基本对象,我们可以把他们封装到一个class 类 中

构造函数:

方法:

方法:

方法:

方法:

方法:

抽象类

我们在使用的时候只需要 new () 就好了

  class threeInit {
        constructor(param) {
            this.param = {
                x: 0,
                y: 0,
                z: 0
            }  

canvas 3d_three.js场景构建canvas轨迹渲染_canvas手写板three.js联动

this.initScene() this.initLight() this.initObject() this.initCamera() } // 传入二维坐标, initObject() { //材质 let material = new THREE.MeshLambertMaterial({ color: "rgb(197, 81, 81)" }); let geometry1 = new THREE.BoxGeometry(10, 10, 100); //创建一个立方体几何对象Geometry } initScene() { this.scene = new THREE.Scene() const group = new THREE.Group(); this.scene.add( group ); const helper = new THREE.GridHelper( 160, 100 ); helper.rotation.x = Math.PI / 2; group.add( helper ); } initLight() { let pointLight = new THREE.PointLight(0xffffff); //创建一个白色的点光源 pointLight.position.set(0, 0, 150); this.scene.add(pointLight); let ambient = new THREE.AmbientLight(0xffffff, 1); this.scene.add(ambient); } initCamera() { this.width = 1280; //canvas画布宽度 this.height = 600; //canvas画布高度 let k = this.width / this.height; //canvas画布宽高比 //创建相机对象 this.camera = new THREE.PerspectiveCamera(30, k, 20, 1000); this.camera.position.set(0, 10, 60); //设置相机位置 let v1 = new THREE.Vector3(0, 0, 0) this.camera.lookAt(v1); //设置相机方向(指向的场景对象) } initRender() { let v1 = new THREE.Vector3(0, 0, 0) // let renderer = new THREE.WebGLRenderer(); let renderer = new THREE.WebGLRenderer({ alpha: true }); renderer.setSize(this.width, this.height);//设置渲染区域尺寸 // 添加控制器 let control = new OrbitControls(this.camera, renderer.domElement); control.target = v1 //设置相机方向(指向的场景对象) control.update(); // 渲染函数 let render = () => { // actions[0].play(); const delta = clock.getDelta(); if ( mixer ) mixer.update( delta ); control.update(); renderer.render(this.scene, this.camera);//执行渲染操作 requestAnimationFrame(render);//请求再次执行渲染函数render,渲染下一帧 } render(); return renderer } }

3. 和 联动

我们第一步我们拿到了 的 移动轨迹数据。我们只需要把 第二步的 改造成动态添加的就可以了。就是如下代码

initObject(position) {
    //材质
    let material = new THREE.MeshLambertMaterial({
        color: "rgb(197, 81, 81)"
    });
   //创建一个立方体几何对象Geometry 
    let geometry2 = new THREE.BoxGeometry(1, 1, 10);   
    for(let i in position){
        let mesh =  new THREE.Mesh(geometry2, material); //网格模型对象Mesh
        mesh.position.set(position[i][0]/10, -position[i][1]/10, 0)
        this.scene.add(mesh)
    }
}

有了这一步后,我们在上面的提笔事件中,我们就可以 new .(你的坐标数组)。这样子就可以进行渲染了

总结

总体来说,这段东西应该是入门难度的 和 three。做一个这种demo应该还是能够学到不少东西的

在线演示地址:.gitee.io/front-css-p…

代码完整地址://…