gpt4 book ai didi

javascript - 了解 canvas Clip() 如何影响多个动态创建的形状

转载 作者:行者123 更新时间:2023-12-03 11:20:16 25 4
gpt4 key购买 nike

我已经在我的第一个真正的 HTML5 Canvas 项目上工作了一段时间了,但我似乎无法让事情按照我的意愿排列。我最近遇到了 context.clip() 函数,它似乎有帮助,但有其他意想不到的后果,所以我想我应该把我的问题放在那里。

我的项目是一张六 Angular 形瓷砖 map ,其边界代表大陆和旅行路线。这是我的 map 的一张好照片:main map

我注意到,如果我在绘制每个六 Angular 形之前使用clip()函数,内部浅绿色六 Angular 形看起来不会那么偏离中心。这是一个特写比较:compare

问题是,当我使用这个clip()函数时,我似乎丢失了边框/路线覆盖。我的代码绘制了所有的六 Angular 形,然后绘制了粗边框,这样它们就不会被绘制在上面。 clipping kills my borders

我不确定我是否理解这里发生的事情。为什么 Clip() 会破坏我的边框?我的整个代码列表都在这个 github 存储库中:https://github.com/boknows/hex-map-game ,但我将在这里列出两个主要功能。 drawHexGrid() 进行数学运算以放置每个单独的十六进制,drawHex() 绘制具有适当填充的十六进制,drawHexBorders() 绘制之后的边框/路线。

HexagonGrid.prototype.drawHexGrid = function (rows, cols, originX, originY, isDebug) {
this.canvasOriginX = originX;
this.canvasOriginY = originY;
this.rows = rows;
this.cols = cols;
var currentHexX;
var currentHexY;
var debugText = "";
var offsetColumn = false;
var hexNum = 1;

for (var col = 0; col < cols; col++) {
for (var row = 0; row < rows; row++) {
if (!offsetColumn) {
currentHexX = (col * this.side) + originX;
currentHexY = (row * this.height) + originY;
} else {
currentHexX = col * this.side + originX;
currentHexY = (row * this.height) + originY + (this.height * 0.5);
}
if (isDebug) {
debugText = hexNum;
hexNum++;
}
if(map.data[row][col].type=="land"){
this.drawHex(currentHexX, currentHexY, "#99CC66", debugText, false, map.data[row][col].owner);
}else if(map.data[row][col].type=="water"){
this.drawHex(currentHexX, currentHexY, "#3333FF", "", false, map.data[row][col].owner);
}else if(map.data[row][col].type=="forest"){
this.drawHex(currentHexX, currentHexY, "#009900", debugText, false, map.data[row][col].owner);
}else if(map.data[row][col].type=="desert"){
this.drawHex(currentHexX, currentHexY, "#F5E8C1", debugText, false, map.data[row][col].owner);
}else if(map.data[row][col].type=="mountains"){
this.drawHex(currentHexX, currentHexY, "#996600", debugText, false, map.data[row][col].owner);
}
}
offsetColumn = !offsetColumn;

}
var offsetColumn = false;
for (var col = 0; col < cols; col++) { //Draw borders separately so they don't get overlapped by other graphics.
for (var row = 0; row < rows; row++) {
if (!offsetColumn) {
currentHexX = (col * this.side) + originX;
currentHexY = (row * this.height) + originY;
} else {
currentHexX = col * this.side + originX;
currentHexY = (row * this.height) + originY + (this.height * 0.5);
}
this.drawHexBorders(currentHexX, currentHexY);
}
offsetColumn = !offsetColumn;
}
};

HexagonGrid.prototype.drawHex = function (x0, y0, fillColor, debugText, highlight, highlightColor, owner) {
this.context.font="bold 12px Helvetica";
this.owner = owner;
this.context.strokeStyle = "#000000";
this.context.lineWidth = 1;
this.context.lineCap='round';

this.context.restore();
var tile = this.getSelectedTile(x0 + this.width - this.side, y0);
var numberOfSides = 6,
size = this.radius,
Xcenter = x0 + (this.width / 2),
Ycenter = y0 + (this.height / 2);
this.context.beginPath();
this.context.lineWidth = 1;
this.context.moveTo (Xcenter + size * Math.cos(0), Ycenter + size * Math.sin(0));
for (var i = 1; i <= numberOfSides;i += 1) {
this.context.lineTo (Xcenter + size * Math.cos(i * 2 * Math.PI / numberOfSides), Ycenter + size * Math.sin(i * 2 * Math.PI / numberOfSides));
}

if(typeof(map.data[tile.row][tile.column]) != "undefined"){
if (fillColor && highlight == false && map.data[tile.row][tile.column].type =="land") {
this.context.fillStyle = map.data[tile.row][tile.column].color;
}else{
this.context.fillStyle = fillColor;
}
}


if (highlight == true){
this.context.fillStyle = highlightColor;
}
this.context.fill();
this.context.closePath();
this.context.save();
this.context.clip();
this.context.lineWidth *= 2;
this.context.stroke();


if(map.data[tile.row][tile.column].type != "water"){
//Draw smaller hex inside bigger hex - v2
var numberOfSides = 6,
size = this.radius*0.7,
Xcenter = x0 + (this.width / 2),
Ycenter = y0 + (this.height / 2);
this.context.fillStyle = fillColor;
this.context.strokeStyle = map.data[tile.row][tile.column].color;
this.context.beginPath();
this.context.lineWidth = .5;
this.context.moveTo (Xcenter + size * Math.cos(0), Ycenter + size * Math.sin(0));
for (var i = 1; i <= numberOfSides;i += 1) {
this.context.lineTo (Xcenter + size * Math.cos(i * 2 * Math.PI / numberOfSides), Ycenter + size * Math.sin(i * 2 * Math.PI / numberOfSides));
}
this.context.fill();
this.context.closePath();
this.context.stroke();

//if defensive boost active, draw grey dotted hex inside of owners colored hex.
var index = 0;
for(var i=0;i<map.dataProp.users.length;i++){
if(map.dataProp.users[i]==map.data[tile.row][tile.column].owner){
index = i;
}
}
var defTrigger = false;
for(var i=0;i<map.dataProp.turnModifiers[index].length;i++){
if(map.dataProp.turnModifiers[index][i].type=="defensiveBoost"){
defTrigger = true;
}
}
if(defTrigger == true){
var numberOfSides = 6,
size = this.radius-12,
Xcenter = x0 + (this.width / 2),
Ycenter = y0 + (this.height / 2);
this.context.strokeStyle = "#929292"
this.context.beginPath();
this.context.lineWidth = 5;
this.context.moveTo (Xcenter + size * Math.cos(0), Ycenter + size * Math.sin(0));
for (var i = 1; i <= numberOfSides;i += 1) {
this.context.lineTo (Xcenter + size * Math.cos(i * 2 * Math.PI / numberOfSides), Ycenter + size * Math.sin(i * 2 * Math.PI / numberOfSides));
}
this.context.fill();
this.context.closePath();
this.context.stroke();
}


//Print number of units
this.context.textAlign="center";
this.context.textBaseline = "middle";
this.context.font = 'bold 13pt Arial';
//Code for contrasting text with background color
/*var clr = getContrastYIQ(map.data[tile.row][tile.column].color); //contrast against player color
var clr = getContrastYIQ(fillColor); //contrast against land color (fillColor)
this.context.fillStyle = clr;
*/
this.context.fillStyle = "#000000";
this.context.fillText(map.data[tile.row][tile.column].units, x0 + (this.width / 2) , y0 + (this.height / 2));
this.context.fillStyle = "";
}
};

HexagonGrid.prototype.drawHexBorders = function (x0, y0) {
var tile = this.getSelectedTile(x0 + this.width - this.side, y0);
if(map.data[tile.row][tile.column].s != ""){
this.context.beginPath();
this.context.lineWidth = 5;
this.context.strokeStyle=map.data[tile.row][tile.column].s;
this.context.moveTo(x0 + this.side, y0 + this.height);
this.context.lineTo(x0 + this.width - this.side, y0 + this.height);
this.context.stroke();
}
if(map.data[tile.row][tile.column].n != ""){

this.context.beginPath();
this.context.lineWidth = 5;
this.context.strokeStyle=map.data[tile.row][tile.column].n;
this.context.moveTo(x0 + this.side, y0);
this.context.lineTo(x0 + this.width - this.side, y0);
this.context.stroke();
}
if(map.data[tile.row][tile.column].ne != ""){
this.context.beginPath();
this.context.lineWidth = 5;
this.context.strokeStyle=map.data[tile.row][tile.column].ne;
this.context.moveTo(x0 + this.side, y0);
this.context.lineTo(x0 + this.width, y0 + (this.height / 2));
this.context.stroke();
}
if(map.data[tile.row][tile.column].se != ""){
this.context.beginPath();
this.context.lineWidth = 5;
this.context.strokeStyle=map.data[tile.row][tile.column].se;
this.context.moveTo(x0 + this.width, y0 + (this.height / 2));
this.context.lineTo(x0 + this.side, y0 + this.height);
this.context.stroke();
}
if(map.data[tile.row][tile.column].sw != ""){
this.context.beginPath();
this.context.lineWidth = 5;
this.context.strokeStyle=map.data[tile.row][tile.column].sw;
this.context.moveTo(x0 + this.width - this.side, y0 + this.height);
this.context.lineTo(x0, y0 + (this.height/2));
this.context.stroke();
}
if(map.data[tile.row][tile.column].nw != ""){
this.context.beginPath();
this.context.lineWidth = 5;
this.context.strokeStyle=map.data[tile.row][tile.column].nw;
this.context.moveTo(x0, y0 + (this.height/2));
this.context.lineTo(x0 + this.width - this.side, y0);
this.context.stroke();
}
};

//Recusivly step up to the body to calculate canvas offset.
HexagonGrid.prototype.getRelativeCanvasOffset = function() {
var x = 0, y = 0;
var layoutElement = this.canvas;
var bound = layoutElement.getBoundingClientRect();
if (layoutElement.offsetParent) {
do {
x += layoutElement.offsetLeft;
y += layoutElement.offsetTop;
} while (layoutElement = layoutElement.offsetParent);

return { x: bound.left, y: bound.top };
}
}

最佳答案

免责声明:我没有看过你的代码——你发布了很多代码! (Stackoverflow 鼓励您发布一个简化的代码片段来说明您的问题)。

但是您的问题可能是由于笔画的完成方式造成的吗?

笔画是在其定义的路径的一半内部和一半外部完成的。因此,如果您描画一个矩形,然后清除同一个矩形,您仍然会看到描边的一部分——您会看到描边的半外部部分。

// draw a stroked rect
context.strokeRect(10,10,30,30);

// clear the same rect
context.clearRect(10,10,30,30);

// the outside half of the stroke is still visible

相反,剪切将防止绘制笔划的半外部部分。也许您丢失的六 Angular 形边框是未绘制的半外侧笔画。

关于javascript - 了解 canvas Clip() 如何影响多个动态创建的形状,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27152052/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com