我试图在全局对象中存储画布引用,然后将该引用应用于元素而不是重新生成画布。这是我现有的代码。我希望这是有道理的。提前谢谢!
假设波形缓存是全局
var cL = document.getElementById('track' + trackId + 'WaveformL');
var cR = document.getElementById('track' + trackId + 'WaveformR');
if (waveformCache.hasOwnProperty(track.path))
{
var waveformCacheItem = waveformCache[track.path];
if (waveformCacheItem.hasOwnProperty('left'))
{
// restore canvas data here to cL element
}
}
else
{
waveformCache[track.path] = {};
var left = track.data.getChannelData(0);
var ctx1 = cL.getContext('2d');
ctx1.save();
ctx1.strokeStyle = 'rgb(49,73,11)';
ctx1.translate(0, 55/2); //centers where the line drawing starts horizontally
for(var i = 0; i < left.length; i += 200) {
var x1 = Math.floor(track.waveformLength * i / left.length); //first parameter affects the length of the drawn waveform #ZOOM
var y1 = left[i] * 55/2;
ctx1.beginPath();
ctx1.moveTo(x1, 0);
ctx1.lineTo(x1 + 1, y1);
ctx1.stroke();
}
ctx1.restore();
waveformCache[track.path].left = ctx1;
}
答案 0 :(得分:1)
如何序列化html5画布的概述CanvasRendingContext2D
画布上下文(CanvasRendingContext2D)保存画布&#39;属性(样式,当前转换等)。
重要!上下文不包含创建画布内容的所有已执行绘图命令。 上下文属性:
着色: strokeStyle,fillStyle(1),globalAlpha,
线条样式: lineWidth,lineCap,lineJoin,miterLimit,
文字样式:字体,textAlign,textBaseline,
合成: globalCompositeOperation,
阴影: shadowColor,shadowBlur,shadowOffsetX,shadowOffsetY
(1)fillStyle
通常是一个字符串(&#39;#ff0000&#39;),但它也可以保存对渐变对象或图案对象的引用。要保存上下文的fillStyle,您必须忽略渐变/模式或者序列化渐变/模式属性。
以下是如何将上下文属性保存到对象中
var properties=['strokeStyle','lineWidth','font','globalAlpha',
'globalCompositeOperation','shadowColor','shadowBlur',
'shadowOffsetX','shadowOffsetY','lineCap','lineJoin',
'miterLimit','textAlign','textBaseline'];
var serializedContext={}
for(var i=0;i<properties.length;i++){
var prop=properties[i];
serializedContext[prop]=context[prop];
}
// fillStyle can be a headache
if(typeof context.fillStyle === 'string'){
serializedContext['fillStyle']=context.fillStyle;
}else{
// do lots more work to serialize gradient or pattern :-O
}
以下是如何将已保存的上下文属性复制到新上下文中:
var context=myOtherCanvas.getContext('2d');
for(var i=0;i<properties.length;i++){
var prop=properties[i];
context[prop]=serializedContext[prop];
}
// fillStyle can be a headache
if(typeof context.fillStyle === 'string'){
serializedContext['fillStyle']=context.fillStyle;
}else{
// do lots more work to re-establish gradient or pattern :-O
}
重新执行图纸
如果要重新执行所有绘图命令,则必须保存命令及其参数。
从您的示例代码中,您的绘图看起来像涉及线段(moveTo
&amp; lineTo
),因此您可以将每个段保存为段对象数组中的段对象。 / p>
var segments=[];
segments.push({moveX:10, moveY:20, lineX:100, lineY:35});
... and push all the other line segments
然后你可以&#34;重播&#34;重置所有上下文属性后的线段绘制命令:
// redraw every line segment
ctx.beginPath()
for(var i=0;i<segments.length;i++){
var s=segments[i];
ctx.moveTo(s.moveX,s.moveY);
ctx.lineTo(s.lineX,s.lineY);
}
ctx.stroke();
您还可以序列化和重放所有常见的绘图命令(arc,beginPath,bezierCurveTo,clearRect,clip,closePath,fill,fillRect,fillText,lineTo,moveTo,quadraticCurveTo,rect,restore,rotate,save,scale,setTransform ,stroke,strokeRect,strokeText,transform,translate)。保存每个命令名称&amp;对象中的关联参数,并将所有这些命令对象保存在数组中。
这些命令返回值,因此您需要做更多工作来处理它们: measureText,getImageData(putImageData),toDataURL,isPointInPath,isPointInStroke,createImageData,createLinearGradient,createRadialGradient,createPattern。幸运的是,这些命令的使用频率低于更常见(更简单)的命令。
关于可移植性
如果您使用此方法保存所有属性&amp;将命令绘制到对象数组中,您可以使用JSON.stringify
轻松地将它们序列化为JSON字符串,并且可以使用JSON.parse
轻松地将它们反序列化为对象数组。
拥有您的画布属性&amp;将序列化为字符串的绘图命令意味着您可以轻松地将它们传输到服务器进行存储,然后获取它们进行重放。
答案 1 :(得分:0)
您可以使用Path2D
object存储路径命令。然后将路径存储在全局对象中。当您需要重新应用路径时,只需使用存储的路径对象进行描边或填充。
例如:
var path = new Path2D();
...
path.moveTo(.. , ..);
path.lineTo(.. , ..);
etc.
稍后当您需要回忆路径时:
ctx.stroke(path);
(奖励是您可以使用SVG paths对其进行初始化。这意味着您可以使用SVG命令定义路径并将其存储为单个字符串。使用Path2D的路由重新应用,但性能略有下降在初始化时。)
Path2D
对于尚不支持它的浏览器可以是polyfilled(请参阅特殊情况说明)。