2013-09-04 2 views
1

Я пытаюсь практиковать с рисунком холста HTML5, поэтому я придумал это. Я должен привести к желтой звезде, которая наложила на зеленый силуэт бюста (голова и плечи человека).Html 5 проблема с холстом

Однако, если линия drawStar() не указана, зеленый силуэт не нарисован. Этот рабочий код не так важен, как объяснение того, что происходит.

http://jsfiddle.net/xiondark2008/LYfHJ/2/

HTML:

<!DOCTYPE html> 
<html> 
<head> 
    <style> 
    h6{ 
     -webkit-margin-before: .5em; 
     -webkit-margin-after: 0; 
    } 
    label{ 
     margin-left: 1em; 
    } 
    </style> 

</head> 
<body> 

    <canvas id="myCanvas" width="19" height="19" 
     style="border:1px solid d3d3d3;"> 
     Your browser does not support the HTML5 canvas tag.</canvas> 
</body> 
</html> 

JavaScript:

function drawProfile(ctx,x,y,width,height) { 
    this.flp = false; 
    this.x = function(r){ return Math.floor(width*(this.flp?1-r:r)); } 
    this.y = function(r){ return Math.floor(height*r); } 

    ctx.save(); 

    ctx.translate(x, y); 
    ctx.fillStyle="#40FF00"; 

    ctx.beginPath(); 
    ctx.moveTo(this.x(0), this.y(1)); 
    ctx.bezierCurveTo(
     this.x(0),  this.y(125/190), 
     this.x(70/190), this.y(170/190), 
     this.x(75/190), this.y(120/190) 
    ); 
    ctx.lineTo(this.x(95/190), this.y(130/190)); 
    ctx.bezierCurveTo(
     this.x(40/190), this.y(130/190), 
     this.x(30/190), this.y(0), 
     this.x(95/190), this.y(0) 
    ); 

    this.flp = true; 

    ctx.bezierCurveTo(
     this.x(30/190), this.y(0), 
     this.x(40/190), this.y(130/190), 
     this.x(95/190), this.y(130/190) 
    ); 
    ctx.lineTo(this.x(75/190), this.y(120/190)); 
    ctx.bezierCurveTo(
     this.x(70/190), this.y(170/190), 
     this.x(0), this.y(125/190), 
     this.x(0), this.y(1) 
    ); 
    ctx.fill(); 

    this.flp = false; 

    ctx.restore(); 
} 

function drawStar(ctx,x,y,height) { 

    var pnts = 5, 
     rad = height/(1-Math.cos(0.8*Math.PI)); 

    this.x = function(p,dst){ 
     return dst * Math.sin((p/pnts)*2*Math.PI); 
    } 
    this.y = function(p,dst){ 
     return dst * Math.cos((p/pnts)*2*Math.PI) * -1; 
    } 
    this.movePct = function(a,b,pct){ 
     var f = (function(x){ 
       var m = (b.y-a.y)/(b.x-a.x); 
       return m*x+(a.y-(a.x*m)); 
      }).bind(), 
      r = b.x - a.x, 
      point = {}; 

     point.x = a.x+(r*pct); 
     point.y = f(point.x); 

     return point; 
    } 
    this.transPoints = function(s,p,e,pct){ 
     var sp = this.movePct(s,p,pct), 
      ep = this.movePct(e,p,pct); 

     return [sp,ep]; 
    } 

    ctx.save(); 

    ctx.translate(x+rad, y+rad); 
    ctx.fillStyle = "#ffff00"; 

    ctx.beginPath(); 

    for(var i=0;i<pnts;i++){ 
     var dst = rad/2, 
      s = { x: this.x(i+0.5, dst), 
        y: this.y(i+0.5, dst) }, 
      p = { x: this.x(i+1, rad), 
        y: this.y(i+1, rad) }, 
      e = { x: this.x(i+1.5, dst), 
        y: this.y(i+1.5, dst) }, 
      t = this.transPoints(s,p,e,.75); 

     if(i==0){ ctx.moveTo(s.x, s.y); } 

     ctx.lineTo(t[0].x, t[0].y); 
     ctx.quadraticCurveTo(p.x, p.y, t[1].x, t[1].y); 
     ctx.lineTo(e.x, e.y); 
    } 
    ctx.fill(); 

    ctx.restore(); 

} 

function draw(c) { 

    var ctx = c.getContext("2d"); 

    this.x = function(r){ return c.width*r; } 
    this.y = function(r){ return c.height*r; } 

    ctx.shadowBlur=this.y(1/19); 
    ctx.shadowColor="black"; 

    //drawStar(ctx, this.x(-3/19), this.y(-1/19), this.y(20/19)); 
    drawProfile(ctx, this.x(6/19), this.y(1/19), this.x(18/19), this.y(18/19)); 


    if(0){ 
     ctx.clearRect(this.x(1), this.y(0), this.x(1), this.y(1)); 
     ctx.clearRect(this.x(0), this.y(1), this.x(1), this.y(1)); 
    } 

} 

draw(document.getElementById("myCanvas")); 
+3

Вы сценарий выглядит слишком сложным по сравнению с тем, что он делает , и смешать ссылаться на это в функции, которая не кажется, при первом образе, быть вызвана как метод объекта. Сначала вы должны подумать о своей архитектуре, и вы, вероятно, найдете проблемы намного проще. Нет ничего хуже, чем бесполезная сложность. – Virus721

+0

Я с @ Virus721 на этом. Ваш код выглядит очень сложным. – Funkyguy

+0

Попробуйте [ссылка] http://www.w3schools.com/html/html5_canvas.asp[/link], если вы более свежий [/ link] и этот [link] https://developer.mozilla.org/en- [/ Link] для всех с полным defination –

ответ

2

Вы используете this в своих функциях. В контексте здесь this привязан к window (есть много ресурсов о том, как использовать this, и вы делаете это неправильно).

В каждой функции, которую вы используете this, привязан к тому же (window), чтобы они переписывали переменные друг друга. (Это из-за того, как вы используете функции. Если вы их опубликуете, это будет другая история).

Так

  1. ваш метод draw() устанавливает this.x, который на самом деле window.x,
  2. затем передает его drawStar() в качестве аргумента
  3. метод функции drawStar() изменяет значение this.x (которое window.x) и возвращается к draw()
  4. затем draw() звонки drawProfile() с this.x (то есть window.x), за исключением того, что это значение является функцией, а не значением поплавка, которым вы хотели.
  5. drawProfile ожидается аргумент, чтобы быть с плавающей точкой, но теперь это функция

(для x чтения x и y)

Вы можете сделать это все с затворами и переменными. Удалите команду this и ваша программа будет работать. Вероятно.

+0

Спасибо за помощь. Я стал жертвой сложного кода в результате многих «небольших» изменений. –

+0

Это случается со всеми. Если вы не можете сказать, что не так, посмотрев на это, хороший старт - это часто перестраивать его, пока вы не сможете. – Joe

0

Joe is right. Вы переписываете функции this.x и this.y. Я не знаю, почему вы это делаете. Я сделал обходной путь сброса this.x и this.y функции к их старому значению в конце функции drawProfile и drawStar:

function drawProfile(ctx,x,y,width,height) { 
    var oldX = this.x, //storing the old values for this.x ... 
     oldY = this.y; // ... and this.y 
    this.flp = false; 
    this.x = function(r){ return Math.floor(width*(this.flp?1-r:r)); } 
    this.y = function(r){ return Math.floor(height*r); } 

    ctx.save(); 

    ctx.translate(x, y); 
    ctx.fillStyle="#40FF00"; 

    ctx.beginPath(); 
    ctx.moveTo(this.x(0), this.y(1)); 
    ctx.bezierCurveTo(this.x(0), this.y(125/190), 
         this.x(70/190), this.y(170/190), 
         this.x(75/190), this.y(120/190) 
        ); 
    ctx.lineTo(this.x(95/190), this.y(130/190)); 
    ctx.bezierCurveTo(this.x(40/190), this.y(130/190), 
         this.x(30/190), this.y(0), 
         this.x(95/190), this.y(0) 
        ); 

    this.flp = true; 

    ctx.bezierCurveTo(this.x(30/190), this.y(0), 
         this.x(40/190), this.y(130/190), 
         this.x(95/190), this.y(130/190) 
        ); 
    ctx.lineTo(this.x(75/190), this.y(120/190)); 
    ctx.bezierCurveTo(this.x(70/190), this.y(170/190), 
         this.x(0), this.y(125/190), 
         this.x(0), this.y(1) 
        ); 
    ctx.fill(); 

    this.flp = false; 

    ctx.restore(); 

    this.x = oldX; //Restoring old values 
    this.y = oldY; 
} 

function drawStar(ctx,x,y,height) 
{ 
    var pnts = 5, 
     rad = height/(1-Math.cos(0.8*Math.PI)), 
     oldX = this.x, //storing the old values for this.x ... 
     oldY = this.y; // ... and this.y 

    this.x = function(p,dst){ 
     return dst * Math.sin((p/pnts)*2*Math.PI); 
    } 
    this.y = function(p,dst){ 
     return dst * Math.cos((p/pnts)*2*Math.PI) * -1; 
    } 
    this.movePct = function(a,b,pct){ 
     var f = (function(x){ 
      var m = (b.y-a.y)/(b.x-a.x); 
      return m*x+(a.y-(a.x*m)); 
     }).bind(), 
      r = b.x - a.x, 
      point = {}; 

     point.x = a.x+(r*pct); 
     point.y = f(point.x); 

     return point; 
    } 
    this.transPoints = function(s,p,e,pct){ 
     var sp = this.movePct(s,p,pct), 
      ep = this.movePct(e,p,pct); 

     return [sp,ep]; 
    } 

    ctx.save(); 

    ctx.translate(x+rad, y+rad); 
    ctx.fillStyle = "#ffff00"; 

    ctx.beginPath(); 

    for(var i=0;i<pnts;i++){ 
     var dst = rad/2, 
      s = { x: this.x(i+0.5, dst), 
       y: this.y(i+0.5, dst) }, 
      p = { x: this.x(i+1, rad), 
       y: this.y(i+1, rad) }, 
      e = { x: this.x(i+1.5, dst), 
       y: this.y(i+1.5, dst) }, 
      t = this.transPoints(s,p,e,.75); 

     if(i==0){ ctx.moveTo(s.x, s.y); } 

     ctx.lineTo(t[0].x, t[0].y); 
     ctx.quadraticCurveTo(p.x, p.y, t[1].x, t[1].y); 
     ctx.lineTo(e.x, e.y); 
    } 
    ctx.fill(); 

    ctx.restore(); 

    this.x = oldX; //Resetting the old values 
    this.y = oldY; 
} 

function draw(c) 
{ 

    var ctx = c.getContext("2d"); 

    this.x = function(r){ return c.width*r; } 
    this.y = function(r){ return c.height*r; } 

    ctx.shadowBlur=this.y(1/19); 
    ctx.shadowColor="black"; 

    drawStar(ctx, this.x(-3/19), this.y(-1/19), this.y(20/19)); 
    drawProfile(ctx, this.x(6/19), this.y(1/19), this.x(18/19), this.y(18/19)); 



    if(0){ 
     ctx.clearRect(this.x(1), this.y(0), this.x(1), this.y(1)); 
     ctx.clearRect(this.x(0), this.y(1), this.x(1), this.y(1)); 
    } 

} 

draw(document.getElementById("myCanvas")); 

http://jsfiddle.net/hhaXM/

Смежные вопросы