最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Transparent Color HTML5 Canvas - Stack Overflow

programmeradmin0浏览0评论

I have a simple Pong game made with some Javascript and a Canvas tag.

I set the background color of the canvas tag to be transparent so the background image of the div tag can be displayed under the canvas.

The problem is that when I have it set to transparent it doesn't draw the ball and paddles correctly as if I set the background to a normal hex color. It draws the path of the paddles and the ball and the screen eventually turns the color of the ball.

The Javascript code is:

//canvas
var Width = 988;
var Height = 310;
var canvas = document.getElementById("Pong");
canvas.width = Width;
canvas.height = Height;
canvas.setAttribute('tabindex', 1);
var ctx = canvas.getContext("2d");
var FPS = 1000 / 60;

var BG = {
    Color: 'transparent',
    Paint: function(){
        ctx.fillStyle = this.Color;
        ctx.fillRect(0, 0, Width, Height);
    }
};

//var Mouse = {X: 0, Y: 0};

var Ball = {
    Radius: 6,
    Color: '#ffffff',
    X: 0,
    Y: 0,
    VelX: 0,
    VelY: 0,

    Paint: function(){
        ctx.beginPath();
        ctx.fillStyle = this.Color;
        ctx.arc(this.X, this.Y, this.Radius, 0, Math.PI * 2, false);
        ctx.fill();
        this.Update();
    },

    Update: function(){
        this.X += this.VelX;
        this.Y += this.VelY;
    },

    Reset: function(){
        this.X = Width/2;
        this.Y = Height/2;
        this.VelX = (!!Math.round(Math.random() * 1) ? 1.5 : -1.5);
        this.VelY = (!!Math.round(Math.random() * 1) ? 1.5 : -1.5);
    }
};

function Paddle(position){
    this.Color = '#ffffff';
    this.Width = 15;
    this.Height = 60;
    this.X = 0;
    this.Y = Height/2 - this.Height/2;
    this.Score = 0;

    if(position == 'left')
        this.X = 50;
    else this.X = 938;

    this.Paint = function(){
        ctx.fillStyle = this.Color;
        ctx.fillRect(this.X, this.Y, this.Width, this.Height);
        ctx.fillStyle = this.Color;
        ctx.font = "normal 10pt Calibri";
        if(position == 'left'){
            ctx.textAlign = "left";
            ctx.fillText("score: " + Player.Score, 10, 10);
        }else{
            ctx.textAlign = "right";
            ctx.fillText("score: " + Computer.Score, Width - 10, 10);
        }
    };

    this.IsCollision = function () {
        if (Ball.X - Ball.Radius > this.Width + this.X || this.X > Ball.Radius * 2 + Ball.X - Ball.Radius) 
            return false;
        if (Ball.Y - Ball.Radius > this.Height + this.Y || this.Y > Ball.Radius * 2 + Ball.Y - Ball.Radius) 
            return false;
      return true;
    };
};

window.requestAnimFrame = (function(){ 
    return window.requestAnimationFrame 
    || window.webkitRequestAnimationFrame 
    || window.mozRequestAnimationFrame 
    || window.oRequestAnimationFrame 
    || window.msRequestAnimationFrame 
    || function( callback ){ return window.setTimeout(callback, FPS); }; }
)();

window.cancelRequestAnimFrame = (function() { 
    return window.cancelAnimationFrame 
            || window.webkitCancelRequestAnimationFrame 
            || window.mozCancelRequestAnimationFrame 
            || window.oCancelRequestAnimationFrame 
            || window.msCancelRequestAnimationFrame 
            || clearTimeout }
)();

//game
var Computer = new Paddle();
var Player = new Paddle('left');

//event listener
function MouseMove(e){
    Player.Y = e.pageY - Player.Height/2;
}
//attache event
canvas.addEventListener("mousemove", MouseMove, true);

function Paint(){
    ctx.beginPath();
    BG.Paint();
    Computer.Paint();
    Player.Paint();
    Ball.Paint();
}

function Loop(){
    init = requestAnimFrame(Loop);
    Paint();

    if(Player.IsCollision() || Computer.IsCollision()){
        Ball.VelX = Ball.VelX * -1;
        Ball.VelX += (Ball.VelX > 0 ? 0.5 : -0.5 );
        if(Math.abs(Ball.VelX) > Ball.Radius * 1.5)
            Ball.VelX = (Ball.VelX > 0 ? Ball.Radius * 1.5 : Ball.Radius * -1.5);
    }

    if(Ball.Y - Ball.Radius < 0 || Ball.Y + Ball.Radius > Height)
        Ball.VelY = Ball.VelY * -1;

    if(Ball.X - Ball.Radius <= 0){
        Computer.Score++;
        Ball.Reset();
    }else if(Ball.X + Ball.Radius > Width){
        Player.Score++;
        Ball.Reset();
    }

    if(Computer.Score === 10)
        GameOver(false);
    else if(Player.Score === 10)
        GameOver(true);

    Computer.Y = (Computer.Y + Computer.Height/2 < Ball.Y ? Computer.Y + Computer.Vel : Computer.Y - Computer.Vel);
};

function GameOver(win){
    cancelRequestAnimFrame(init);
    BG.Paint();
    ctx.fillStyle = "#ffffff";
    ctx.font = "bold 40px Calibri";
    ctx.textAlign = "center";
    ctx.fillText((win ? "A WINNER IS YOU" : "GAME OVER"), Width/2, Height/2);
    ctx.font = "normal 16px Calibri";
    ctx.fillText("refresh to reply", Width/2, Height/2 + 20);
}

function NewGame(){
    Ball.Reset();
    Player.Score = 0;
    Computer.Score = 0;
    Computer.Vel = 1.25;
    Loop();
}

NewGame();

I tried simply removing the BG var but it just did the same thing.

Update: I also tried with and without ctx.closePath with no success.

I have a simple Pong game made with some Javascript and a Canvas tag.

I set the background color of the canvas tag to be transparent so the background image of the div tag can be displayed under the canvas.

The problem is that when I have it set to transparent it doesn't draw the ball and paddles correctly as if I set the background to a normal hex color. It draws the path of the paddles and the ball and the screen eventually turns the color of the ball.

The Javascript code is:

//canvas
var Width = 988;
var Height = 310;
var canvas = document.getElementById("Pong");
canvas.width = Width;
canvas.height = Height;
canvas.setAttribute('tabindex', 1);
var ctx = canvas.getContext("2d");
var FPS = 1000 / 60;

var BG = {
    Color: 'transparent',
    Paint: function(){
        ctx.fillStyle = this.Color;
        ctx.fillRect(0, 0, Width, Height);
    }
};

//var Mouse = {X: 0, Y: 0};

var Ball = {
    Radius: 6,
    Color: '#ffffff',
    X: 0,
    Y: 0,
    VelX: 0,
    VelY: 0,

    Paint: function(){
        ctx.beginPath();
        ctx.fillStyle = this.Color;
        ctx.arc(this.X, this.Y, this.Radius, 0, Math.PI * 2, false);
        ctx.fill();
        this.Update();
    },

    Update: function(){
        this.X += this.VelX;
        this.Y += this.VelY;
    },

    Reset: function(){
        this.X = Width/2;
        this.Y = Height/2;
        this.VelX = (!!Math.round(Math.random() * 1) ? 1.5 : -1.5);
        this.VelY = (!!Math.round(Math.random() * 1) ? 1.5 : -1.5);
    }
};

function Paddle(position){
    this.Color = '#ffffff';
    this.Width = 15;
    this.Height = 60;
    this.X = 0;
    this.Y = Height/2 - this.Height/2;
    this.Score = 0;

    if(position == 'left')
        this.X = 50;
    else this.X = 938;

    this.Paint = function(){
        ctx.fillStyle = this.Color;
        ctx.fillRect(this.X, this.Y, this.Width, this.Height);
        ctx.fillStyle = this.Color;
        ctx.font = "normal 10pt Calibri";
        if(position == 'left'){
            ctx.textAlign = "left";
            ctx.fillText("score: " + Player.Score, 10, 10);
        }else{
            ctx.textAlign = "right";
            ctx.fillText("score: " + Computer.Score, Width - 10, 10);
        }
    };

    this.IsCollision = function () {
        if (Ball.X - Ball.Radius > this.Width + this.X || this.X > Ball.Radius * 2 + Ball.X - Ball.Radius) 
            return false;
        if (Ball.Y - Ball.Radius > this.Height + this.Y || this.Y > Ball.Radius * 2 + Ball.Y - Ball.Radius) 
            return false;
      return true;
    };
};

window.requestAnimFrame = (function(){ 
    return window.requestAnimationFrame 
    || window.webkitRequestAnimationFrame 
    || window.mozRequestAnimationFrame 
    || window.oRequestAnimationFrame 
    || window.msRequestAnimationFrame 
    || function( callback ){ return window.setTimeout(callback, FPS); }; }
)();

window.cancelRequestAnimFrame = (function() { 
    return window.cancelAnimationFrame 
            || window.webkitCancelRequestAnimationFrame 
            || window.mozCancelRequestAnimationFrame 
            || window.oCancelRequestAnimationFrame 
            || window.msCancelRequestAnimationFrame 
            || clearTimeout }
)();

//game
var Computer = new Paddle();
var Player = new Paddle('left');

//event listener
function MouseMove(e){
    Player.Y = e.pageY - Player.Height/2;
}
//attache event
canvas.addEventListener("mousemove", MouseMove, true);

function Paint(){
    ctx.beginPath();
    BG.Paint();
    Computer.Paint();
    Player.Paint();
    Ball.Paint();
}

function Loop(){
    init = requestAnimFrame(Loop);
    Paint();

    if(Player.IsCollision() || Computer.IsCollision()){
        Ball.VelX = Ball.VelX * -1;
        Ball.VelX += (Ball.VelX > 0 ? 0.5 : -0.5 );
        if(Math.abs(Ball.VelX) > Ball.Radius * 1.5)
            Ball.VelX = (Ball.VelX > 0 ? Ball.Radius * 1.5 : Ball.Radius * -1.5);
    }

    if(Ball.Y - Ball.Radius < 0 || Ball.Y + Ball.Radius > Height)
        Ball.VelY = Ball.VelY * -1;

    if(Ball.X - Ball.Radius <= 0){
        Computer.Score++;
        Ball.Reset();
    }else if(Ball.X + Ball.Radius > Width){
        Player.Score++;
        Ball.Reset();
    }

    if(Computer.Score === 10)
        GameOver(false);
    else if(Player.Score === 10)
        GameOver(true);

    Computer.Y = (Computer.Y + Computer.Height/2 < Ball.Y ? Computer.Y + Computer.Vel : Computer.Y - Computer.Vel);
};

function GameOver(win){
    cancelRequestAnimFrame(init);
    BG.Paint();
    ctx.fillStyle = "#ffffff";
    ctx.font = "bold 40px Calibri";
    ctx.textAlign = "center";
    ctx.fillText((win ? "A WINNER IS YOU" : "GAME OVER"), Width/2, Height/2);
    ctx.font = "normal 16px Calibri";
    ctx.fillText("refresh to reply", Width/2, Height/2 + 20);
}

function NewGame(){
    Ball.Reset();
    Player.Score = 0;
    Computer.Score = 0;
    Computer.Vel = 1.25;
    Loop();
}

NewGame();

I tried simply removing the BG var but it just did the same thing.

Update: I also tried with and without ctx.closePath with no success.

Share Improve this question edited Oct 24, 2013 at 23:39 Carl asked Oct 24, 2013 at 23:21 CarlCarl 2453 gold badges4 silver badges15 bronze badges 3
  • You never seem to call ctx.closePath which will probably cause issues. – david Commented Oct 24, 2013 at 23:30
  • @david Thanks for the ment. I just tried that with no success. – Carl Commented Oct 24, 2013 at 23:38
  • 1 That doesn't matter, unless you try to stroke the path. For fill, it auto-closes. – Niet the Dark Absol Commented Oct 24, 2013 at 23:42
Add a ment  | 

2 Answers 2

Reset to default 6

This is because you don't clear the canvas at the start of each frame. With a solid-colour background this doesn't matter, but with transparent you must do this:

ctx.clearRect(0,0,canvas.width,canvas.height);

You need to clear the canvas on every draw. Canvas keeps the content that has been drawn on it.

Having a transparent canvas isn't a good idea anyway. Transparency makes things slower as it has to be reputed every time you draw anything to the canvas. Try drawing an image into it using the image draw functions. You might find that it can use the GPU to do the image position.

发布评论

评论列表(0)

  1. 暂无评论
ok 不同模板 switch ($forum['model']) { /*case '0': include _include(APP_PATH . 'view/htm/read.htm'); break;*/ default: include _include(theme_load('read', $fid)); break; } } break; case '10': // 主题外链 / thread external link http_location(htmlspecialchars_decode(trim($thread['description']))); break; case '11': // 单页 / single page $attachlist = array(); $imagelist = array(); $thread['filelist'] = array(); $threadlist = NULL; $thread['files'] > 0 and list($attachlist, $imagelist, $thread['filelist']) = well_attach_find_by_tid($tid); $data = data_read_cache($tid); empty($data) and message(-1, lang('data_malformation')); $tidlist = $forum['threads'] ? page_find_by_fid($fid, $page, $pagesize) : NULL; if ($tidlist) { $tidarr = arrlist_values($tidlist, 'tid'); $threadlist = well_thread_find($tidarr, $pagesize); // 按之前tidlist排序 $threadlist = array2_sort_key($threadlist, $tidlist, 'tid'); } $allowpost = forum_access_user($fid, $gid, 'allowpost'); $allowupdate = forum_access_mod($fid, $gid, 'allowupdate'); $allowdelete = forum_access_mod($fid, $gid, 'allowdelete'); $access = array('allowpost' => $allowpost, 'allowupdate' => $allowupdate, 'allowdelete' => $allowdelete); $header['title'] = $thread['subject']; $header['mobile_link'] = $thread['url']; $header['keywords'] = $thread['keyword'] ? $thread['keyword'] : $thread['subject']; $header['description'] = $thread['description'] ? $thread['description'] : $thread['brief']; $_SESSION['fid'] = $fid; if ($ajax) { empty($conf['api_on']) and message(0, lang('closed')); $apilist['header'] = $header; $apilist['extra'] = $extra; $apilist['access'] = $access; $apilist['thread'] = well_thread_safe_info($thread); $apilist['thread_data'] = $data; $apilist['forum'] = $forum; $apilist['imagelist'] = $imagelist; $apilist['filelist'] = $thread['filelist']; $apilist['threadlist'] = $threadlist; message(0, $apilist); } else { include _include(theme_load('single_page', $fid)); } break; default: message(-1, lang('data_malformation')); break; } ?>