有没有更短的方法来编写canvas html的代码?我想尽可能避免使用图像

时间:2014-11-19 09:45:14

标签: javascript html5 canvas

如何在不重复上下文的情况下简化此代码?有没有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();

4 个答案:

答案 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;
&#13;
&#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>