倘若我用出这招3Dkunkun,阁下该如何应对呢!

抛玉引砖

我正在参加「掘金·启航计划」,最新闲来无事,决定学习一下新技术,丰富一下自身(实在是无鱼可摸了,jym发小故事的频率不太行啊),所以就让我来给jym创造一点话题吧.最近看了几篇threejs的教学文章,决定动手实现一个3d版的坤坤(不喜勿喷?).

原图长这个样子

2722689571d241b3a80ec3244e239c6d~tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.webp

经过大佬的处理之后变成了酱紫,大佬的文章链接我放这里啦juejin.cn/post/717867…

657b10b6ddf240ec833f64ae8867fa5c~tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.webp

Show Time!

好了,下面轮到我们表演啦,如何把这张图片变成360度无死角环绕,让你充分体会kunkun的魅力,最终加入我们ikun呢,那就需要用到threejs了.先看一下最终的效果吧:

iShot_2023-04-07_18.02.12.gif

怎么样,是不是被我们kunkun迷住了,那还犹豫什么呢,加入我们ikun吧,坤流无所不在?.

实现过程

实现起来还是挺容易的,简单来说就是利用threejs创建了一个立方集合体(BoxGeometry),然后对立方体进行贴图(注意这里只能是静态图片,动图是不行的),那如何让我们的kunkun动起来,充分展示舞蹈魅力呢,我们只需要循环渲染,每一帧贴不同的图片就可以了.

具体的threejs教程我就不写了,因为我也是刚学,就放一下大佬写的教程文章吧
juejin.cn/post/698098…

第一步,对立方体进行贴图

 createModel() {
        this.canvas = document.createElement('canvas');
        this.ctx = this.canvas.getContext('2d');
        this.canvas.width = 500;
        this.canvas.height = 529;
        const img = new Image();
        img.src = `/test/2.png`;
        this.ctx.drawImage(img, 0, 0)//绘制图片
        const geometry = new THREE.BoxGeometry(2, 2, 2);
        this.texture = new THREE.Texture(this.canvas);
        this.texture.needsUpdate = true;
        const material = new THREE.MeshBasicMaterial({ map: this.texture, side: THREE.BackSide })
        const cube = new THREE.Mesh(geometry, material)
        this.cube = cube;
        this.scene.add(cube);
    }

效果如下
image.png

第二步,让我们的kunkun动起来

值得注意的是,为了让贴图动起来,需要不断的更新贴图的图像,这里我用的是canvas,然后不断改变canvas里渲染的图片

    getMaterial() {
        this.current++;
        if (this.current > 86) this.current = 2;
        return `/test/${this.current}.png`;
    }

    createCanvas() {
        this.canvas = document.createElement('canvas');
        this.ctx = this.canvas.getContext('2d');
        this.canvas.width = 500;
        this.canvas.height = 529;
        this.timer = setInterval(() => {
            const img = new Image();   // 创建一个<img>元素
            img.onload = () => {
                this.ctx.drawImage(img, 0, 0)//绘制图片
            }
            img.src = this.getMaterial(); // 设置图片源地址
        }, 100);
    }



    createModel() {
        this.createCanvas();
        const geometry = new THREE.BoxGeometry(2, 2, 2);
        this.texture = new THREE.Texture(this.canvas);
        this.texture.needsUpdate = true;
        const material = new THREE.MeshBasicMaterial({ map: this.texture, side: THREE.BackSide })
        const cube = new THREE.Mesh(geometry, material)
        this.cube = cube;
        this.scene.add(cube);
    }

到这里我们的kunkun就动起来啦.

image.png

完整代码放下面啦,欢迎大佬们指教,我很菜,但我不改.

import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'


export class KunKun {
    constructor({ container, width, height }) {
        this.dom = container || document.body;
        this.width = width || window.innerWidth;
        this.height = height || window.innerHeight;
    }
    current = 2;
    init() {
        // 第一步新建一个场景
        this.scene = new THREE.Scene();
        this.setCamera();
        this.setRenderer();
        this.createModel();
        this.initControls();
        this.animate();
    }



    initControls() {
        this.orbitControls = new OrbitControls(this.camera, this.renderer.domElement)

    }

    getMaterial() {
        this.current++;
        if (this.current > 86) this.current = 2;
        return `/test/${this.current}.png`;
    }


    createCanvas() {
        this.canvas = document.createElement('canvas');
        this.ctx = this.canvas.getContext('2d');
        this.canvas.width = 500;
        this.canvas.height = 529;
        this.timer = setInterval(() => {
            const img = new Image();   // 创建一个<img>元素
            img.onload = () => {
                this.ctx.drawImage(img, 0, 0)//绘制图片
            }
            img.src = this.getMaterial(); // 设置图片源地址
            this.img = img;
        }, 100);
    }

    createModel() {
        this.createCanvas();
        const geometry = new THREE.BoxGeometry(2, 2, 2);
        this.texture = new THREE.Texture(this.canvas);
        this.texture.needsUpdate = true;
        const material = new THREE.MeshBasicMaterial({ map: this.texture, side: THREE.BackSide })
        const cube = new THREE.Mesh(geometry, material)
        this.cube = cube;
        this.scene.add(cube);
    }


    animate() {
        this.texture.needsUpdate = true;
        requestAnimationFrame(this.animate.bind(this))
        this.renderer.render(this.scene, this.camera)
    }
    // 新建透视相机
    setCamera() {
        // 第二参数就是 长度和宽度比 默认采用浏览器  返回以像素为单位的窗口的内部宽度和高度
        this.camera = new THREE.PerspectiveCamera(
            75,
            this.width / this.height,
            0.1,
            1000
        );
        this.camera.position.set(1, 1, 4);
    }

    // 设置渲染器
    setRenderer() {
        this.renderer = new THREE.WebGLRenderer({
            antialias: true,//抗锯齿
        })
        // 设置画布的大小
        this.renderer.setSize(this.width, this.height)
        //这里 其实就是canvas 画布  renderer.domElement
        this.dom.appendChild(this.renderer.domElement)
    }

    // 设置环境光
    setLight() {
        this.ambientLight = new THREE.AmbientLight(0xffffff) // 环境光
        this.scene.add(this.ambientLight)
    }

    // 销毁画布
    destroy() {
        this.renderer.domElement.remove();
        clearInterval(this.timer);
    }
}
import React, { useEffect, useRef } from 'react';
import { KunKun } from './class';


const Demo = () => {
  const domRef = useRef();
  useEffect(() => {
    const map = new KunKun({
      container: domRef.current,
      width: 600,
      height: 800
    });
    map.init();
    return () => {
      map.destroy();
    };
  }, []);
  return <div ref={domRef}></div>;
};

export default Demo;

我这里是用工具把gif图解析成每一帧,存在本地来进行展示的,网上有很多库可以做到这点,你们就不必参考我这种方式啦,原谅我很菜?.

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYnZB7DV' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片