Javascript 如何创建低内存消耗的快照到网格画布系统HTML+;JS?
我试图做的(我已经能够完成,但性能很差)是在画布上应用一种网格,以便能够从用户那里获取关于原点位置的输入。收到输入后,通过键盘提供“绘制”坐标 这几天我所做的就是计算画布的宽度和高度,然后除以一个标准的20x20正方形的面积(用px表示)。通过这种方式,我可以在结果上循环并创建n个正方形,我将在网格元素内的display flex中渲染这些正方形。然后这个网格元素被应用到画布上 一切正常,但是有很多div,如果用户选择将div缩小到10x10,那么,这将对性能产生很大影响。。。所以我想找到一个更轻松的方法来做这件事 我考虑过在两个div中使用HR元素,这两个div将应用于画布上。一个div在列中显示元素,另一个在行中显示元素。这样我应该获得网格,但是快照呢?我如何检测两个HR元素的交点,并使用该确切点作为位置 我无法在画布上直接绘制网格的原因是,这应该尽可能保持“纯净”。仅包含用户的最终绘图 以下是“非优化”代码: 我使用Angular 5作为框架Javascript 如何创建低内存消耗的快照到网格画布系统HTML+;JS?,javascript,html,css,canvas,Javascript,Html,Css,Canvas,我试图做的(我已经能够完成,但性能很差)是在画布上应用一种网格,以便能够从用户那里获取关于原点位置的输入。收到输入后,通过键盘提供“绘制”坐标 这几天我所做的就是计算画布的宽度和高度,然后除以一个标准的20x20正方形的面积(用px表示)。通过这种方式,我可以在结果上循环并创建n个正方形,我将在网格元素内的display flex中渲染这些正方形。然后这个网格元素被应用到画布上 一切正常,但是有很多div,如果用户选择将div缩小到10x10,那么,这将对性能产生很大影响。。。所以我想找到一个更
<div class="draw-zone" #drawZone>
<div class="grid" #grid [ngClass]="{'activated': activateDrawZones}">
<div *ngFor="let block of gridBlocks" class="grid-block" [ngClass]="{'show': showGrid, 'ten-x-ten': blockSize === 10, 'twe-x-twe': blockSize === 20, 'thr-x-thr': blockSize === 30, 'fou-x-fou': blockSize === 40}"
#gridBlock (click)="draw($event, gridBlock)"></div>
</div>
<canvas #canvas [height]="canvasSize.y" [width]="canvasSize.x"></canvas>
</div>
将组件方法用于校准:
如您所见,我正在画布元素上应用“.grid”元素。网格元素包含以灵活模式显示的所有块。如您所见,网格容器具有display:flex和flex wrap:wrap属性。这样,当用户在块上单击时,我可以通过获取其相对于父块的位置来猜测x,y坐标。与画布具有相同的尺寸。一旦有了x,y坐标,我就可以在画布上画图了。是的,创建大量DOM元素并尝试使用javascript动态定位和调整它们的大小不会特别有效。我认为
hr
元素不会为您解决这个问题
首先,您是否考虑过直接在画布上绘制网格
另一个选择是在画布后面有一个背景图像,上面有网格。这将自动调整大小,性能与网页的任何其他方面一样
现在是“捕捉”部分。看起来您已经知道了如何在画布上绘制所需内容,一旦您获得了所需的网格信息。您需要的是一个方法来获取用户单击的网格。我猜这就是为什么你要覆盖所有的div 相反,画布本机跟踪鼠标单击。使用一些列出的技术应该能够获得您正在寻找的网格交互信息
编辑:生成和查找网格的方法:
var高度=100;
var宽度=200;
var水平网格=8;
垂直网格=4;
函数边界网格(长度、网格、x){
var部门=[];
可变网格宽度=长度/网格;
对于(i=0;i x){
分区推送((i-1)*网格宽度);
分区。推送(i*网格宽度);
打破
}
否则如果(i*网格宽度==x){
分区。推送(i*网格宽度);
打破
}
}
否则{
分区。推送(i*网格宽度);
}
}
返回分区;
}
log(“获取所有x和y网格线位置”);
console.log(边界网格(宽度、水平网格));
控制台日志(边界网格1d(高度、垂直网格));
log(“获取坐标(60,30)周围的x和y网格线位置”);
console.log(边界网格1d(宽度,水平网格,60));
控制台日志(边界网格1d(高度,垂直网格,30))代码>一些代码对于理解您要做的事情很有用。另外,您所说的“在网格元素内的display flex中渲染”是什么意思?渲染的确切含义是什么?你只是想画网格线吗?有什么原因不能直接在画布上绘制它吗?对不起,我已经试着更好地解释了,还提供了一些代码:)正如你所说,我正在尝试绘制一个网格,我可以在用户光标单击时使用它来“捕捉”用户光标。然后使用单击的块数据计算相对于父对象的x、y坐标。然后在画布上画画。正如我在编辑中所说的,画布应该尽可能保持干净。那么除了检查div是否被单击之外,您对div做了其他任何事情吗?您也可以在画布上添加一个单击侦听器,并使用一些基本的数学计算所需的位置,而无需重新填充div。感谢您的建议,我已经在阅读:)我有一个问题,让我们假设在画布上绘制此网格,并将绘制坐标保留在一个单独的对象中。然后,我可以使用该网格来检测对每个单独的“网格正方形”的点击,我倾向于动态生成我的坐标。然后我可以动态地确定需要多少网格。编写函数应该很容易,因为它可以返回坐标序列,或者返回给定坐标的最近网格坐标。让我在回答中给你举个例子。。。
.draw-zone{
flex-grow: 2;
height: 100%;
position: relative;
canvas{
z-index: 10;
}
.grid{
top: 0;
left: 0;
z-index: 11;
width: 100%;
display: flex;
flex-wrap: wrap;
overflow: hidden;
position: absolute;
margin-left: -.1rem;
border-radius: .5rem;
align-content: stretch;
border: 1px solid transparent;
&.activated{
border-color: #3f51b5;
}
.grid-block{
opacity: 0;
border-right: 1px solid #3f51b5;
border-bottom: 1px solid #3f51b5;
&.show{
opacity: .1;
}
&:hover{
opacity: 1;
border-radius: 50%;
background-color: #3f51b5;
transform: scale(1.2);
}
&.ten-x-ten{
width: 10px;
height: 10px;
}
&.twe-x-twe{
width: 20px;
height: 20px;
}
&.thr-x-thr{
width: 30px;
height: 30px;
}
&.fou-x-fou{
width: 40px;
height: 40px;
}
}
}
private calculateGrid() {
this.activateDrawZones = false;
this.canvasSize.x = this._drawZone.nativeElement.clientWidth;
this.canvasSize.y = this._drawZone.nativeElement.clientHeight;
const blocksCount = (this.canvasSize.x * this.canvasSize.y) / (this.blockSize * this.blockSize);
this.gridBlocks = [];
for (let i = 0; i < blocksCount; i++) {
this.gridBlocks.push({ size: this.blockSize });
}
this.activateDrawZones = true;
}
public draw(e: MouseEvent, block: HTMLDivElement, returnOnFail?: boolean) {
const x = block.offsetLeft + (this.blockSize / 2);
const y = block.offsetTop + (this.blockSize / 2);
if (this.firstClick) {
this.ctx.beginPath();
this.ctx.moveTo(x, y);
this.setCrosshair(x, y);
this.firstClick = false;
this.addPathToDrawSequence(x, y);
return;
}
if (this.isNotOnTheSameAxisAsTheLastInsert(x, y)) {
if (returnOnFail) { return; }
this.toggleDrawDirection();
this.draw(e, block, true);
return;
}
this.ctx.lineTo(x, y);
this.ctx.stroke();
this.setCrosshair(x, y);
this.addPathToDrawSequence(x, y);
}