Canvas HTML fillText буквы, чтобы не анимировать только тени - PullRequest
0 голосов
/ 18 сентября 2018

Требуется только анимация теней и предотвращение анимации 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 ]

0 голосов
/ 19 сентября 2018

Ваша основная проблема (пикселизация текста) связана с тем, что вы не очищаете холст между каждым кадром, а снова и снова рисуете в одной и той же позиции.Полупрозрачные пиксели, создаваемые сглаживанием, смешивают до все большего и большего количества непрозрачных пикселей.

Но в вашей ситуации кажется, что вы действительно хотите, чтобы хотя бы тень смешивалась следующим образом.

Для этого одним из способов будет нарисовать только один раз ваш обычный текст и иметь возможность рисовать только тень, позади текущего рисунка.


Рисование только тени фигуры.

Один прием, позволяющий рисовать только тени вашей фигуры, - это нарисовать вашу фигуру из видимого viewPort, с shadowOffsets, установленным в обратное значение этой позиции.

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>

Как только мы получим эту ясную тень без нарисованной на ней фигуры, мы можем перерисовать ее, как пожелаем.


Рисование за текущими пикселями

Параметр * destination-over *1028* делает именно это.

Таким образом, если мы соберем их вместе, мы сможем нарисовать за обычным текстом и нарисовать только нашу тень за ним в каждом кадре, избегая путаницы сглаживания.

(Обратите внимание, чтомы также можем сохранить чистую тень на неэкранном холсте для исполнения, поскольку тень - очень медленная операция.)

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;
}
<canvas id="canvas"></canvas>
0 голосов
/ 18 сентября 2018

Просто нарисуйте свои собственные тени, вот пример:

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)
<canvas id="canvas" width=300px height=170px></canvas>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...