通过字母在画布上绘制文本,以控制单个字母的alpha,同时与中心对齐
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过字母在画布上绘制文本,以控制单个字母的alpha,同时与中心对齐相关的知识,希望对你有一定的参考价值。
我试图以非常具体的方式在画布上绘制一些字母 - 能够定位单个字母并应用alpha。这些单词需要以基线为中心,并在画布中对齐中心并填充strokeText而不是填充样式。
文本也需要断行,例如;
现在,我已经尝试了几种方法来解决这个问题 - 当写出单词(作为完整单词)时它工作正常(没有淡入淡出) - 但是当我尝试将它们写成单独的字母时,我无法正确地将它们置于中心位置。我的代码在下面省略了特定字母上的alpha,一旦我能正确地将事物放在中心,这应该不是问题!
我意识到问题是我试图在画布上分别以0为中心绘制每个字母,并为每个字母添加字母间距,但考虑到中间线的不同大小,我无法想办法让它们居中!
var can = document.querySelector('canvas'),
ctx = can.getContext('2d');
function drawStroked(text, fontSize, color, offsetX, offsetY) {
let line = text.split('
');
this.ctx.font = fontSize + 'px ' + 'TimesNewRoman';
this.ctx.strokeStyle = color;
this.ctx.lineWidth = 2;
this.ctx.textBaseline = 'middle';
this.ctx.textAlign = 'center';
let positionX = this.ctx.canvas.width/3;
let positionY = this.ctx.canvas.height/4;
if(offsetX !== 0) {
positionX += offsetX;
}
if(offsetY !== 0) {
positionY += offsetY;
}
for (var i = 0; i < line.length; i++) {
for (var j = 0; j < line[i].length; j++) {
let letterSpacing = 0;
let lineHeight = positionY;
if(line[i][j] === line[i].length) {
lineHeight = lineHeight * i;
}
this.ctx.strokeText(line[i][j], positionX + (letterSpacing + (j*130)), positionY + (i*fontSize));
}
}
}
drawStroked('THIS
IS THE
TEXT', 100, '#000', 0, 0);
<canvas width="1000" height="1000"></canvas>
由Blindman67产生的输出和完成的代码!
const Hero = class {
constructor(pos, canvas) {
this.position = document.getElementById(pos);
this.canvas = document.getElementById(canvas);
this.height = document.getElementsByClassName('home')[0].clientHeight;
this.width = this.position.offsetWidth;
this.ctx = this.canvas.getContext('2d');
this.title = 'THIS
IS THE
TEXT';
this.canvas.width = this.width;
this.canvas.height = this.height;
this._init_ui();
}
// Draw text to text canvas
_init_ui() {
// BLUE
this.drawStroked(300, '#1816ff', -3, 2, 0.95, [1, 5, 9, 12]);
// GREEN
this.drawStroked(300, '#1bff32', 0, 0, 0.95, [1, 5, 9, 12]);
// RED
this.drawStroked(300, '#ff162f', 3, -2, 0.95, [1, 5, 9, 12]);
}
drawStroked(fontSize, color, offsetX, offsetY, textVertSpacing, fade) {
// Random Char's to scramble through --- to do
// let chars = '!<>-_\/[]{}—=+*^?#________';
// The words
let line = this.title.split('
');
// Set the font + size
this.ctx.font = fontSize + 'px ' + 'Kommissar';
// Set the colour - NEED TO ADD ALPHA LOGIC
this.ctx.strokeStyle = color;
// Set the stroke width
this.ctx.lineWidth = 1;
// Set the baseline
this.ctx.textBaseline = 'middle';
// Set the align
this.ctx.textAlign = 'center';
let positionX = this.width/2;
let positionY = this.height/4;
positionX += offsetX;
positionY += offsetY;
let charIndex = 0;
for (var i = 0; i < line.length; i++) {
// get the width of the whole line
let width = this.ctx.measureText(line[i]).width;
console.log(width);
// use the width to find start
var textPosX = positionX - width / 2;
for (let j = 0; j < line[i].length; j++) {
// get char
let char = line[i][j];
// get its width
let cWidth = this.ctx.measureText(char).width;
// check if char needs to fade
if (fade.indexOf(charIndex) > -1) {
this.ctx.globalAlpha = 0.2;
} else {
this.ctx.globalAlpha = 1;
}
// draw the char offset by half its width (center)
this.ctx.strokeText(char, textPosX + cWidth / 2, positionY);
// move too the next pos
textPosX += cWidth;
// count the char
charIndex += 1;
}
// move down one line
positionY += fontSize * textVertSpacing;
}
}
};
export default Hero;
Use ctx.measureText
你需要使用ctx.measureText
并获得每个角色的宽度,然后你可以正确地隔开它们。
正确的字符间距
因为你有对齐中心,你必须将角色的宽度移动一半,然后绘制它,然后再移动一半的宽度。字符中心之间的间距是每个添加的宽度的一半。因此,如果"I"
是20
像素宽,"W"
是60那么他们之间的空间是10 + 30 = 40
;
淡化字符
为了做淡入淡出,我传递了一个数组,其中字符的索引为淡入淡出。我每次画一个角色都算数。要检查字符是否应该淡入,请检查索引数组中的字符数。如果它们匹配则淡化该角色。
有关更多信息,请参阅示例
简单的例子......
...我认为你想要的。我添加了两条红线以确保对齐正确。
const ctx = canvas.getContext('2d');
ctx.fillStyle = "#FDD"; // mark the center
ctx.fillRect(canvas.width / 2 | 0, 0, 1, canvas.height);
ctx.fillRect(0, canvas.height / 2 | 0, canvas.width, 1);
ctx.fillStyle = "black";
// textVertSpacing is fraction of FontSize
// fade is the index of characters to fade, including spaces
// centerX and y is center of all text
function drawStroked(text, fontSize, color, centerX, centerY, textVertSpacing, fade) {
let line = text.split('
');
ctx.font = fontSize + 'px ' + 'TimesNewRoman';
ctx.strokeStyle = color;
ctx.lineWidth = 2;
ctx.textBaseline = 'middle';
ctx.textAlign = 'center';
// to count each character
var charIndex = 0;
// find the top ypos and then move down half a char space
var yPos = centerY - fontSize * line.length * 0.5 * textVertSpacing + fontSize * textVertSpacing / 2;
for (var i = 0; i < line.length; i++) {
// get the width of the whole line
var width = ctx.measureText(line[i]).width;
// use the width to find start
var textPosX = centerX - width / 2;
for (var j = 0; j < line[i].length; j++) {
// get char
var char = line[i][j];
// get its width
var cWidth = ctx.measureText(char).width;
// check if char needs to fade
if (fade.indexOf(charIndex) > -1) {
ctx.globalAlpha = 0.5;
} else {
ctx.globalAlpha = 1;
}
// draw the char offset by half its width (center)
ctx.fillText(char, textPosX + cWidth / 2, yPos);
// move too the next pos
textPosX += cWidth;
// count the char
charIndex += 1
}
// move down one line
yPos += fontSize * textVertSpacing;
}
}
drawStroked('THIS
IS THE
TEXT', 60, '#000', canvas.width / 2, canvas.height / 2, 0.9, [2, 4, 8, 12]);
<canvas id="canvas" width="500" height="200"></canvas>
在webpack设置中使用它很抱歉它不会运行!
// Code in UTIL
getRandomInt(max) {
return Math.floor(Math.random() * (max - 0 + 1)) + 0;
};
const $window = $(window);
let running = false;
const Hero = {
init() {
this.home = $('#home');
this.position = $('#hero');
this.canvas = $('#title');
this.ctx = this.canvas[0].getContext('2d');
this.width = this.position.width();
this.height = this.home.height();
this.ctx.lineWidth = 1.5;
this.fontSize = null;
this.letterSpacing = null;
if(this.position.lenth === 0) {
return;
}
if(running) {
return;
}
// Set hero opacity to 0 for animation
// $('#hero').css('opacity', 0);
this.size();
$window.on('resize', () => {
clearTimeout(this.debounce);
this.debounce = setTimeout( () => {
this.height = this.home.height();
this.width = this.position.width();
this.size();
}, 50);
});
},
size() {
running = true;
this.canvas[0].width = this.width;
this.canvas[0].height = this.height;
if(this.width < 1000) {
this.fontSize = 150;
this.letterSpacing = 5;
} else {
this.fontSize = 300;
this.letterSpacing = 30;
}
},
animate(frames) {
var frameCount = frames || 0;
const flickerRate = 4;
const fade = [Utils.getRandomInt(13), Utils.getRandomInt(13)];
if((frameCount % flickerRate) === 0){
this.ctx.clearRect(0, 0, this.width, this.height);
// Blue
this.drawStroked(this.fontSize, '#0426ff', -2, 2, true, fade);
// Green
this.drawStroked(this.fontSize, '#04ffae', 1, 2, true, fade);
// Pink
this.drawStroked(this.fontSize, '#ff29ad', 0, 0, true, fade);
// White
this.drawStroked(this.fontSize, '#fff', 0, 0, true, fade);
}
frameCount ++;
console.log(frameCount);
// requestAnimationFrame(this.animate);
setTimeout(() => {
this.animate(frameCount);
}, 0.5);
},
drawStroked(fontSize, color, offsetX, offsetY, flicker, fade) {
let line = 'CODE
IN THE
DARK'.split('
'),
chars = line.join('');
// Set the font + size
this.ctx.font = fontSize + 'px ' + 'Kommissar';
// Set the colour
this.ctx.strokeStyle = color;
// Set the baseline
this.ctx.textBaseline = 'middle';
// Set the align
this.ctx.textAlign = 'center';
let letterSpacing = this.letterSpacing,
positionX = (this.width/2 + letterSpacing) + offsetX,
positionY = (this.height/4) + offsetY,
charIndex = 0;
for (var i = 0; i < line.length; i++) {
// get the width of the whole line
let width = this.ctx.measureText(line[i]).width;
// use the width to find start
var textPosX = positionX - width / 2;
for (let j = 0; j < line[i].length; j++) {
// get char
let char = line[i][j];
// get its width
let cWidth = this.ctx.measureText(char).width;
// check if char needs to fade
if(flicker) {
this.ctx.globalAlpha = fade.indexOf(charIndex) > -1 ? Math.random() * 0.5 + 0.25 : 0;
} else {
this.ctx.globalAlpha = 1;
}
// draw the char offset by half its width (center)
this.ctx.shadowColor = color;
this.ctx.shadowBlur = 15;
this.ctx.strokeText(char, textPosX + cWidth / 2, positionY);
// move too the next pos
textPosX += cWidth;
// count the char
charIndex += 1;
}
// move down one line
positionY += fontSize * 1.05;
}
}
};
export default Hero;
#home {
width: 100%;
#hero {
position: absolute;
z-index: 5;
top: 0;
left: 0;
width: 100%;
padding: 30px 0;
> canvas {
margin: 0 auto;
display: block;
}
}
}
<div id="home">
<div id="hero">
<canvas id="title"></canvas>
</div>
</div>
以上是关于通过字母在画布上绘制文本,以控制单个字母的alpha,同时与中心对齐的主要内容,如果未能解决你的问题,请参考以下文章