我试图在另一个画布上添加一个画布-我如何使这个函数等待开始,直到第一个画布被创建?

function PaintObject(brush) {

    this.started = false;

    // get handle of the main canvas, as a DOM object, not as a jQuery Object. Context is unfortunately not yet
    // available in jquery canvas wrapper object.
    var mainCanvas = $("#" + brush).get(0);

    // Check if everything is ok
    if (!mainCanvas) {alert("canvas undefined, does not seem to be supported by your browser");}
    if (!mainCanvas.getContext) {alert('Error: canvas.getContext() undefined !');}

    // Get the context for drawing in the canvas
    var mainContext = mainCanvas.getContext('2d');
    if (!mainContext) {alert("could not get the context for the main canvas");}

    this.getMainCanvas = function () {
        return mainCanvas;
    }
    this.getMainContext = function () {
        return mainContext;
    }

    // Prepare a second canvas on top of the previous one, kind of second "layer" that we will use
    // in order to draw elastic objects like a line, a rectangle or an ellipse we adjust using the mouse
    // and that follows mouse movements
    var frontCanvas = document.createElement('canvas');
    frontCanvas.id = 'canvasFront';
    // Add the temporary canvas as a second child of the mainCanvas parent.
    mainCanvas.parentNode.appendChild(frontCanvas);

    if (!frontCanvas) {
        alert("frontCanvas null");
    }
    if (!frontCanvas.getContext) {
        alert('Error: no frontCanvas.getContext!');
    }
    var frontContext = frontCanvas.getContext('2d');
    if (!frontContext) {
        alert("no TempContext null");
    }

    this.getFrontCanvas = function () {
        return frontCanvas;
    }
    this.getFrontContext = function () {
        return frontContext;
    }

当前回答

根据您需要支持的浏览器,可以选择MutationObserver。

编辑:现在所有主流浏览器都支持MutationObserver。

以下内容应该可以达到目的:

// callback executed when canvas was found
function handleCanvas(canvas) { ... }

// set up the mutation observer
var observer = new MutationObserver(function (mutations, me) {
  // `mutations` is an array of mutations that occurred
  // `me` is the MutationObserver instance
  var canvas = document.getElementById('my-canvas');
  if (canvas) {
    handleCanvas(canvas);
    me.disconnect(); // stop observing
    return;
  }
});

// start observing
observer.observe(document, {
  childList: true,
  subtree: true
});

注意:我自己还没有测试过这段代码,但这是大概的想法。

您可以轻松地将其扩展为只搜索DOM中发生更改的部分。为此,使用突变参数,它是MutationRecord对象的数组。

其他回答

这是对杰米·哈伯的回答的一个小小的改进

const checkElement = async selector => {
  while ( document.querySelector(selector) === null) {
    await new Promise( resolve =>  requestAnimationFrame(resolve) )
  }
  return document.querySelector(selector); 
};

使用方法:

checkElement('.myElement').then((selector) => {
  console.log(selector);
});

一种更现代的等待元素的方法:

while(!document.querySelector(".my-selector")) {
  await new Promise(r => setTimeout(r, 500));
}
// now the element is loaded

注意,这段代码需要包装在一个异步函数中。

这只适用于现代浏览器,但我发现它更容易使用一个then,所以请先测试,但是:

ES5

function rafAsync() {
    return new Promise(resolve => {
        requestAnimationFrame(resolve); //faster than set time out
    });
}

function checkElement(selector) {
    if (document.querySelector(selector) === null) {
        return rafAsync().then(() => checkElement(selector));
    } else {
        return Promise.resolve(true);
    }
}

ES6

async function checkElement(selector) {
    const querySelector = null;
    while (querySelector === null) {
        await rafAsync();
        querySelector = document.querySelector(selector);
    }
    return querySelector;
}  

使用

checkElement('body') //use whichever selector you want
.then((element) => {
     console.info(element);
     //Do whatever you want now the element is there
});

Iftah的另一种变体

var counter = 10;
var checkExist = setInterval(function() {
  console.log(counter);
  counter--
  if ($('#the-canvas').length || counter === 0) {
    console.log("by bye!");
    clearInterval(checkExist);
  }
}, 200);

以防元素从未显示,所以我们不进行无限检查。

这是一种纯粹的基于承诺的JavaScript方法,您可以知道需要等待多少毫秒。

    const waitElementFor = function(query, ms = 3000) { // 3000 === 3 seconds
        return new Promise((resolve) => {
            var waited = 0;
            var el = null;
            var wi = setInterval(function() {
                el = document.querySelector(query);
                if (waited >= ms || el) {
                    clearInterval(wi);
                    if(el) {
                        resolve(el);
                    } else {
                        resolve(null);
                    }
                }
                waited += 10;
            }, 10);  
        });
    }

要使用该函数,只需在异步函数中使用以下代码。

var element = await waitElementFor('#elementID');

代码片段:

const waitElementFor = function(query, ms = 3000) { // 3000 === 3 seconds return new Promise((resolve) => { var waited = 0; var el = null; var wi = setInterval(function() { el = document.querySelector(query); if (waited >= ms || el) { clearInterval(wi); if(el) { resolve(el); } else { resolve(null); } } waited += 10; }, 10); }); } async function snippetTestAyncFunction(){ var element = await waitElementFor('#elementID'); console.log(element); } snippetTestAyncFunction();