代码之家  ›  专栏  ›  技术社区  ›  Brad Vanderbush

画布HTML填充文本字母,不只是动画阴影

  •  2
  • Brad Vanderbush  · 技术社区  · 6 年前

    只希望阴影的动画,并保持从动画的fillText由于字母像素化得到运行了一遍又一遍。

        var canvas = document.getElementById('canvas')
        var ctx = this.canvas.getContext('2d')
        var width = canvas.width = canvas.scrollWidth
        var height = canvas.height = canvas.scrollHeight
        var start;
        var j=0;
    	var makeText = function(){  
    	   j+=1 
    
    	   ctx.shadowColor= 'red'; 
           ctx.shadowOffsetX = j;  //animate
    	   ctx.shadowOffsetY = j; //animate
    	   ctx.globalAlpha=0.5;
    	   ctx.font = "48px serif";
           ctx.fillStyle = "black";
           ctx.fillText('hey you', width/2, height / 2); //Only ran once so letters 
                                                         //don't pixelate!
       }
        
        			
    	function animateText(timestamp){
    		var runtime = timestamp - start;
    		var progress = Math.min(runtime / 1400, 1); 
     
    		makeText(progress)
    				
    		if(progress < 1){
    			requestAnimationFrame(animateText)
    		}else {
    			return;
    		}
    	}
    	requestAnimationFrame(function(timestamp){
    		start = timestamp;
    		animateText(timestamp)
    	})
    			 
    <canvas id="canvas" width=500px height=500px></canvas>

    2 回复  |  直到 6 年前
        1
  •  2
  •   Helder Sepulveda    6 年前

    只要画出你自己的影子,下面是一个例子:

    var canvas = document.getElementById('canvas')
    var ctx = this.canvas.getContext('2d')
    ctx.font = "68px serif";
    var base = {text: 'hey you', x: 10, y: 60 }
    var inc = 2;
    var j = 30;
    
    var makeText = function() {
      ctx.globalAlpha = 1;
      ctx.fillStyle = "black";
      ctx.fillText(base.text, base.x, base.y); 
    }
    
    var makeshadow = function(offset) {
      ctx.fillStyle = "red";
      for (var i = 0; i < offset; i++) {
        ctx.globalAlpha = 1/i;
        ctx.fillText(base.text, base.x + i, base.y + i);
      }
    }
    
    function animateText() {  
      ctx.clearRect(0, 0, 999, 999)
      makeshadow(j);
      makeText();  
      j += inc;
      if (j > 35 || j < 3) inc *= -1
    }
    
    setInterval(animateText, 50)
    <canvas id="canvas" width=300px height=170px></canvas>

    如果你在混合中加入一些数学,你可以得到一些很酷的效果:

    var canvas = document.getElementById('canvas')
    var ctx = this.canvas.getContext('2d')
    ctx.font = "68px serif";
    var base = {text: '123456', x: 30, y: 80 }
    var inc = 5;
    var j = 0;
    
    var makeText = function() {
      ctx.globalAlpha = 1;
      ctx.fillStyle = "black";
      ctx.fillText(base.text, base.x, base.y); 
    }
    
    var makeshadow = function(offset) {
      ctx.globalAlpha = 0.05;
      ctx.fillStyle = "red";
      for (var i = 0; i < offset; i++)
        ctx.fillText(base.text, base.x + Math.sin(i/5)*10, base.y + Math.cos(i/5)*15);
    }
    
    function animateText() {  
      ctx.clearRect(0, 0, 999, 999)
      makeshadow(j);
      makeText();  
      j += inc;
      if (j > 120 || j < 0) inc *= -1
    }
    setInterval(animateText, 50)
    <
        2
  •  1
  •   Community Mr_and_Mrs_D    4 年前

    你的主要问题(文本像素化)是由于你没有清除画布之间的每一帧,并绘制一次又一次在同一个位置。由抗锯齿创建的半透明像素混合到越来越多的不透明像素。

    但在你的情况下,似乎你真的希望至少阴影像这样混在一起。

    要做到这一点,一种方法是只画一次你的正常文本,并能够画 影子,


    只画形状的影子。

    只绘制形状阴影的一个技巧是,将阴影偏移设置为与此位置相反的位置,从可见视口中绘制形状。

    var text = 'foo bar';
    var ctx = canvas.getContext('2d');
    var original_x = 20; // the position it would have been
    
    ctx.font = '30px sans-serif';
    
    var targetPosition = ctx.measureText(text).width + original_x + 2;
    // default shadow settings
    ctx.shadowColor = 'red';
    ctx.shadowBlur = 3;
    // just to show what happens
    var x = 0;
    anim();
    
    function anim() {
      if(++x >= targetPosition) {
        x=0;
        return;
      }
      // if we weren't to show the anim, we would use 'targetPosition'
      // instead of 'x'
      ctx.shadowOffsetX = x;
      ctx.clearRect(0,0,canvas.width,canvas.height);
      ctx.fillText(text, -x + original_x, 30);
      requestAnimationFrame(anim);
    }
    // restart the anim on click
    onclick = function() {
      if(x===0)anim();
    };
    <canvas id="canvas"></canvas>

    一旦我们有了这个清晰的阴影,不需要在上面画我们的形状,我们就可以随心所欲地重新画它。


    这个 “目的地结束” compositing option 就是这样。

    (请注意,我们还可以将干净的阴影保留在屏幕外的画布上,以便进行表演,因为阴影是一个非常缓慢的操作。)

    var text = 'foo bar';
    var ctx = canvas.getContext('2d');
    ctx.font = '48px sans-serif';
    var x = 20;
    var y = 40;
    var shadow = generateTextShadow(ctx, text, x, y, 'red', 5);
    
    ctx.globalAlpha = 0.5;
    ctx.fillText(text, x, y);
    // from now on we'll draw behind current content
    ctx.globalCompositeOperation = 'destination-over';
    
    var shadow_pos = 0;
    anim();
    // in the anim, we just draw the shadow at a different offset every frame
    function anim() {
      if(shadow_pos++ > 65) return;
      ctx.drawImage(shadow, shadow_pos, shadow_pos);
    
      requestAnimationFrame(anim);
    }
    
    // returns a canvas where only the shadow of the text provided is drawn
    function generateTextShadow(original_ctx, text, x, y, color, blur, offsetX, offsetY) {
      var canvas = original_ctx.canvas.cloneNode();
      var ctx = canvas.getContext('2d');
      ctx.font = original_ctx.font;
      var targetPosition = ctx.measureText(text).width + 2;
      // default shadow settings
      ctx.shadowColor = color || 'black';
      ctx.shadowBlur = blur || 0;
      ctx.shadowOffsetX = targetPosition + x +(offsetX ||0);
      ctx.shadowOffsetY = (offsetY || 0);
      ctx.fillText(text, -targetPosition, y);
      return canvas;
    }
    <