Skip to content

Commit

Permalink
support clone canvas
Browse files Browse the repository at this point in the history
  • Loading branch information
zjffun committed Apr 22, 2020
1 parent f8c4e1c commit fed7f66
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 3 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-preset-shopify": "^16.5.0",
"canvas": "^1.6.13",
"codecov": "^3.0.2",
"concurrently": "^3.5.1",
"core-js": "^2.5.7",
Expand Down
4 changes: 2 additions & 2 deletions src/Draggable/Draggable.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {closest} from 'shared/utils';
import {closest, cloneNode} from 'shared/utils';

import {Announcement, Focusable, Mirror, Scrollable} from './Plugins';

Expand Down Expand Up @@ -374,7 +374,7 @@ export default class Draggable {
this.lastPlacedContainer.classList.remove(this.getClassNameFor('container:placed'));
}

this.source = this.originalSource.cloneNode(true);
this.source = cloneNode(this.originalSource, true);
this.originalSource.parentNode.insertBefore(this.source, this.originalSource);
this.originalSource.style.display = 'none';

Expand Down
3 changes: 2 additions & 1 deletion src/Draggable/Plugins/Mirror/Mirror.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import AbstractPlugin from 'shared/AbstractPlugin';
import {cloneNode} from 'shared/utils';

import {
MirrorCreateEvent,
Expand Down Expand Up @@ -163,7 +164,7 @@ export default class Mirror extends AbstractPlugin {
}

const appendableContainer = this[getAppendableContainer](source) || sourceContainer;
this.mirror = source.cloneNode(true);
this.mirror = cloneNode(source, true);

const mirrorCreatedEvent = new MirrorCreatedEvent({
source,
Expand Down
23 changes: 23 additions & 0 deletions src/shared/utils/cloneNode/cloneNode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Get the new clone with canvas content cloned for a given node.
*
* @param {Node} node The node to clone
* @param {Boolean} deep equal to the deep parameter of Node.cloneNode(), default false
* @return {Node} new clone with canvas content cloned
*/
export default function cloneNode(node, deep = false) {
const newClone = node.cloneNode(deep);
let canvases;
let newCanvases;
if (node.tagName === 'CANVAS') {
canvases = [node];
newCanvases = [newClone];
} else {
canvases = node.querySelectorAll('canvas');
newCanvases = newClone.querySelectorAll('canvas');
}
[...newCanvases].forEach((newCanvas, i) => {
newCanvas.getContext('2d').drawImage(canvases[i], 0, 0);
});
return newClone;
}
3 changes: 3 additions & 0 deletions src/shared/utils/cloneNode/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import cloneNode from './cloneNode';

export default cloneNode;
65 changes: 65 additions & 0 deletions src/shared/utils/cloneNode/tests/cloneNode.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import {createSandbox} from 'helper';
import cloneNode from '../cloneNode';

const sampleMarkup = `
<div class="CanvasContainer">
<div class="FirstDiv">First</div>
<canvas class="FirstCanvas" width="100" height="100"></canvas>
<div class="SecondDiv">Second</div>
<canvas class="SecondCanvas" widht="100" height="100"></canvas>
</div>
`;

describe('utils', () => {
let sandbox;
let canvasContainer;
let firstCanvas;
let secondCanvas;
let firstDiv;
let secondDiv;

beforeEach(() => {
sandbox = createSandbox(sampleMarkup);
canvasContainer = sandbox.querySelector('.CanvasContainer');
firstCanvas = canvasContainer.querySelector('.FirstCanvas');
secondCanvas = canvasContainer.querySelector('.SecondCanvas');
firstDiv = canvasContainer.querySelector('.FirstDiv');
secondDiv = canvasContainer.querySelector('.SecondDiv');

const firstCtx = firstCanvas.getContext('2d');
const secondCtx = secondCanvas.getContext('2d');

firstCtx.fillRect(0, 0, 10, 10);
secondCtx.fillRect(10, 10, 20, 20);
});

afterEach(() => {
sandbox.parentNode.removeChild(sandbox);
});

it('clone canvas content when cloned node has canvas elements', () => {
const newClone = cloneNode(canvasContainer, true);
const newFirstCanvas = newClone.querySelector('.FirstCanvas');
const newSecondCanvas = newClone.querySelector('.SecondCanvas');
expect(newFirstCanvas.toDataURL()).toEqual(firstCanvas.toDataURL());
expect(newSecondCanvas.toDataURL()).toEqual(secondCanvas.toDataURL());
});

it('clone nodes when cloned node has canvas elements', () => {
const newClone = cloneNode(canvasContainer, true);
const newFirstDiv = newClone.querySelector('.FirstDiv');
const newSecondDiv = newClone.querySelector('.SecondDiv');
expect(newFirstDiv.innerHTML).toEqual(firstDiv.innerHTML);
expect(newSecondDiv.innerHTML).toEqual(secondDiv.innerHTML);
});

it('clone canvas content when cloned node is canvas', () => {
const newCanvas = cloneNode(firstCanvas, true);
expect(newCanvas.toDataURL()).toEqual(firstCanvas.toDataURL());
});

it('not clone child nodes when deep is false', () => {
const newClone = cloneNode(canvasContainer);
expect(newClone.childNodes).toHaveLength(0);
});
});
1 change: 1 addition & 0 deletions src/shared/utils/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export {default as closest} from './closest';
export {default as requestNextAnimationFrame} from './requestNextAnimationFrame';
export {default as distance} from './distance';
export {default as cloneNode} from './cloneNode';

0 comments on commit fed7f66

Please sign in to comment.