如何在不重复上下文的情况下简化此代码?有没有canvas api的库? 我尝试使用with(context),但它会抛出一个错误,因为我正在使用'use strict'。这有什么办法吗?
context.save();
context.beginPath();
context.setTransform(1, 0, 0, 1, 0, 0);
context.translate(alien.x, alien.y);
context.rotate(0);
context.moveTo(-15, 0);
context.lineTo(-15, 5);
context.bezierCurveTo(-15, -10, 15, -10, 15, 5);
context.lineTo(15, 0);
context.lineTo(-15, 0);
context.lineTo(-15, 5);
context.lineTo(-20, 5);
context.lineTo(-25, 10);
context.lineTo(25, 10);
context.lineTo(20, 5);
context.lineTo(-20, 5);
context.moveTo(10, 10);
context.lineTo(10, 15);
context.lineTo(15, 15);
context.lineTo(15, 10);
context.moveTo(-10, 10);
context.lineTo(-10, 15);
context.lineTo(-15, 15);
context.lineTo(-15, 10);
context.strokeStyle = '#fff';
context.stroke();
context.closePath();
context.restore();
答案 0 :(得分:1)
编写一个包装器对象 - 使用它还可以缩短名称以及扩展功能,例如在调用笔划等的同时设置颜色和线宽。
更新:我还做了 this library (免费/ MIT),其中包含了上下文。
称呼他们你想要的东西 - 这些只是当然的例子。确保每个都返回允许链接的this
对象。如果您只计划使用单个实例,则可以将这些方法放在主对象中而不是使用原型:
function CTX(ctx) {
this.ctx = ctx;
};
CTX.prototype.move = function(x,y) {this.ctx.moveTo(x, y); return this};
CTX.prototype.line = function(x,y) {this.ctx.lineTo(x, y); return this};
CTX.prototype.bez = function(a,b,c,d,e,f,g) {
this.ctx.bezierTo(a,b,c,d,e,f,g);
return this;
};
// etc.
使用:只需使用此实例包装您的上下文:
var ctx = new CTX(context);
ctx .save()
.begin()
.setTrans(1, 0, 0, 1, 0, 0)
.trans(alien.x, alien.y)
.rot(0)
.move(-15, 0)
.line(-15, 5)
.bez(-15, -10, 15, -10, 15, 5)
.line(15, 0)
// etc.
function CTX(ctx) {
this.ctx = ctx;
};
CTX.prototype.begin = function() {
this.ctx.beginPath();
return this;
};
CTX.prototype.move = function(x, y) {
this.ctx.moveTo(x, y);
return this;
};
CTX.prototype.line = function(x, y) {
this.ctx.lineTo(x, y);
return this;
};
CTX.prototype.stroke = function(color) {
if (color) this.ctx.strokeStyle = color;
this.ctx.stroke();
return this;
};
// ... define more here
var ctx = new CTX(canvas.getContext('2d'));
ctx
.begin()
.move(20, 20)
.line(50, 50)
.line(80, 20)
.line(110, 50)
.stroke('#00f');
// etc.

<canvas id=canvas width=500 height=180></canvas>
&#13;
答案 1 :(得分:0)
Javascript没有方法链接的默认选项。 Jquery确实有这个选项,但没有使用默认的Canvas方法(尽管有一个jCanvas插件)。
我认为你最好的选择是编写一个方法,用一组参数执行一个方法,返回上下文,这样就可以模拟链接了:
//Call on the canvas
//methodname is a string with the methodname;
//arguments is a list of arguments
canvas.prototype.applyMethodToContext = function(methodname, arguments){
this[methodname].apply(this, arguments);
return context;
}
此方法完全未经测试,可能需要进行一些更改才能完全正常工作。如果您更喜欢使用经过测试的第三方解决方案(并且不要求将该方法作为字符串输入),则有人编写了一个允许画布链接的小型javascript文件(80行):https://github.com/millermedeiros/CanvasContext2DWrapper
答案 2 :(得分:0)
看看这些网站,它只为您创建一个简单的画布http://www.w3resource.com/html5/canvas-element.php
答案 3 :(得分:0)
这是使用类似SVG的语法简明地指定画布路径数据的一种方法。
我从一段时间后写过的SVGPath-to-CanvasPath交叉编译器中抽取了以下内容。关于SVG路径数据的好处是它非常短而且非常短。简洁。它使用单个字母来定义绘图命令,它将所有命令组合成一个字符串。
// Canvas path drawing commands represented by single command letters
M == moveTo
L == lineTo
Q == quadraticCurveTo
C == bezierCurveTo
R == rect
A == arc
Z == closePath
Y == clip
因此,您的复杂画布路径可以由一个短字符串表示,如下所示:
var data='M-15,0 L-15,5 C-15,-10,15,-10,15,5 L15,0 L-15,0 L-15,5 L-20,5 L-25,10 L25,10 L20,5 L-20,5 M10,10 L10,15 L15,15 L15,10 M-10,10 L-10,15 L-15,15 L-15,10';
以下是示例代码和解析&amp;将此data
字符串绘制到Canvas:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var commandExpander={
M: 'moveTo',
L: 'lineTo',
Q: 'quadraticCurveTo',
C: 'bezierCurveTo',
R: 'rect',
A: 'arc',
Z: 'closePath',
Y: 'clip'
}
// your path written as a single string
var data='M-15,0 L-15,5 C-15,-10,15,-10,15,5 L15,0 L-15,0 L-15,5 L-20,5 L-25,10 L25,10 L20,5 L-20,5 M10,10 L10,15 L15,15 L15,10 M-10,10 L-10,15 L-15,15 L-15,10';
// convert the single data string into separate commands
var commands=parseData(data);
// execute the drawing commands
definePath(commands);
// stroke the result
ctx.stroke();
// Take a single string containing path data
// Break it into separate commands and put all commands into an array
// One command consists of a letter and the command arguments
function parseData(data){
var commands=[];
var cmdSegments = data.match(/[a-z][^a-z]*/ig);
for(var i=0;i<cmdSegments.length;i++){
var segment=cmdSegments[i];
var command={letter:null,args:null};
commands.push(command);
command.letter=segment.slice(0,1);
command.args=segment
.slice(1)
.trim()
.replace(/-+/g,' -')
.trim()
.replace(/\s+/g,',')
.replace(/,+/g,',')
.split(",")
.filter(function(e){return e!==''});
for(var a=0;a<command.args.length;a++){
command.args[a]=Number(command.args[a]);
}
}
return(commands);
}
// execute all the commands in the cmds[] array
function definePath(cmds){
ctx.beginPath();
for(var i=0;i<cmds.length;i++){
var command=commandExpander[cmds[i].letter];
var args=cmds[i].args;
ctx[command].apply(ctx,args);
}
}
body{ background-color: ivory; padding:10px; }
#canvas{border:1px solid red;}
<canvas id="canvas" width=300 height=300></canvas>