簡體   English   中英

我將上傳一個使用 toDataURL 和 imgurAPI 渲染的 WebGL Canvas,但它將是一張黑色圖像

[英]I'll upload a WebGL rendered Canvas with toDataURL and imgurAPI, but it will be an image that will be a black image

我會感激你能給我的任何智慧。 先感謝您。

假設

我使用名為 Phaser.js 的游戲引擎編寫了一個 Javascript 游戲。

問題。

  • [ ] 在響應中訪問 URL 時,顯示的圖像僅為黑色。

來自 imgurAPI 的響應內容

{"id":"dwdGkep","title":null,"description":null,"datetime":1672621440,"type":"image\/png","animated":false,"width":800,"height":800,"size":12914,"views":0,"bandwidth":0,"vote":null,"favorite":false,"nsfw":null,"section":null,"account_url":null,"account_id":0,"is_ad":false,"in_most_viral":false,"has_sound":false,"tags":[],"ad_type":0,"ad_url":"","edited":"0","in_gallery":false,"deletehash":"445HisfrUgBgogT","name":"","link":"https:\/\/i.imgur.com\/dwdGkep.png"},"success":true,"status":200}

由於“成功”:真實,“狀態”:200,上傳過程本身似乎沒問題。

相關源碼

圖片發送過程

function dataURLtoBlob(dataURL) {
  const bin = atob(dataURL.split(',')[1]);
  const buffer = new Uint8Array(bin.length);
  for (let i = 0; i < bin.length; i++) {
    buffer[i] = bin.charCodeAt(i);
  }
  return new Blob([buffer], { type: 'image/png' });
}

function canvasToImage() {
  //get image data from canvas element
  //const canvas = document.getElementsByTagName("canvas")[0];
  var gl = game.canvas.getContext("webgl", { preserveDrawingBuffer: true });
  const imageData = game.canvas.toDataURL("image/png");

  // convert image data to Blob format
  const blob = dataURLtoBlob(imageData);

  const xhr = new XMLHttpRequest();

  xhr.open("POST", "https://api.imgur.com/3/image");
  xhr.setRequestHeader('Authorization', 'Client-ID XXXXXXXXXXXXXXXX');

  xhr.onload = function() {
    if (xhr.status === 200) {
      console.log(xhr.response);
    } else {
      console.error(xhr.response.data); }
    }
  };

  xhr.send(blob);
}

上面流程的調用部分(摘錄)就像在create function中設置一個事件。

tweetButton.on("pointerdown", () => {
// Put what happens when the button is clicked here
canvasToImage();
});

這是創建 function 的完整代碼

var tweetButton;

// create a game object
function create() {
    // display the tweetButton
    tweetButton = this.add.image(400, 500, "tweetButton");
    tweetButton.setDepth(10);
    tweetButton.setVisible(false); tweetButton;
    tweetButton.setInteractive();
    tweetButton.on("pointerdown", () => {
    // Write the process to be executed when the button is clicked here
    canvasToImage();
    });
    var startScreenImage = this.add.image(400, 400, "startScreen");
    startScreenImage.setInteractive();
    // Create text to display the timer
    this.gameTitle = this.add.text(200, 155, "Endless Chase", {
    fontSize: "70px",
    fill: "#000000" // make the text color black
    });
    this.startMessage = this.add.text(200, 250, "Click to start game", {
    fontSize: "40px",
    fill: "#000000" // set text color to black
    });
    this.Notion = this.add.text(200, 600, "*The game is only for play on a computer", {
    fontSize: "30px",
    fill: "#DC143C" // set text color to black
    });
    startScreenImage.on("pointerdown", () => {
    // delete startScreenImage when clicked
    this.gameTitle.destroy();
    this.startMessage.destroy();
    this.Notion.destroy(); this.startMessage.destroy(); this.startScreenImage.destroy()
    startScreenImage.destroy();
    startScreenImage_flg = true;
    // Write the process to start the game here
    // Create a cursor
    this.cursor = this.add.circle(400, 400, 17, 0x0000ff);
    // create red circles
    this.redCircles = [];
    var redCircle = this.add.circle(
        Phaser.Math.Between(
        this.cursor.x - clearance, // coordinates 300px left from cursor
        this.cursor.x + clearance // coordinates 300px right of cursor
        ),
        Phaser.Math.Between(
        this.cursor.y - clearance, // coordinates 300px above the cursor
        this.cursor.y + clearance // coordinates 300px below cursor
        ),
        50, // radius
        0xff0000 // color
    );
    this.redCircles.push(redCircle);
    // start the process of adding a red circle every 5 seconds
    this.intervalId = setInterval(() => {
        // create a red circle
        var redCircle = this.add.circle(
        Phaser.Math.Between(this.cursor.x - clearance, this.cursor.x + clearance),
        Phaser.Math.Between(this.cursor.y - clearance, this.cursor.y + clearance),
        50, // radius
        0xff0000 // color
        );
        redCircle.speed = Math.random() * 0.09 + 0.01;
        this.redCircles.push(redCircle);
    }, 5000);

    // Create text to display the timer
    this.timerText = this.add.text(10, 10, "0 seconds", {
        fontSize: "32px",
        fill: "#000000" // make the text color black
    });
    // initialize the timer
    this.elapsedTime = 0;
    this.prevTime = this.time.now;
    this.gameOverText = this.add.text(200, 300, "", {
        fontSize: "32px",
        fill: "#000000" // set text color to black
    });
    this.gameOverText.setDepth(10);
    });
    // Register a process to end the game when the tab becomes inactive
    document.addEventListener("visibilitychange", () => {
    this.gameOver = true;
    startScreenImage_flg = true;
    clearInterval(this.intervalId);
    });
}

我試過的

我為同一事件嘗試了以下方法,但沒有用。

var gl = game.canvas.getContext("webgl", { preserveDrawingBuffer: true });

當前處理

  • [ ] 在Result畫面中點擊Canvas中的一個元素將執行以下一系列過程。
  • [ ] 使用 toDataURL() 將 WebGL canvas 轉換為圖像。
  • [ ] 將圖像數據轉換為 Blob 格式。
  • [ ] 使用 imgur 的 API 以 XMLHttpRequest 上傳 Blob 格式的數據
  • [ ] 獲取響應中的URL`

最好的解決方案是,簡單地使用相位器的內置 function snapshot鏈接到文檔),生成的圖像應該顯示正確(不需要特殊配置)。

這個 function 創建當前 canvas 的圖像,並將拍攝的快照作為HTMLImageElement傳遞給回調 function。

你只需要調整你的代碼看起來像這樣:

function canvasToImage() {

    game.renderer.snapshot(function (image) {
        
        const blob = dataURLtoBlob(image.src);
        const xhr = new XMLHttpRequest();

        ...

        xhr.send(blob);         
    });

}

如果這對你不起作用(我在我的一個本地項目上測試過它,並且它在我的設置中有效) ,你只需要在移相器 github上打開一個問題或在討論頁面上提及它,然后將進行修復。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM