JS Canvas 中的栅格图层
Posted
技术标签:
【中文标题】JS Canvas 中的栅格图层【英文标题】:Raster Layers in JS Canvas 【发布时间】:2015-07-31 22:08:52 【问题描述】:我需要你的帮助来做一个带有图层的小油漆应用程序。 我希望我的程序能够处理不同的图层,但不要使用多个画布或使用外部库,以便更多地了解整个画布的工作原理。 我考虑将每个数据存储在位于不同图层对象的数组中,然后将它们从最低到最高打印在画布上。问题是我想用手绘画,而不仅仅是圆形和正方形。如果我会记住我用手画的所有东西,那么它会很慢(已经尝试过)。 谢谢大家的帮助!
【问题讨论】:
那么,您的具体编程问题是什么? 【参考方案1】:您当然可以只使用一个画布来应用非正式的 z-index。
您已经确定了一种正确的方法:
序列化(“记住”)所有绘图命令和参数。 清除画布。 以正确的顺序重绘每一层上的所有折线。然后您可以重播那些保存的命令。显示将很快发生。
这是您的 Layer.draw
方法的一个版本,它已经过重构以获得更好的性能:
// draw() will define & stroke all polylines on this layer
// The 1st point in each polyline contains that line's styling
Layer.prototype.draw = function( ctx )
// just return if there's no points to draw
if(this.points.length<2)return;
// cache an often used array
var pts=this.points;
// index for points
var i=0;
// process all points in the
while(i<pts.length)
// cache the often used first point in a new polyline
var p=pts[i];
// set styles for this polyline
ctx.lineWidth = p.lineWidth;
ctx.lineJoin = p.lineJoin;
ctx.lineCap = p.lineCap;
ctx.strokeStyle = p.strokeStyle;
// begin this polyline path
ctx.beginPath();
ctx.moveTo(p.x, p.y);
i++;
// define all segment points on this polyline
while( i<pts.length && pts[i].lineWidth==undefined )
ctx.lineTo( pts[i].x , pts[i].y );
i++;
// stroke this polyline
ctx.stroke();
// end while(i<pts.length)
这是示例代码和演示:
Point = function( x , y )
this.x = x;
this.y = y;
Point.prototype.invert = function()
var t = this.x;
this.x = this.y;
this.y = t;
Layer = function()
this.points = [];
Layer.prototype.draw = function( ctx )
// just return if there's no points to draw
if(this.points.length<2)return;
// cache an often used array
var pts=this.points;
// index for points
var i=0;
// process all points in the
while(i<pts.length)
// cache the often used first point in a new polyline
var p=pts[i];
// set styles for this polyline
ctx.lineWidth = p.lineWidth;
ctx.lineJoin = p.lineJoin;
ctx.lineCap = p.lineCap;
ctx.strokeStyle = p.strokeStyle;
// begin this polyline path
ctx.beginPath();
ctx.moveTo(p.x, p.y);
i++;
// define all segment points on this polyline
while( i<pts.length && pts[i].lineWidth==undefined )
ctx.lineTo( pts[i].x , pts[i].y );
i++;
// stroke this polyline
ctx.stroke();
// end while(i<pts.length)
ExtendedPoint = function( x , y , style )
this.x = x;
this.y = y;
this.lineWidth = style.lineWidth;
this.lineJoin = style.lineJoin;
this.lineCap = style.lineCap;
this.strokeStyle = style.strokeStyle;
function startLine( e )
var x = e.clientX - canvas.offsetLeft;
var y = e.clientY - canvas.offsetTop;
var p = new ExtendedPoint( x , y ,
lineWidth: 5,
lineJoin: "round",
lineCap: "round",
// testing only: make each new polyline a different color
// strokeStyle: "black"
strokeStyle: randomColor(),
);
selectedLayer.points.push(p);
isDrawing = true;
function continueLine( e )
if (isDrawing == true)
var x = e.clientX - canvas.offsetLeft;
var y = e.clientY - canvas.offsetTop;
var p = new Point( x , y );
selectedLayer.points.push( p );
function endLine()
isDrawing = false;
function redraw()
context.clearRect( 0, 0, 400, 400 );
for ( var i = 0 ; i < layers.length ; i++ )
layers[i].draw( context );
var canvas = document.getElementById("cvs");
canvas.setAttribute("width" , 400);
canvas.setAttribute("height", 400);
var context = canvas.getContext("2d");
var layers = [];
layers.push( new Layer() );
var selectedLayer = layers[0];
var isDrawing = false;
canvas.addEventListener( "mousedown" , startLine );
canvas.addEventListener( "mousemove" , continueLine );
canvas.addEventListener( "mousemove" , redraw );
canvas.addEventListener( "mouseup" , endLine );
// testing only: make each polyline a different color
function randomColor()
return('#'+Math.floor(Math.random()*16777215).toString(16));
body background-color: ivory;
canvasborder:1px solid red;
<h4>Drag to draw layered lines</h4>
<canvas id="cvs" width=400 height=400></canvas>
【讨论】:
您好,感谢您的回答。我以前做过,这是一个小提琴(刚刚创建它)jsfiddle.net/drago96/4gq011yx这就是为什么我说这很慢,也许是我的错或者我没有很好地表达我的想法......(对不起语言,我我不是英语) 非常感谢,它真的很好用!没想到缓存积分会这么快! (可能只是中风功能只运行了几次)。我还考虑过使用三个画布(一个用于所选图层顶部的图层,一个用于所选图层上的绘画,另一个用于后面的图层)。比我将所有图层保存为使用 drawImage() 方法绘制的图像。当我完成编程后,我也会在这里放一个这个版本的小提琴。非常感谢!再见! 完成了另一个想法。这是小提琴jsfiddle.net/drago96/4gq011yx/3以上是关于JS Canvas 中的栅格图层的主要内容,如果未能解决你的问题,请参考以下文章
Android UICanvas 画布 ③ ( Canvas 图层栈 | Canvas#saveLayer() 新建图层 | Canvas 状态栈保存信息标志位 )