[英]Canvas not showing some paths
当我的内部函数从%
等变量计算时,为什么我的路径有时不显示?
在开发简单的图形工具来创建可转换为图像的可填充模板时,我注意到有时我绘制的路径会根据它们的位置而消失。 这可以通过在某些点上添加0.02px
或Number.ESPSILON
来解决,但这并不是真正的解决方案。 为什么会这样?
有问题的代码:
// Starts with setting canvas
async setCanvas() {
this.$self.get.loading.style.display = '';
this.canvas = this.$self.get.canvas;
this.canvas.setAttribute('width', this.canvas.offsetWidth * this.$.scale)
this.canvas.setAttribute('height', this.canvas.offsetHeight * this.$.scale)
this.ctx = this.canvas.getContext("2d");
this.picture.x = this.decimal(((this.canvas.offsetWidth - this.$.width) / 2)*this.$.scale);
this.picture.y = this.decimal(((this.canvas.offsetHeight - this.$.height) / 2)*this.$.scale);
this.drawCanvas();
// Then we draw on it
await this.draw();
this.loaderDebouncer();
}
[...]
async draw() {
for(let i=0; i < this.$.layout.length; i++) {
const layout = this.$.layout[i];
Object.values(layout.inputs || {}).forEach(input => {
// this should not be relevant as is just integration of Form framework
if (!input.object) {
input.object = FormBuilder.sGenerateFieldItem(input.value || null);
this.setMain(input.value, layout, input);
}
});
await this.drawEntity(layout);
}
}
[...]
async drawEntity(entity) {
const types = {
image: e => this.drawImage(e),
rect: e => this.drawRect(e),
text: e => this.drawText(e),
polygon: e => this.drawPolygon(e), // <- draws the path
default: e => console.error('Not recognized type', e.type),
};
await (types[entity.type] || types.default)(entity);
}
// !! The relevant method!
async drawPolygon(entity) {
const data = entity.data,
path = await this.retrieveValue(data.path || [], entity),
{ width, height, left, top } = this.calculateSizeAndPos(entity),
x = this.decimal(this.picture.x + left),
y = this.decimal(this.picture.y + top);
this.ctx.save();
this.ctx.beginPath();
this.ctx.moveTo(x, y);
path.forEach(point => {
this.polygonFunction(x, y, point[0])(...point.slice(1));
});
this.ctx.fillStyle = this.fill(data.fill) || this.ctx.fillStyle;
this.ctx.fill();
this.ctx.closePath();
if (entity.custom) {
entity.custom(this.ctx);
}
if (entity.outline) {
const outline = entity.outline;
this.polygonFunction(x, y, 'stroke')(this.thickness(outline.thickness || 5), this.fill(outline.fill || '#000'));
}
this.ctx.restore();
}
polygonFunction(x, y, type) {
const fns = {
line: (lineX, lineY,) => {
lineX = this.decimal(x + this.calc(lineX, 'x')), lineY = this.decimal(y + this.calc(lineY, 'y'));
this.ctx.lineTo(lineX, lineY)
},
curve: (cp1x, cp1y, cp2x, cp2y, curveX, curveY) => {
cp1x = this.decimal(x + this.calc(cp1x, 'x'));
cp1y = this.decimal(y + this.calc(cp1y, 'y'));
cp2x = this.decimal(x + this.calc(cp2x, 'x'));
cp2y = this.decimal(y + this.calc(cp2y, 'y'));
curveX = this.decimal(x + this.calc(curveX, 'x'));
curveY = this.decimal(y + this.calc(curveY, 'y'));
this.ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, curveX, curveY);
},
stroke: (thickness, fill) => {
this.ctx.save();
this.ctx.strokeStyle = fill || '#000';
this.ctx.lineWidth = this.thickness(thickness, 5);
this.ctx.lineJoin = "round";
this.ctx.miterLimit = 2;
this.ctx.stroke();
this.ctx.restore();
},
default: () => fns.line(...arguments),
};
return fns[type] || fns.default
}
decimal(number, precision = 2) {
return +number.toFixed(precision);
}
retrieveValue(value, entity) {
if (typeof value == 'function') {
return value(entity, this.$.indexes, this);
}
return value;
}
calculateSizeAndPos(entity) {
return {
width: this.calc(entity.size?.w, 'x'),
height: this.calc(entity.size?.h, 'y'),
left: this.calc(entity.pos?.x, 'x'),
top: this.calc(entity.pos?.y, 'y')
}
}
用于消失路径的设置:
{
id: 'arrow',
label: 'Rune Position',
editable: true,
type: 'polygon',
pos: {
x: '42.5%',
y: '60%',
},
data: {
path: layer => {
if (layer.inputs.position.value == 0) {
layer.data.fill = '#FFF';
layer.outline.fill = '#000';
return [
['line', '1.5%', '2.5w%'],
['line', '-1.5%', '2.5w%'],
];
}
layer.data.fill = '#000';
layer.outline.fill = '#FFF';
return [
['line', '1.5%', '0'],
['line', '0', '2.5w%'],
['line', '-1.5%', '0'],
];
},
fill: '#FFF'
},
outline: {
fill: '#000',
thickness: .5,
},
inputs: {
position: {
type: 'select',
label: 'Rune Position',
options: [
['Top', '0'],
['Bottom', '1'],
],
value: '0',
inherited: null,
}
}
}
由于某种原因,在填充之前关闭路径使其消失(?)。 更改函数的顺序消除了所有实例上的这个问题。 从:
this.ctx.beginPath();
this.ctx.moveTo(x, y);
[...draw]
this.ctx.closePath();
this.ctx.fill();
this.ctx.stroke();
到:
this.ctx.beginPath();
this.ctx.moveTo(x, y);
[...draw]
this.ctx.fill();
this.ctx.closePath();
this.ctx.stroke();
关于路径的外观,它们应该保持不变,因为在不先调用closePath
情况下填充路径没有明显差异(检查此答案https://stackoverflow.com/a/72567642/11495586 )。
问题未解决?试试以下方法:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.