Javascript 使用Canvas GlobalComposite制作面具用于拼图游戏后端的操作

Javascript 使用Canvas GlobalComposite制作面具用于拼图游戏后端的操作,javascript,php,html,canvas,html5-canvas,Javascript,Php,Html,Canvas,Html5 Canvas,我正在尝试为发布简单的拼图游戏制作一个后端。游戏使用12个预先制作好的形状作为面具来制作12个拼图。我找到了非常好的,并进行了测试 我正在制作的应用程序使用ajax将每个完成的部分发送到serverside.php脚本。用户使用SSE加载图像(600x400),应用程序根据数组arr_x和arr_y的值将原始图像移动到tempCanvas中。这应该发生在for循环中: function drawPieces(){ var canvas = document.getElementById(

我正在尝试为发布简单的拼图游戏制作一个后端。游戏使用12个预先制作好的形状作为面具来制作12个拼图。我找到了非常好的,并进行了测试

我正在制作的应用程序使用ajax将每个完成的部分发送到serverside.php脚本。用户使用SSE加载图像(600x400),应用程序根据数组arr_x和arr_y的值将原始图像移动到
tempCanvas
中。这应该发生在for循环中:

function drawPieces(){
    var canvas = document.getElementById("myCanvas");
    var context =canvas.getContext("2d");
    var tempCanvas = document.getElementById("tempCanvas");       
    var tempContext = tempCanvas.getContext("2d");
    var img_mask = new Image();
    var w;
    var h; 
    var cvd0,cvd1,cvd2,cvd3,cvd4,cvd5,cvd6,cvd7,cvd8,cvd9,cvd10,cvd11;
    var arr_data = [cvd0,cvd1,cvd2,cvd3,cvd4,cvd5,cvd6,cvd7,cvd8,cvd9,cvd10,cvd11];
    var arr_x = [0,-136,-289,-414,0,-115,-270,-415,0,-118,-288,-415];
    var arr_y = [0,0,0,0,-113,-111,-111,-124,-244,-256,-243,-241];
    var img_bg = new Image(600, 400);        

    for (var i = 0; i<arr_x.length; i++) {
        img_bg = original;
        // get the mask
        img_mask.src = "img/mask"+i+".png";

        w = img_mask.width;
        h = img_mask.height;
        console.log("w = ", img_mask.width, " h = ", img_mask.height);

        tempCanvas.width = w;
        tempCanvas.height = h;

         // Her lages maska
        tempContext.drawImage(img_mask,0,0);
        tempContext.globalCompositeOperation = 'source-in';
        tempContext.drawImage(img_bg,arr_x[i],arr_y[i]);
        myCanvas.width = w;
        myCanvas.height = h;

        // Draws tempCanvas on to myCanvas
        console.log("tempCanvas: ", tempCanvas, " img_mask.src = ", img_mask.src);
        context.drawImage(tempCanvas, 0, 0);
        arr_data[i] = myCanvas;
        sendData(arr_data[i], [i]);                
    };
}
我的设置绝对有问题,但我不知道是什么。谁来帮帮我

顺便说一下,这也是我的.php脚本:

<?php
if (isset($GLOBALS["HTTP_RAW_POST_DATA"]))
{
    // Get the data
    $imageData=$GLOBALS['HTTP_RAW_POST_DATA'];

    $parts = explode("<split>", $imageData);
    $imageData = $parts[0];
    $index= $parts[1];

    // Remove the headers (data:,) part.
    // A real application should use them according to needs such as to check image type
    $filteredData=substr($imageData, strpos($imageData, ",")+1);

    // Need to decode before saving since the data we received is already base64 encoded
    $unencodedData=base64_decode($filteredData);

    // Save file.
    $fp = fopen( "pieces/".$index.".png", "wb" );
    fwrite( $fp, $unencodedData);
    fclose( $fp );
}
?>

问题 问题是,图像加载是异步的,这意味着它们在后台加载,而您的代码仍在继续

这意味着当您尝试将图像与drawImage一起使用时,图像将无法准备就绪(加载并解码),从而导致错误。这里的错误是间接的,因为w和h没有获得画布的有效值,这意味着画布的宽度为0,高度为0,这将在尝试绘制时触发实际错误

它第二次“起作用”的原因是,浏览器缓存中存在图像,并且可能能够在使用图像之前提供该图像

另一个问题是,在循环中,您正在覆盖image变量,因此加载时只使用最后一个图像

解决方案 解决方案是在开始循环之前制作或使用图像加载器。制作一个很容易,但为了简单起见,我将在本例中使用(免责声明:作者同上),但只要您对图像使用回调,任何类型的加载程序都可以:

function drawPieces(){
    var canvas = document.getElementById("myCanvas");
    var context =canvas.getContext("2d");
    var tempCanvas = document.getElementById("tempCanvas");       
    var tempContext = tempCanvas.getContext("2d");
    var img_mask;
    var w;
    var h; 
    var cvd0,cvd1,cvd2,cvd3,cvd4,cvd5,cvd6,cvd7,cvd8,cvd9,cvd10,cvd11;
    var arr_data = [cvd0,cvd1,cvd2,cvd3,cvd4,cvd5,cvd6,cvd7,cvd8,cvd9,cvd10,cvd11];
    var arr_x = [0,-136,-289,-414,0,-115,-270,-415,0,-118,-288,-415];
    var arr_y = [0,0,0,0,-113,-111,-111,-124,-244,-256,-243,-241];

    var img_bg;

    // using some image(s) loader
    var loader = new YAIL({done: draw});

    for (var i = 0; i<arr_x.length; i++)
        loader.add("img/mask"+i+".png");

    loader.load();  // start loading images

    // this is called when images has loaded
    function draw(e) {

        for (var i = 0; i<arr_x.length; i++) {

            //img_bg = original;  ??
            // get the mask
            var img_mask = e.images[i];  // loaded images in an array

            w = img_mask.width;          // now you will have a valid
            h = img_mask.height;         //  dimension here

            console.log("w = ", img_mask.width, " h = ", img_mask.height);

            tempCanvas.width = w;
            tempCanvas.height = h;

             // Her lages maska
            tempContext.drawImage(img_mask,0,0);
            tempContext.globalCompositeOperation = 'source-in';
            tempContext.drawImage(img_bg,arr_x[i],arr_y[i]);
            myCanvas.width = w;
            myCanvas.height = h;

            // Draws tempCanvas on to myCanvas
            console.log("tempCanvas: ", tempCanvas, " img_mask.src = ", img_mask.src);
            context.drawImage(tempCanvas, 0, 0);
            arr_data[i] = myCanvas;
            sendData(arr_data[i], [i]);                
        }
    };
}
功能抽片(){
var canvas=document.getElementById(“myCanvas”);
var context=canvas.getContext(“2d”);
var tempCanvas=document.getElementById(“tempCanvas”);
var tempContext=tempCanvas.getContext(“2d”);
var-img_掩模;
var-w;
var h;
变量cvd0、cvd1、cvd2、cvd3、cvd4、cvd5、cvd6、cvd7、cvd8、cvd9、cvd10、cvd11;
var arr_数据=[cvd0、cvd1、cvd2、cvd3、cvd4、cvd5、cvd6、cvd7、cvd8、cvd9、cvd10、cvd11];
var arr_x=[0,-136,-289,-414,0,-115,-270,-415,0,-118,-288,-415];
var arr_y=[0,0,0,0,-113,-111,-111,-124,-244,-256,-243,-241];
var img_bg;
//使用一些图像加载程序
var loader=new YAIL({done:draw});
对于(var i=0;i
<?php
if (isset($GLOBALS["HTTP_RAW_POST_DATA"]))
{
    // Get the data
    $imageData=$GLOBALS['HTTP_RAW_POST_DATA'];

    $parts = explode("<split>", $imageData);
    $imageData = $parts[0];
    $index= $parts[1];

    // Remove the headers (data:,) part.
    // A real application should use them according to needs such as to check image type
    $filteredData=substr($imageData, strpos($imageData, ",")+1);

    // Need to decode before saving since the data we received is already base64 encoded
    $unencodedData=base64_decode($filteredData);

    // Save file.
    $fp = fopen( "pieces/".$index.".png", "wb" );
    fwrite( $fp, $unencodedData);
    fclose( $fp );
}
?>
function drawPieces(){
    var canvas = document.getElementById("myCanvas");
    var context =canvas.getContext("2d");
    var tempCanvas = document.getElementById("tempCanvas");       
    var tempContext = tempCanvas.getContext("2d");
    var img_mask;
    var w;
    var h; 
    var cvd0,cvd1,cvd2,cvd3,cvd4,cvd5,cvd6,cvd7,cvd8,cvd9,cvd10,cvd11;
    var arr_data = [cvd0,cvd1,cvd2,cvd3,cvd4,cvd5,cvd6,cvd7,cvd8,cvd9,cvd10,cvd11];
    var arr_x = [0,-136,-289,-414,0,-115,-270,-415,0,-118,-288,-415];
    var arr_y = [0,0,0,0,-113,-111,-111,-124,-244,-256,-243,-241];

    var img_bg;

    // using some image(s) loader
    var loader = new YAIL({done: draw});

    for (var i = 0; i<arr_x.length; i++)
        loader.add("img/mask"+i+".png");

    loader.load();  // start loading images

    // this is called when images has loaded
    function draw(e) {

        for (var i = 0; i<arr_x.length; i++) {

            //img_bg = original;  ??
            // get the mask
            var img_mask = e.images[i];  // loaded images in an array

            w = img_mask.width;          // now you will have a valid
            h = img_mask.height;         //  dimension here

            console.log("w = ", img_mask.width, " h = ", img_mask.height);

            tempCanvas.width = w;
            tempCanvas.height = h;

             // Her lages maska
            tempContext.drawImage(img_mask,0,0);
            tempContext.globalCompositeOperation = 'source-in';
            tempContext.drawImage(img_bg,arr_x[i],arr_y[i]);
            myCanvas.width = w;
            myCanvas.height = h;

            // Draws tempCanvas on to myCanvas
            console.log("tempCanvas: ", tempCanvas, " img_mask.src = ", img_mask.src);
            context.drawImage(tempCanvas, 0, 0);
            arr_data[i] = myCanvas;
            sendData(arr_data[i], [i]);                
        }
    };
}