62

I'm trying to place a background image on the back of this canvas script I found. I know it's something to do with the context.fillstyle but not sure how to go about it. I'd like that line to read something like this:

context.fillStyle = "url('http://www.samskirrow.com/background.png')";

Here is my current code:

var waveform = (function() {

var req = new XMLHttpRequest();
req.open("GET", "js/jquery-1.6.4.min.js", false);
req.send();
eval(req.responseText);
req.open("GET", "js/soundmanager2.js", false);
req.send();
eval(req.responseText);
req.open("GET", "js/soundcloudplayer.js", false);
req.send();
eval(req.responseText);
req.open("GET", "js/raf.js", false);
req.send();
eval(req.responseText);

// soundcloud player setup

soundManager.usePolicyFile = true;
soundManager.url = 'http://www.samskirrow.com/client-kyra/js/';
soundManager.flashVersion = 9;
soundManager.useFlashBlock = false;
soundManager.debugFlash = false;
soundManager.debugMode = false;
soundManager.useHighPerformance = true;
soundManager.wmode = 'transparent';
soundManager.useFastPolling = true;
soundManager.usePeakData = true;
soundManager.useWaveformData = true;
soundManager.useEqData = true;

var clientID = "345ae40b30261fe4d9e6719f6e838dac";
var playlistUrl = "https://soundcloud.com/kyraofficial/sets/kyra-ft-cashtastic-good-love";

var waveLeft = [];
var waveRight = [];

// canvas animation setup
var canvas;
var context;

function init(c) {
    canvas = document.getElementById(c);
    context = canvas.getContext("2d");
    soundManager.onready(function() {
        initSound(clientID, playlistUrl);
    });
    aniloop();
}

function aniloop() {
    requestAnimFrame(aniloop);
    drawWave();
}

function drawWave() {
    
    var step = 10;
    var scale = 60;
    
    // clear
    context.fillStyle = "#ff19a7";
    context.fillRect(0, 0, canvas.width, canvas.height);
    
    // left wave
    context.beginPath();
            
    for ( var i = 0; i < 256; i++) {
        
        var l = (i/(256-step)) * 1000;
        var t = (scale + waveLeft[i] * -scale);
        
        if (i == 0) {
        context.moveTo(l,t);
        } else {
        context.lineTo(l,t); //change '128' to vary height of wave, change '256' to move wave up or down.
    }
    }
    
    context.stroke();


    // right wave
    context.beginPath();
    context.moveTo(0, 256);
    for ( var i = 0; i < 256; i++) {
        
        context.lineTo(4 * i, 255 + waveRight[i] * 128.);
    }
    context.lineWidth = 0.5;
    context.strokeStyle = "#000";
    context.stroke();
}

function updateWave(sound) {
    waveLeft = sound.waveformData.left;
}

return {
    init : init
};
})();

Revised code - currently just showing black as the background, not an image:

// canvas animation setup
var backgroundImage = new Image(); 
backgroundImage.src = 'http://www.samskirrow.com/images/main-bg.jpg'; 
var canvas;
var context;

function init(c) {
    canvas = document.getElementById(c);
    context = canvas.getContext("2d");
    soundManager.onready(function() {
        initSound(clientID, playlistUrl);
    });
    aniloop();
}

function aniloop() {
    requestAnimFrame(aniloop);
    drawWave();
}

function drawWave() {
    
    var step = 10;
    var scale = 60;
    
    // clear
    context.drawImage(backgroundImage, 0, 0);
    context.fillRect(0, 0, canvas.width, canvas.height);
    
    // left wave
    context.beginPath();
            
    for ( var i = 0; i < 256; i++) {
        
        var l = (i/(256-step)) * 1000;
        var t = (scale + waveLeft[i] * -scale);
        
        if (i == 0) {
        context.moveTo(l,t);
        } else {
        context.lineTo(l,t); //change '128' to vary height of wave, change '256' to move wave up or down.
    }
    }
    
    context.stroke();


    // right wave
    context.beginPath();
    context.moveTo(0, 256);
    for ( var i = 0; i < 256; i++) {
        
        context.lineTo(4 * i, 255 + waveRight[i] * 128.);
    }
    context.lineWidth = 0.5;
    context.strokeStyle = "#ff19a7";
    context.stroke();
}

function updateWave(sound) {
    waveLeft = sound.waveformData.left;
}

return {
    init : init
};
})();
Sam Skirrow
  • 3,647
  • 15
  • 54
  • 101
  • 1
    `context.fillStyle` accepts only strings, `CanvasGradient` and `CanvasPattern` objects, and the strings are parsed as CSS color values. If you want to draw an image to the canvas, create an `Image` object with the source set to the required image's URL, and then simply use `context.drawImage`. If you draw the image before anything else in `drawWave`, right when you clear the canvas, you have your background. – Rikonator Dec 23 '12 at 17:09
  • Thanks @Rikonator my scripting is not that great, any chance you could elaborate on how I'd implement your points?? – Sam Skirrow Dec 23 '12 at 17:23
  • 1
    @Loktar has already answered and I've nothing to add, but here's a fiddle with an active animation anyway: http://jsfiddle.net/vZ8UT/ – Rikonator Dec 23 '12 at 17:48
  • Thanks for taking the time to do that demo @Rikonator, my revised code is above, currently just showing a black background - not an image. Any thoughts? – Sam Skirrow Dec 23 '12 at 20:13
  • 1
    Get rid of the `context.fillRect` immediately after `context.drawImage`. If you use `fillRect` after you draw the image, you are essentially filling a rectangle the size of the canvas with the default fill style **over** the background image, defeating the point of drawing the image. – Rikonator Dec 23 '12 at 20:17
  • A-Mazing. Thank you so much for your help, worked like a charm! – Sam Skirrow Dec 23 '12 at 20:22

4 Answers4

75

Theres a few ways you can do this. You can either add a background to the canvas you are currently working on, which if the canvas isn't going to be redrawn every loop is fine. Otherwise you can make a second canvas underneath your main canvas and draw the background to it. The final way is to just use a standard <img> element placed under the canvas. To draw a background onto the canvas element you can do something like the following:

Live Demo

var canvas = document.getElementById("canvas"),
    ctx = canvas.getContext("2d");

canvas.width = 903;
canvas.height = 657;


var background = new Image();
background.src = "http://www.samskirrow.com/background.png";

// Make sure the image is loaded first otherwise nothing will draw.
background.onload = function(){
    ctx.drawImage(background,0,0);   
}

// Draw whatever else over top of it on the canvas.
Chris
  • 2,174
  • 28
  • 37
Loktar
  • 34,764
  • 7
  • 90
  • 104
41

Why don't you style it out:

<canvas id="canvas" width="800" height="600" style="background: url('./images/image.jpg')">
  Your browser does not support the canvas element.
</canvas>
Nezar Fadle
  • 1,335
  • 13
  • 11
  • Does this work on all modern browsers? I heard a rumour it didn't work in IE, but can't find any proof. – Josh Aug 01 '17 at 20:52
4

Make sure that in case your image is not in the dom, and you get it from local directory or server, you should wait for the image to load and just after that to draw it on the canvas.

something like that:

function drawBgImg() {
    let bgImg = new Image();
    bgImg.src = '/images/1.jpg';
    bgImg.onload = () => {
        gCtx.drawImage(bgImg, 0, 0, gElCanvas.width, gElCanvas.height);
    }
}
Jaydeep
  • 1,686
  • 1
  • 16
  • 29
Emanuel
  • 163
  • 1
  • 9
-4

Canvas does not using .png file as background image. changing to other file extensions like gif or jpg works fine.

Sathiesh
  • 33
  • 1