Javascript'这个'传递画布以在页面加载时起作用

时间:2017-05-31 04:12:34

标签: javascript html canvas this

我正在尝试将画布HTML元素作为参数传递,我想这个'这个'会工作,但我不能得到它。有人可以帮助我使用这个'这个'在页面加载时将画布传递给main()的关键字,好吗?

不能工作:

<html>
    <head>
    <title>Draw on Canvas</title>
    </head>
    <body onload=main(this.firstChild)><canvas></canvas></body>
    <script>
        function main(canv) {
            cntx = canv.getContext("2d");
            cntx.rect(10, 10, 100, 100);
            cntx.fill();
        }
    </script>
</html>

有效,但想使用&#39;这个&#39;改为关键字:

<html>
    <head>
    <title>Draw on Canvas</title>
    </head>
    <body onload=main(document.body.firstChild)><canvas></canvas></body>
    <script>
        function main(canv) {
            cntx = canv.getContext("2d");
            cntx.rect(10, 10, 100, 100);
            cntx.fill();
        }
    </script>
</html>

不起作用(没有为canvas元素定义onload):

<html>
    <head>
    <title>Draw on Canvas</title>
    </head>
    <body><canvas onload=main(this)></canvas></body>
    <script>
        function main(canv) {
            cntx = canv.getContext("2d");
            cntx.rect(10, 10, 100, 100);
            cntx.fill();
        }
    </script>
</html>

运行,并使用&#39;这个&#39;,但希望代码在不点击的情况下运行:

<html>
    <head>
    <title>Draw on Canvas</title>
    </head>
    <body><canvas onclick=main(this)></canvas></body>
    <script>
        function main(canv) {
            cntx = canv.getContext("2d");
            cntx.rect(10, 10, 100, 100);
            cntx.fill();
        }
    </script>
</html>

4 个答案:

答案 0 :(得分:1)

我建议您考虑采用不同的方法,因为如果您将其整合到HTML标记中,则可能会使整个脚本逻辑的表现力变得复杂。更重要的是,虽然您无法在HTML标记上下文中使用onload来获取窗口之外的任何this,但您可以创建JS函数,这些函数定义为在window.onload之后以您想要的任何方式执行

您已经使用JavaScript来定义画布属性,为什么不在JS中同时创建画布呢!

您还可以看到如何扩展这一功能以打开您在动态创建/附加更多画布的选项。

如果这对您不起作用,请告诉我这是否是一个问题的抽象问题,我可能会更直接地帮助您。

&#13;
&#13;
<html>
    <head>
        <title>Draw on Canvas</title>
    </head>
    <body>

        <script>
            function createCanvasRect(x, y, width, height) {
                var canv = document.createElement('canvas'),
                    cntx = canv.getContext('2d');

                cntx.rect(x, y, width, height);
                cntx.fill();

                return canv;
            }

            function load() {
                var canvas = createCanvasRect(10, 10, 100, 100);

                document.body.appendChild(canvas);
            }

            window.onload = load;
        </script>
    </body>
    
</html>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

试试这个。我从HTML中输出了javascript以获得更清晰的代码。

&#13;
&#13;
function main() {
    console.log(this);
    var cntx = this.getContext("2d");
    cntx.rect(10, 10, 100, 100);
    cntx.fill();
}

window.onload = function() {
    main.call(document.getElementById('main'));
}
&#13;
<html>
    <head>
        <title>Draw on Canvas</title>
    </head>
    <body>
        <canvas id="main"></canvas>
    </body>
</html>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

您的问题在于使用 onload

通常,内联附加的侦听器被调用,就像包装在外部函数中一样, this 设置为调用侦听器的元素。但是,附加到body元素的 onload 侦听器不是这种情况。它们的执行被延迟,并且在全局 / 窗口对象设置为 this 的情况下调用它们。

所以你不能按照你想要的方式使用这个

以下演示了使用 this 作为全局对象调用正文的 load 侦听器,但调用了div的 click 侦听器div元素为 this

<script>
  // Reference to global/window object
  var global = this;
</script>
  
<body onload="console.log(this === global)">
<div onclick="console.log(this.tagName)">clickable div</div>
</body>

答案 3 :(得分:-1)

有很多方法可以做。

Javascript中的元素引用

要访问DOM元素,您需要通过为其提供唯一的id来识别它。

<canvas id="myCanvas"></canvas>

注意id必须是唯一的,如果另一个元素具有相同的ID,浏览器将进入怪癖模式(见下文)

然后,您可以使用其id作为变量名直接访问它。

 var ctx = myCanvas.getContext("2d");

有些人更喜欢使用更慢,更痛苦。

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

或其他人使用

 var ctx = document.querySelector("#myCanvas").getContext("2d");

按顺序获取

所有这些方法都有一个问题。当浏览器解析页面时,它会从上到下一次向DOM添加元素。

如果在要使用的元素上方添加一些脚本,脚本将找不到尚未创建的元素

<canvas id="topCan"></canvas>
<script> // this code is run when the browser finds it
    var ctx = topCan.getContext("2d"); // works as the element has been created
    var ctx1 = botCan.getContext("2d"); // no work as the element does not yet exist
</script>
<canvas id="botCan"></canvas>

所以要确保在元素之后添加脚本(在结束体标记之前看到下面的怪癖模式)

有时候你把脚本放在内容之后很简单。那时你将代码放在你调用load事件的函数中。在将所有元素添加到页面之前,函数中的代码将不会运行。

你如何倾听这个事件取决于你,见下文

组织活动

直接分配事件处理程序被认为是不好的形式

 myCanvas.onclick = function(){};

如果你这样做会更糟糕

 <canvas onclick = "myFuction(this)"></canvas>

与启蒙之路充满了那些说出以下方式的方式

 const canvas = document.querySelector("#myCanvas");   
 canvas.addEventListener("click",myFunction);
 function myFunction(){ /* code */}

以上所有方法都有效,其中没有一个是对还是错,还有其他一些方法。你使用什么方法取决于你,我总是建议你使用你最容易记住和使用的方法。

小心怪癖

但有一些事情你不应该做。原因是一些布局使得浏览器在90年代后期的早期思考它,并且你没有遵循规则(没有人真正知道的规则),以阻止它的自我在同行旁边看起来很愚蠢,它会切换到quirks mode这不好,通常会减慢一切。

可以触发怪癖模式的一件事就是将脚本标记放在不应该的位置。

所以永远不要在身体或头标记之外放置脚本标记

世界和平的道路总是把脚本标签放在他们所属的地方。

<html>
   <head>
      <script></script> <!-- browser is your friend -->
   </head>
   <body>
      <script></script> <!-- browser thinks your great -->
      <p> some content </p>
      <script></script> <!-- and you know everything-->
   </body>
</html>

走向黑暗的道路。将脚本标记放在任何位置,如下所示

<script></script> <!-- wrong -->
<html>
   <script></script> <!-- wrong -->
   <head>

   </head>
   <script></script> <!-- oh so bad -->
   <body>
   </body>
   <script></script> <!-- oh so bad -->
</html>
<script></script> <!-- just playing with fire -->

单程

我如何做取决于目前的潮流

<html>
    <head>
    <title>Draw on Canvas</title>
    </head>
    <body>
        <!-- id the canvas with a unique id -->
        <canvas id = myCanvas></canvas>
        <script>  // script after the element you are accessing
            const ctx = myCanvas.getContext("2d");
            ctx.rect(10, 10, 100, 100);
            ctx.fill();
         </script> <!-- ensure the script is inside the body tag -->
     </body>
</html>