如何更改出现在 arc - context 2d 上的文本顺序,并停止 canvas 2d 上的填充样式覆盖(与 chart.js 一起使用)?
How to change order of text to appear on arc - context 2d, and stop fill style overwriting on the canvas 2d (using with chart.js)?
所以我试图在上下文 2d 中构建一个带有文本的圆弧作为圆角矩形,但是文本在它下面并且被隐藏了,另外,圆弧的填充样式被文本。这是我得到的和我想要的:
这是带有代码的 js fiddle:https://jsfiddle.net/abhishek_soni/vzs6dLy9/19/
这是相同的代码:
Html代码:
<canvas></canvas>
Js代码:
var roundRect = function(ctx, x, y, w, h, r) {
var x2 = x + w;
var y2 = y + h;
if (w < 2 * r) r = w / 2;
if (h < 2 * r) r = h / 2;
ctx.beginPath();
ctx.moveTo(x + r, y);
ctx.arcTo(x2, y, x2, y2, r);
ctx.arcTo(x2, y2, x, y2, r);
ctx.arcTo(x, y2, x, y, r);
ctx.arcTo(x, y, x2, y, r);
};
var canvas = document.querySelector('canvas');
var context = canvas.getContext('2d');
context.save();
roundRect(context, 0, 0, 50, 60, 20);
context.fillStyle = 'red'; // This should work, but it doesn't
context.fill();
context.restore();
context.fillStyle = 'green';
context.fillText('Hey', 50, 80) // if I change this to 50 it hides behind the arc, which I don't want.
context.textAlign = "center";
context.fill();
context.save();
roundRect(context, 100, 100, 50, 90, 20);
context.fillStyle = 'red'; // This should work, but it doesn't
context.fill();
context.restore();
context.fillStyle = 'green';
context.fillText('Hey', 90, 100) // if I change this to 50 it hides behind the arc, which I don't want.
context.textAlign = "center";
context.fill();
context.save();
roundRect(context, 300, 100, 50, 120, 20);
context.fillStyle = 'red'; // This should work, but it doesn't
context.fill();
context.restore();
context.fillStyle = 'green';
context.fillText('Hey', 90, 130) // if I change this to 50 it hides behind the arc, which I don't want.
context.textAlign = "center";
context.fill();
问题是您在创建不需要的文本后调用 fill()
。 fill()
应用于之前绘制的形状。 fillText()
和 fillRect()
等方法的目的是让您无需在之后调用 fill()
即可进行绘制。
不要在文本后调用 fill 并且它有效。
接下来要将文本对齐到形状的中心,我会计算中心并将文本放置在那里,然后使用 context.textAlign = 'center';
将其居中。
这是一个例子
var canvas = document.querySelector('canvas');
var context = canvas.getContext('2d');
canvas.width = innerWidth;
canvas.height = innerHeight;
let center = {}
var roundRect = function(ctx, x, y, w, h, r) {
var x2 = x + w;
var y2 = y + h;
center = {x: x + w/2, y: y + h/2}
if (w < 2 * r) r = w / 2;
if (h < 2 * r) r = h / 2;
ctx.beginPath();
ctx.moveTo(x + r, y);
ctx.arcTo(x2, y, x2, y2, r);
ctx.arcTo(x2, y2, x, y2, r);
ctx.arcTo(x, y2, x, y, r);
ctx.arcTo(x, y, x2, y, r);
ctx.closePath();
};
context.fillStyle = 'red';
roundRect(context, 0, 0, 50, 60, 20);
context.fill();
context.fillStyle = 'green';
context.textAlign = 'center';
context.fillText('Hey', center.x, center.y);
context.textAlign = "center";
context.fillStyle = 'red';
roundRect(context, 100, 100, 50, 90, 20);
context.fill();
context.fillStyle = 'green';
context.textAlign = 'center';
context.fillText('Hey', center.x, center.y)
context.textAlign = "center";
context.fillStyle = 'red';
roundRect(context, 300, 100, 50, 120, 20);
context.fill();
context.fillStyle = 'green';
context.textAlign = 'center';
context.fillText('Hey', center.x, center.y);
context.textAlign = "center";
<canvas id="canvas"></canvas>
我还将添加一个使用 class 的示例来执行此操作。与其他方法相比,我更喜欢这种方法。如果你不需要不同的颜色形状,你可以去掉 color 参数。如果您想要不同颜色的文本,您可以为此添加一个。
var canvas = document.querySelector("canvas");
var ctx = canvas.getContext("2d");
canvas.width = innerWidth;
canvas.height = innerHeight;
class roundRect {
constructor(x, y, w, h, r, c) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.x2 = this.x + this.w;
this.y2 = this.y + this.h;
this.center = { x: x + w / 2, y: y + h / 2 };
this.r = r;
this.color = c;
}
drawShape() {
if (this.w < 2 * this.r) this.r = this.w / 2;
if (this.h < 2 * this.r) this.r = this.h / 2;
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.moveTo(this.x + this.r, this.y);
ctx.arcTo(this.x2, this.y, this.x2, this.y2, this.r);
ctx.arcTo(this.x2, this.y2, this.x, this.y2, this.r);
ctx.arcTo(this.x, this.y2, this.x, this.y, this.r);
ctx.arcTo(this.x, this.y, this.x2, this.y, this.r);
ctx.closePath();
ctx.fill();
}
drawText() {
ctx.fillStyle = 'green';
ctx.textAlign = "center";
ctx.textBaseline = 'middle';
ctx.fillText("Hey", this.center.x, this.center.y);
}
}
let rect1 = new roundRect(0, 0, 50, 60, 20, 'red', 'Text')
let rect2 = new roundRect(60, 0, 50, 80, 20, 'lightblue', 'Text')
let rect3 = new roundRect(120, 0, 50, 100, 20, 'lightgreen', 'Text')
rect1.drawShape();
rect1.drawText();
rect2.drawShape();
rect2.drawText();
rect3.drawShape();
rect3.drawText();
<canvas id="canvas"></canvas>
编辑:
要旋转您的文本,请使用以下方法。
var canvas = document.querySelector('canvas');
var context = canvas.getContext('2d');
canvas.width = innerWidth;
canvas.height = innerHeight;
let center = {}
var roundRect = function(ctx, x, y, w, h, r) {
var x2 = x + w;
var y2 = y + h;
center = {x: x + w/2, y: y + h/2}
if (w < 2 * r) r = w / 2;
if (h < 2 * r) r = h / 2;
ctx.beginPath();
ctx.moveTo(x + r, y);
ctx.arcTo(x2, y, x2, y2, r);
ctx.arcTo(x2, y2, x, y2, r);
ctx.arcTo(x, y2, x, y, r);
ctx.arcTo(x, y, x2, y, r);
ctx.closePath();
};
context.fillStyle = 'red';
roundRect(context, 0, 0, 50, 60, 20);
context.fill();
context.fillStyle = 'green';
context.textAlign = 'center';
context.fillText('Hey', center.x, center.y);
context.textAlign = "center";
context.fillStyle = 'red';
roundRect(context, 100, 100, 50, 90, 20);
context.fill();
context.fillStyle = 'green';
context.textAlign = 'center';
context.textBaseline = 'middle';
context.save() //save before you transform something
context.translate(center.x, center.y) //use this to position
context.rotate(degToRad(90)) //rotate here using degrees
context.fillText('Hey', 0, 0) //draw this a (0, 0)
context.fillStyle = 'lightblue'; //delete this
context.fillRect(0, 0, canvas.width, canvas.height) //and this
context.restore() //restore when done with all objects you want affected
context.textAlign = "center";
context.fillStyle = 'red';
roundRect(context, 300, 100, 50, 120, 20);
context.fill();
context.fillStyle = 'green';
context.textAlign = 'center';
context.fillText('Hey', center.x, center.y);
context.textAlign = "center";
function degToRad(deg) {
return deg * (Math.PI/180)
}
<canvas id="canvas"></canvas>
所以我试图在上下文 2d 中构建一个带有文本的圆弧作为圆角矩形,但是文本在它下面并且被隐藏了,另外,圆弧的填充样式被文本。这是我得到的和我想要的:
这是带有代码的 js fiddle:https://jsfiddle.net/abhishek_soni/vzs6dLy9/19/
这是相同的代码:
Html代码:
<canvas></canvas>
Js代码:
var roundRect = function(ctx, x, y, w, h, r) {
var x2 = x + w;
var y2 = y + h;
if (w < 2 * r) r = w / 2;
if (h < 2 * r) r = h / 2;
ctx.beginPath();
ctx.moveTo(x + r, y);
ctx.arcTo(x2, y, x2, y2, r);
ctx.arcTo(x2, y2, x, y2, r);
ctx.arcTo(x, y2, x, y, r);
ctx.arcTo(x, y, x2, y, r);
};
var canvas = document.querySelector('canvas');
var context = canvas.getContext('2d');
context.save();
roundRect(context, 0, 0, 50, 60, 20);
context.fillStyle = 'red'; // This should work, but it doesn't
context.fill();
context.restore();
context.fillStyle = 'green';
context.fillText('Hey', 50, 80) // if I change this to 50 it hides behind the arc, which I don't want.
context.textAlign = "center";
context.fill();
context.save();
roundRect(context, 100, 100, 50, 90, 20);
context.fillStyle = 'red'; // This should work, but it doesn't
context.fill();
context.restore();
context.fillStyle = 'green';
context.fillText('Hey', 90, 100) // if I change this to 50 it hides behind the arc, which I don't want.
context.textAlign = "center";
context.fill();
context.save();
roundRect(context, 300, 100, 50, 120, 20);
context.fillStyle = 'red'; // This should work, but it doesn't
context.fill();
context.restore();
context.fillStyle = 'green';
context.fillText('Hey', 90, 130) // if I change this to 50 it hides behind the arc, which I don't want.
context.textAlign = "center";
context.fill();
问题是您在创建不需要的文本后调用 fill()
。 fill()
应用于之前绘制的形状。 fillText()
和 fillRect()
等方法的目的是让您无需在之后调用 fill()
即可进行绘制。
不要在文本后调用 fill 并且它有效。
接下来要将文本对齐到形状的中心,我会计算中心并将文本放置在那里,然后使用 context.textAlign = 'center';
将其居中。
这是一个例子
var canvas = document.querySelector('canvas');
var context = canvas.getContext('2d');
canvas.width = innerWidth;
canvas.height = innerHeight;
let center = {}
var roundRect = function(ctx, x, y, w, h, r) {
var x2 = x + w;
var y2 = y + h;
center = {x: x + w/2, y: y + h/2}
if (w < 2 * r) r = w / 2;
if (h < 2 * r) r = h / 2;
ctx.beginPath();
ctx.moveTo(x + r, y);
ctx.arcTo(x2, y, x2, y2, r);
ctx.arcTo(x2, y2, x, y2, r);
ctx.arcTo(x, y2, x, y, r);
ctx.arcTo(x, y, x2, y, r);
ctx.closePath();
};
context.fillStyle = 'red';
roundRect(context, 0, 0, 50, 60, 20);
context.fill();
context.fillStyle = 'green';
context.textAlign = 'center';
context.fillText('Hey', center.x, center.y);
context.textAlign = "center";
context.fillStyle = 'red';
roundRect(context, 100, 100, 50, 90, 20);
context.fill();
context.fillStyle = 'green';
context.textAlign = 'center';
context.fillText('Hey', center.x, center.y)
context.textAlign = "center";
context.fillStyle = 'red';
roundRect(context, 300, 100, 50, 120, 20);
context.fill();
context.fillStyle = 'green';
context.textAlign = 'center';
context.fillText('Hey', center.x, center.y);
context.textAlign = "center";
<canvas id="canvas"></canvas>
我还将添加一个使用 class 的示例来执行此操作。与其他方法相比,我更喜欢这种方法。如果你不需要不同的颜色形状,你可以去掉 color 参数。如果您想要不同颜色的文本,您可以为此添加一个。
var canvas = document.querySelector("canvas");
var ctx = canvas.getContext("2d");
canvas.width = innerWidth;
canvas.height = innerHeight;
class roundRect {
constructor(x, y, w, h, r, c) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.x2 = this.x + this.w;
this.y2 = this.y + this.h;
this.center = { x: x + w / 2, y: y + h / 2 };
this.r = r;
this.color = c;
}
drawShape() {
if (this.w < 2 * this.r) this.r = this.w / 2;
if (this.h < 2 * this.r) this.r = this.h / 2;
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.moveTo(this.x + this.r, this.y);
ctx.arcTo(this.x2, this.y, this.x2, this.y2, this.r);
ctx.arcTo(this.x2, this.y2, this.x, this.y2, this.r);
ctx.arcTo(this.x, this.y2, this.x, this.y, this.r);
ctx.arcTo(this.x, this.y, this.x2, this.y, this.r);
ctx.closePath();
ctx.fill();
}
drawText() {
ctx.fillStyle = 'green';
ctx.textAlign = "center";
ctx.textBaseline = 'middle';
ctx.fillText("Hey", this.center.x, this.center.y);
}
}
let rect1 = new roundRect(0, 0, 50, 60, 20, 'red', 'Text')
let rect2 = new roundRect(60, 0, 50, 80, 20, 'lightblue', 'Text')
let rect3 = new roundRect(120, 0, 50, 100, 20, 'lightgreen', 'Text')
rect1.drawShape();
rect1.drawText();
rect2.drawShape();
rect2.drawText();
rect3.drawShape();
rect3.drawText();
<canvas id="canvas"></canvas>
编辑:
要旋转您的文本,请使用以下方法。
var canvas = document.querySelector('canvas');
var context = canvas.getContext('2d');
canvas.width = innerWidth;
canvas.height = innerHeight;
let center = {}
var roundRect = function(ctx, x, y, w, h, r) {
var x2 = x + w;
var y2 = y + h;
center = {x: x + w/2, y: y + h/2}
if (w < 2 * r) r = w / 2;
if (h < 2 * r) r = h / 2;
ctx.beginPath();
ctx.moveTo(x + r, y);
ctx.arcTo(x2, y, x2, y2, r);
ctx.arcTo(x2, y2, x, y2, r);
ctx.arcTo(x, y2, x, y, r);
ctx.arcTo(x, y, x2, y, r);
ctx.closePath();
};
context.fillStyle = 'red';
roundRect(context, 0, 0, 50, 60, 20);
context.fill();
context.fillStyle = 'green';
context.textAlign = 'center';
context.fillText('Hey', center.x, center.y);
context.textAlign = "center";
context.fillStyle = 'red';
roundRect(context, 100, 100, 50, 90, 20);
context.fill();
context.fillStyle = 'green';
context.textAlign = 'center';
context.textBaseline = 'middle';
context.save() //save before you transform something
context.translate(center.x, center.y) //use this to position
context.rotate(degToRad(90)) //rotate here using degrees
context.fillText('Hey', 0, 0) //draw this a (0, 0)
context.fillStyle = 'lightblue'; //delete this
context.fillRect(0, 0, canvas.width, canvas.height) //and this
context.restore() //restore when done with all objects you want affected
context.textAlign = "center";
context.fillStyle = 'red';
roundRect(context, 300, 100, 50, 120, 20);
context.fill();
context.fillStyle = 'green';
context.textAlign = 'center';
context.fillText('Hey', center.x, center.y);
context.textAlign = "center";
function degToRad(deg) {
return deg * (Math.PI/180)
}
<canvas id="canvas"></canvas>