在“动态”画布上绘图

Posted

技术标签:

【中文标题】在“动态”画布上绘图【英文标题】:Drawing on a "dynamic" canvas 【发布时间】:2020-10-12 10:32:47 【问题描述】:

所以我有一个循环,可以根据 jquery 的某些参数创建画布。 代码如下:

var Game = 
    cards: [],
    $board: $('[data-display="game-board"]'),

    deal: function() 
     var self = this;
     var dealRequest = $.ajax(
        url: 'set.php?action=deal',
        type: 'GET',
        dataType: 'json',
        success: function(data) 
            self.cards = data;
            self.displayCards.call(self);
            self.existingSet(data);
            self.setCardListeners();
            self.setPageListeners();
        
     );
   ,

    displayCards: function() 
     var self = this;
     $.each(this.cards, function(index, card) 
       var cardNode = $('<div>');
       cardNode.addClass('card');
       $(cardNode).data(
         'id': card.id,
         'shape': card.shape,
         'fill': card.fill,
         'color': card.color,
         'number': card.number
       );
     
   var shapeNode = $("<canvas></canvas>");
   shapeNode.addClass('shape ' + card.color + ' ' + card.shape + ' ' + card.fill);

   for (var i = 0; i < card.number; i++) 
     cardNode.append(shapeNode.clone());
   
   self.$board.append(cardNode);
    
   // display 4 cards per row
   if ((index+1) % 3 === 0) 
    self.$board.append($('<div>'));
   
;

然后我尝试从我的 html 中恢复这些使用 css 类的名称创建的画布,例如:

var canvases = document.getElementsByClassName('shape diamond red solid');

但是当我尝试在这些画布中绘制时,没有显示任何内容。我会这样做:

var canvases = document.getElementsByClassName('shape red diamond solid');
for (let canvas of canvases) 
    var context = canvas.getContext('2d');
    drawDiamond(context, 50, 50, 75, 100);
    canvas.fillStyle("#FF0000");
    ctx.fillRect(0, 0, canvas.width, canvas.height);

但是当我静态地创建一个画布时。

您能帮我找出问题或解决方案吗?谢谢!

【问题讨论】:

我看不到您将画布附加到文档的哪个位置,因此它不是您可以“获取”的元素。 我还是个 javascript 初学者,我对它知之甚少。你能告诉我怎么做吗? 【参考方案1】:

建议以下代码:

$.each(this.cards, function(index, card) 
  var cardNode = $('<div>', 
    class: "card"
  ).appendTo("body");
  cardNode.data(card);
  var shapeNode = $('<canvas>', 
    class: "shape " + card.color + " " + card.shape + " " + card.fill
  ).appendTo(cardNode);
);

一旦完成,以下应该可以工作:

var canvases = $('.shape.red.diamond.solid');

canvases.each(function(i, c) 
    var context = c.getContext('2d');

    drawDiamond(context, 50, 50, 75, 100);
    c.fillStyle("#FF0000");
    ctx.fillRect(0, 0, c.width, c.height);
);

更新

您的示例更彻底,但它不是一个最小的、可重现的示例。请考虑以下内容。

var Game = 
  cards: [],
  $board: $('[data-display="game-board"]'),
  deal: function() 
    var self = this;
    /*
    $.getJSON('set.php?action=deal', function(data) 
      $.each(data, function(i, card) 
        self.cards.push(card);
      );
      self.displayCards();
      self.existingSet(data);
      self.setCardListeners();
      self.setPageListeners();
    );
    */
    self.cards.push(
      id: "ace-spade",
      shape: "spade",
      fill: "solid",
      color: "black",
      number: 1
    );
    self.displayCards();
  ,
  displayCards: function() 
    var self = this;
    if (self.cards.length == 0) 
      return false;
    
    $.each(self.cards, function(index, card) 
      var cardNode = $('<div>', 
        class: "card"
      ).appendTo(self.$board);
      cardNode.data(
        'id': card.id,
        'shape': card.shape,
        'fill': card.fill,
        'color': card.color,
        'number': card.number
      );

      for (var i = 0; i < card.number; i++) 
        cardNode.append($("<canvas>", 
          class: 'shape ' + card.color + ' ' + card.shape + ' ' + card.fill
        ));
      
      self.$board.append(cardNode);

      // display 4 cards per row
      if ((index + 1) % 3 === 0) 
        self.$board.append($('<div>'));
      
    );
  
;

Game.deal();
.card 
  border: 1px solid #000;
  border-radius: 6px;
  width: 100px;
  height: 175px;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div data-display="game-board"></div>

我无法使用 AJAX 进行测试,因此我用黑桃 A 填充了“套牌”。生成的 HTML 是:

<div data-display="game-board">
  <div class="card">
    <canvas class="shape black spade solid"></canvas>
  </div>
</div>

您需要在自己的代码中进一步测试。如果需要,请进一步更新您的问题。

【讨论】:

我不知道为什么,但它不起作用。此外,当我执行 console.log(canvases) 时,也没有显示任何内容。 @redkoo 那么您需要提供一个最小的、可重现的示例:***.com/help/minimal-reproducible-example @redkoo 我更新了我的答案。没有适当的例子,我无法完全解决您的问题。希望这能让你朝着正确的方向前进。如果它解决了这一部分,您可以将其标记为答案(并投票)。如果之后您需要更多帮助,可以考虑提出一个新问题。 感谢您的回答。我有最后一个问题:当我尝试执行 $.getJSON 时,它不会显示我的形状,因为当我执行 var canvases = $('.shape');它仍然是空的,但是当我静态推卡时它可以工作。你怎么看? @redkoo 无法理解您的意思。如果我的回答解决了您最初的问题,请标记并投票。我建议您进一步研究它,如果需要,发布新问题的新问题。

以上是关于在“动态”画布上绘图的主要内容,如果未能解决你的问题,请参考以下文章

Wpf依赖属性动态键向下

带有查询字符串的 JavaScript 文件,用于在 img src 中动态生成画布作为 png 图像

无法在多个画布上绘制

使用vue学习three.js之加载和使用纹理-使用canvas画布上的绘画作为纹理渲染到方块上,使用动态绘画纹理

重点突破——SVG技术动态随机绘制圆形

只需要一些关于画布上动态可拖动输入元素的指导