-->

jQuery: How do I clone a div containing a p5 canva

2019-07-29 02:25发布

问题:

Using jQuery to clone a div:

$(document).ready(function() {
// clicking the buttton
  $(".showcanvas").click(function() {
// cloning and appending the div
    $(".canvas").first().clone(true).appendTo("article").fadeIn("1200");
    });
  });

with a p5 canvas inside that div:

<script>
  var sketch = function(p) {
     p.setup = function(){
       p.createCanvas(100, 100);
       p.background(0);
     }
   };
   new p5(sketch, 'drawing');
</script>

the div clones correctly but the p5 canvas is not there.

how do I clone the div so that the p5 canvas will be inside it?

https://jsfiddle.net/vanderhurk/xpvt214o/896958/

(click on "show canvas" button to see)

回答1:

Your canvas element is being cloned correctly. However, this will not clone any data written to the canvas.

If you wish to clone the state of the canvas without rerunning the code that generated it in the first place, you need to write the content of the original canvas to the newly created canvas.

$(document).ready(function() {
  $(".showcanvas").click(function() {
	
  // Find the original canvas element
  var origCanvas = $(".canvas").first().find('canvas');
  
  // Clone the div wrapper
  var clonedDiv = $(".canvas").first().clone(true);
  
  // Find the cloned canvas
  var clonedCanvas = clonedDiv.find('canvas');
  
  // Update the ID. (IDs should be unique in the document)
  clonedCanvas.prop('id', 'defaultCanvas' + $(".canvas").length)
  
  // Draw the original canvas to the cloned canvas
  clonedCanvas[0].getContext('2d').drawImage(origCanvas[0], 0, 0);
  
  // Append the cloned elements 
  // (Use .hide() before .fadeIn(). The duration should be a number, not a string)
  clonedDiv.appendTo("article").hide().fadeIn(1200);
    
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/p5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/addons/p5.dom.min.js"></script>

<article>
  <button class = "showcanvas">show canvas</button>

  <div class = "canvas">
    <div id = "drawing">
    hi
    </div>
  </div>
</article>

<script>
  var sketch = function(p) {
     p.setup = function(){
       p.createCanvas(100, 100);
       p.background(0);
     }
   };
   new p5(sketch, 'drawing');
</script>

Based on comments below, it does not seem to be possible to clone a canvas with its event handlers attached. To create a fully working canvas like your example I believe you would need to initialise a new instance of p5 for the cloned element.

Example: https://jsfiddle.net/3rror404/12fxj48h/40/



回答2:

It looks like when your canvas is cloned, it inherits the same ID as the original. I suspect that when the javascript is drawing to the canvas, it'll only find the first one with the given id and draw to that. Any others will be ignored. Try changing the id of each canvas on clone. You'll probably also need to let p5 know of the new canvases. I've forked your fiddle here with working cloning to demonstrate the issue; https://jsfiddle.net/12fxj48h/

 $(document).ready(function() { // clicking the buttton  
 $(".showcanvas").click(function() { // cloning and appending the div
    let clone = $(".canvas").first().clone();
    let cloned_canvas = clone.find("canvas");
    cloned_canvas.attr("id", "defaultCanvas1");

    clone.appendTo("article");
    new p5(sketch, 'drawing');      
  });  
});

UPDATE

In fact, it seems you don't need to update the ID (I'd still do it anyway). Just re-running p5 seems to work. https://jsfiddle.net/yfum1xjv/

$(document).ready(function() {
// clicking the buttton
  $(".showcanvas").click(function() {
// cloning and appending the div
    let clone = $(".canvas").first().clone();

    clone.appendTo("article");
    new p5(sketch, 'drawing');
    });
  });