three.js 用中文字作为贴图

闲来无事,把three.js其中有一个例子改了一下,变成从一个中心点喷射出中文字的例子,下面直接贴代码好了
html:

<html lang="en">
    <head>
        <title>three.js canvas - text - sprites</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
        <style>
            body {
                background-color: #000000;
                margin: 0px;
                overflow: hidden;
            }

            a {
                color: #0078ff;
            }
    @media screen and (max-width: 600px) {
                html{
                    font-size:6px;
                }
            }
        </style>
    </head>
    <body>
        <div class="controls">
            <input type="text" name="danmu"  id="danmuInput"/>
            <button onclick="sendText()">发射弹幕(send)</button>
        </div>
    <div class="clear" onclick="clearAll()">
        清除(clear)
    </div>
    </body>
</html>

css只是表现层让他看起来稍微好看一点,所以不算是最重要的,除此之外写了一小部分便于在手机上浏览响应式css
css:

 @media screen and (max-width: 600px) {
                html{
                    font-size:6px;
                }
            }
html{
                font-size:10px;
            }
            *{
                margin:0;
                padding:0;
                box-sizing:border-box;
            }
            .controls{
                width:40rem;
                height:20rem;
                border: 0.2rem solid #88f;
                border-radius:0.5rem;
                position:fixed;
                bottom:1rem;
                left:50%;
                margin-left:-20rem;
                background-color: rgba(155,155,255,0.1);

            }
            #danmuInput{
                width:30rem;
                font-size:2rem;
                text-align:center;
                background-color: rgba(155,155,255,0.6);
                color:white;
                height:3.8rem;
                line-height:3.8rem;
                margin:4rem 0 0 5rem;
                border:0.1rem solid rgba(200,200,255,0.3);
            }
            #danmuInput:focus{
                border:0.1rem solid rgba(200,200,255,0.9);
                box-shadow:none;
                outline:none;
                box-shadow:0 0 0.2rem 0.1rem rgba(200,200,255,0.9);
            }
            .controls button{
                position:absolute;
                width:20rem;
                height:4rem;
                bottom:2rem;
                left:50%;
                margin-left:-10rem;
                background-color: rgba(0,0,0,0);
                color:white;
                font-size:2rem;
                text-shadow:0 0 5px #fff;
            }
.controls button:hover{
  cursor:pointer;
  background-color: rgba(255,255,255,0.4);
  color:#00f;
}
.clear{
  width:12rem;
  height:4rem;
  background-color:rgba(255,177,255,0.1);
  position:fixed;
  top:2rem;
  right:4rem;
  font-size:2rem;
  color:white;
  font-weght:bold;
  line-height:4rem;
  text-align:center;
  text-shadow:0 0 1rem rgba(255,177,255,0.6);
  border-radius:0.4rem;
  transition: all .3s; 
}
.clear:hover{
  cursor:pointer;
  background-color:rgba(255,200,255,0.4);
  line-height:3.8rem;
  box-shadow:0 0 1rem 0.5rem rgba(255,200,255,0.2);
}
.clear:active{
  cursor:pointer;
  background-color:rgba(255,200,255,0.3);
  line-height:4.2rem;
  box-shadow:0 0 1rem 0.5rem rgba(255,200,255,0.2);
}

最关键的js部分:
前置js:
three.js
https://threejs.org/build/three.js
three.js的项目管理插件 方便
https://threejs.org/examples/js/renderers/Projector.js
tween渐变插件 有许多渐变函数可以用 用于制作动画
https://threejs.org/examples/js/libs/tween.min.js
three里面的信息搜集展示插件 可以显示帧数等性能信息
https://threejs.org/examples/js/libs/stats.min.js
画布渲染插件 ,因为three默认用的是webgl渲染有了这个插件可以用canvas原生2d模式渲染,添加canvas渲染器必备
https://threejs.org/examples/js/renderers/CanvasRenderer.js

   var container, stats;
           //首先最开始要生声明变量
            var camera, scene, renderer, particle;
            var mouseX = 0, mouseY = 0;
            var text = "弹幕";    

            var windowHalfX = window.innerWidth / 2;
            var windowHalfY = window.innerHeight / 2;
            //初始化函数
            init();
            //动画函数 递归的方式调用
            animate();
            //初始化
            function init() {
                //  初始化canvas元素
                container = document.createElement( 'div' );
                document.body.appendChild( container );
                //创建相机
                camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 5000 );
                camera.position.z = 1000;
                //创建场景
                scene = new THREE.Scene();
                var color = "red";
                var material = new THREE.SpriteMaterial( {
                    map: new THREE.CanvasTexture( generateSprite(text,color) ),
                    blending: THREE.AdditiveBlending
                } );
                //生成100个并且每隔100ms出现一个
                for ( var i = 0; i < 100; i++ ) {

                    particle = new THREE.Sprite( material );

                    initParticle( particle, i * 100 );

                    scene.add( particle );
                }
                //使用的渲染器是THREE的2Dcanvas渲染器而非webgl
                renderer = new THREE.CanvasRenderer();
                renderer.setClearColor( 0x000040 );//设置清屏的颜色一般来说是背景的颜色这里设置了深蓝色
                renderer.setPixelRatio( window.devicePixelRatio );
                renderer.setSize( window.innerWidth, window.innerHeight );
                container.appendChild( renderer.domElement );
                //用于展现帧数等数据信息
                stats = new Stats();
                container.appendChild( stats.dom );

                document.addEventListener( 'mousemove', onDocumentMouseMove, false );
                document.addEventListener( 'touchstart', onDocumentTouchStart, false );
                document.addEventListener( 'touchmove', onDocumentTouchMove, false );

                //

                window.addEventListener( 'resize', onWindowResize, false );

            }
            //当网页窗口发生变化时改变canvas渲染部分的大小的函数
            function onWindowResize() {

                windowHalfX = window.innerWidth / 2;
                windowHalfY = window.innerHeight / 2;

                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();

                renderer.setSize( window.innerWidth, window.innerHeight );

            }
            //这个才是创建单个字符片段的函数
            function generateSprite(text,style) {

                var canvas = document.createElement( 'canvas' );
                canvas.width = 300;
                canvas.height = 300;

                var context = canvas.getContext( '2d' );
                    context.beginPath();
                    context.font='50px Microsoft YaHei';
                    context.fillStyle = style;
                    context.fillText(text,0,50);
                    context.fill();
                    context.stroke();
                return canvas;

            }
            //将例子中创建一个类似于星星的圆点的画布的函数换了名字
            function generateTextSprite() {
                //创建canvas画布
                var canvas = document.createElement( 'canvas' );
                canvas.width = 16;
                canvas.height = 16;
                //绘制
                var context = canvas.getContext( '2d' );
                //生成渐变圆点
                var gradient = context.createRadialGradient( canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, canvas.width / 2 );
                gradient.addColorStop( 0, 'rgba(255,255,255,1)' );
                gradient.addColorStop( 0.2, 'rgba(0,255,255,1)' );
                gradient.addColorStop( 0.4, 'rgba(0,0,64,1)' );
                gradient.addColorStop( 1, 'rgba(0,0,0,1)' );

                context.fillStyle = gradient;
                context.fillRect( 0, 0, canvas.width, canvas.height );

                return canvas;

            }
            function initParticle( particle, delay ) {

                var particle = this instanceof THREE.Sprite ? this : particle;
                var delay = delay !== undefined ? delay : 0;

                particle.position.set( -500, 0, 0 );
                particle.scale.x = particle.scale.y = 300 /*Math.random() * 32 + 16*/;
                //用了线性函数插件
                new TWEEN.Tween( particle )
                    .delay( delay )
                    .to( {}, 10000 )
                    .onComplete( initParticle )/*这是一个递归 用于持续产生 间隔10s钟*/
                    .start();

                new TWEEN.Tween( particle.position )
                    .delay( delay )
                    .to( { x: Math.random() * 4000 - 2000, y: Math.random() * 1500 - 750, z: Math.random() * 4000 - 2000 }, 10000 )
                    .start();

                new TWEEN.Tween( particle.scale )
                    .delay( delay )
                    .to( { x: 0.03, y: 0.03 }, 10000 )
                    .start();

            }

            //

            function onDocumentMouseMove( event ) {
                mouseX = event.clientX - windowHalfX;
                mouseY = event.clientY - windowHalfY;
            }

            function onDocumentTouchStart( event ) {

                if ( event.touches.length == 1 ) {

                    //event.preventDefault();

                    mouseX = event.touches[ 0 ].pageX - windowHalfX;
                    mouseY = event.touches[ 0 ].pageY - windowHalfY;

                }

            }

            function onDocumentTouchMove( event ) {

                if ( event.touches.length == 1 ) {

                    //event.preventDefault();

                    mouseX = event.touches[ 0 ].pageX - windowHalfX;
                    mouseY = event.touches[ 0 ].pageY - windowHalfY;

                }

            }

            //

            function animate() {
                requestAnimationFrame( animate );
                render();
                stats.update();
            }

            function render() {
                TWEEN.update();
                camera.position.x += ( mouseX - camera.position.x ) * 0.05;
                camera.position.y += ( - mouseY - camera.position.y ) * 0.05;
                camera.lookAt( scene.position );
                renderer.render( scene, camera );

            }

            function changeText(t){
                if ( t != ''){
                    text = t;
                }
                console.log("nyan");
                return text;

            }
            function changeTextAndShow(text,color){
                //确定材料
                //检测在场景中是否过多材料
                if(scene.children.length>2000){return;};
                var material = new THREE.SpriteMaterial( {
                    map: new THREE.CanvasTexture( generateSprite(text,color) ),
                    blending: THREE.AdditiveBlending
                } );

                //生成 并且加入到渲染环境中
                for ( var i = 0; i < 10; i++ ) {
                    particle = new THREE.Sprite( material );
                    initParticle( particle, i * 10 );
                    scene.add( particle );
                }
                console.log("nyan");
            }
            function sendText(){

                var texts = document.getElementById("danmuInput").value;
                if(texts == '')return;
                var color = getRandomColor();
                changeTextAndShow(texts,color);
     console.log("nyannnnn");
            }
            function getRandomColor(){
                var color = "rgba(" + Math.floor(Math.random() * 155 + 100 ) + "," +
                                    Math.floor(Math.random() * 155 + 100) + "," +
                                    Math.floor(Math.random() * 155 +100) + "," +
                                    (Math.random() * 0.5 + 0.5) + ")";
                return color;
            }
            //个人恶趣味
            setTimeout('changeTextAndShow("惊吓","yellow")',2000);
    setTimeout('changeTextAndShow("nyancat","blue")',3000);
    setTimeout('changeTextAndShow("QwQ","rgba(233,155,233,0.6)")',4000);
    changeTextAndShow("惊吓","green");
    function clearAll(){
                scene.children.splice(0,scene.children.length);
    }
    //个人恶趣味 清空之后如果屏幕内没有弹幕则会过11秒加入10个弹幕,鉴于循环周期是10秒所以110秒之后有会有10秒的循环
  function showTextWhenNoTextHere(){
    if(scene.children.length>100){return;}
    else{
      console.log("show more");
      changeTextAndShow("寂寞弹幕","yellow");
    }
  }
setInterval("showTextWhenNoTextHere()",11000);

最后的效果:
https://codepen.io/towrabbit/full/JpqwZy/

猜你喜欢

转载自blog.csdn.net/towrabbit/article/details/80028485