Skip to content

Commit 1d392a1

Browse files
authored
refactor(dia.Paper)!: add SVG grid layer (#2458)
1 parent ee3e219 commit 1d392a1

File tree

9 files changed

+262
-236
lines changed

9 files changed

+262
-236
lines changed

packages/joint-core/demo/paper/src/paper.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -367,8 +367,7 @@ $h.on('input change', function() {
367367
paper.setDimensions(parseInt($w.val(), 10), parseInt(this.value, 10));
368368
});
369369
$grid.on('input change', function() {
370-
paper.options.gridSize = this.value;
371-
paper.drawGrid();
370+
paper.setGridSize(this.value);
372371
});
373372
$('.range').on('input change', function() {
374373
$(this).next().text(this.value);
@@ -548,7 +547,6 @@ var gridTypes = {
548547
var renderer = _inputRenderer(gridTypes, function(gridOpt) {
549548

550549
paper.setGrid(gridOpt);
551-
paper.drawGrid();
552550
});
553551

554552
var $gridTypesOpt = $('.grid-types-opt');

packages/joint-core/docs/src/joint/api/dia/Paper/prototype/clearGrid.html

Lines changed: 0 additions & 3 deletions
This file was deleted.

packages/joint-core/docs/src/joint/api/dia/Paper/prototype/drawGrid.html

Lines changed: 0 additions & 7 deletions
This file was deleted.

packages/joint-core/docs/src/joint/api/dia/Paper/prototype/setGrid.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<pre class="docs-method-signature"><code>paper.setGrid(gridOption)</code></pre>
2-
<p>Set the type of visual grid on the paper. Note, you still have to call <code>paper.drawGrid()</code> afterwards to draw the grid.</p>
2+
<p>Set the type of visual grid on the paper. If a falsy value is provided, the grid is removed.</p>
33

4-
<pre><code>paper.setGrid(); // default pattern (dot) with default settings
4+
<pre><code>paper.setGrid(); // removes the grid visual
55
paper.setGrid(true); // default pattern (dot) with default settings
66

77
paper.setGrid('mesh'); // pre-defined pattern with default settings

packages/joint-core/src/dia/Paper.mjs

Lines changed: 31 additions & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import {
2121
debounce,
2222
omit,
2323
result,
24-
merge,
2524
camelCase,
2625
cloneDeep,
2726
invoke,
@@ -46,6 +45,7 @@ import * as connectionPoints from '../connectionPoints/index.mjs';
4645
import * as anchors from '../anchors/index.mjs';
4746

4847
import $ from '../mvc/Dom/index.mjs';
48+
import { GridLayer } from './layers/GridLayer.mjs';
4949

5050
const sortingTypes = {
5151
NONE: 'sorting-none',
@@ -83,6 +83,8 @@ const defaultHighlighting = {
8383
};
8484

8585
const defaultLayers = [{
86+
name: LayersNames.GRID,
87+
}, {
8688
name: LayersNames.BACK,
8789
}, {
8890
name: LayersNames.CELLS,
@@ -395,7 +397,6 @@ export const Paper = View.extend({
395397
// Layers (SVGGroups)
396398
this._layers = {};
397399

398-
this.setGrid(options.drawGrid);
399400
this.cloneOptions();
400401
this.render();
401402
this._setDimensions();
@@ -556,15 +557,6 @@ export const Paper = View.extend({
556557
position: 'absolute',
557558
inset: 0
558559
}
559-
}, {
560-
namespaceURI: ns.xhtml,
561-
tagName: 'div',
562-
className: addClassNamePrefix('paper-grid'),
563-
selector: 'grid',
564-
style: {
565-
position: 'absolute',
566-
inset: 0
567-
}
568560
}, {
569561
namespaceURI: ns.svg,
570562
tagName: 'svg',
@@ -629,7 +621,7 @@ export const Paper = View.extend({
629621
}
630622

631623
if (options.drawGrid) {
632-
this.drawGrid();
624+
this.setGrid(options.drawGrid);
633625
}
634626

635627
return this;
@@ -640,11 +632,20 @@ export const Paper = View.extend({
640632
V(this.svg).prepend(V.createSVGStyle(css));
641633
},
642634

635+
createLayer(name) {
636+
switch (name) {
637+
case LayersNames.GRID:
638+
return new GridLayer({ name, paper: this, patterns: this.constructor.gridPatterns });
639+
default:
640+
return new PaperLayer({ name });
641+
}
642+
},
643+
643644
renderLayers: function(layers = defaultLayers) {
644645
this.removeLayers();
645646
// TODO: Layers to be read from the graph `layers` attribute
646647
layers.forEach(({ name, sorted }) => {
647-
const layerView = new PaperLayer({ name });
648+
const layerView = this.createLayer(name);
648649
this.layers.appendChild(layerView.el);
649650
this._layers[name] = layerView;
650651
});
@@ -681,10 +682,6 @@ export const Paper = View.extend({
681682

682683
update: function() {
683684

684-
if (this.options.drawGrid) {
685-
this.drawGrid();
686-
}
687-
688685
if (this._background) {
689686
this.updateBackgroundImage(this._background);
690687
}
@@ -1810,7 +1807,7 @@ export const Paper = View.extend({
18101807
}
18111808

18121809
const { options } = this;
1813-
const { origin, drawGrid } = options;
1810+
const { origin } = options;
18141811

18151812
// setter
18161813
tx || (tx = 0);
@@ -1828,11 +1825,6 @@ export const Paper = View.extend({
18281825
origin.y = oy;
18291826

18301827
this.trigger('translate', ox, oy);
1831-
1832-
if (drawGrid) {
1833-
this.drawGrid();
1834-
}
1835-
18361828
return this;
18371829
},
18381830

@@ -2639,155 +2631,17 @@ export const Paper = View.extend({
26392631
},
26402632

26412633
setGridSize: function(gridSize) {
2642-
26432634
const { options } = this;
26442635
options.gridSize = gridSize;
2645-
26462636
if (options.drawGrid && !options.drawGridSize) {
26472637
// Do not redraw the grid if the `drawGridSize` is set.
2648-
this.drawGrid();
2649-
}
2650-
2651-
return this;
2652-
},
2653-
2654-
clearGrid: function() {
2655-
2656-
const { childNodes } = this;
2657-
if (childNodes && childNodes.grid) {
2658-
childNodes.grid.style.backgroundImage = '';
2638+
this.getLayerView(LayersNames.GRID).renderGrid();
26592639
}
26602640
return this;
26612641
},
26622642

2663-
_getGridRefs: function() {
2664-
2665-
if (!this._gridCache) {
2666-
2667-
this._gridCache = {
2668-
root: V('svg', { width: '100%', height: '100%' }, V('defs')),
2669-
patterns: {},
2670-
add: function(id, vel) {
2671-
V(this.root.node.childNodes[0]).append(vel);
2672-
this.patterns[id] = vel;
2673-
this.root.append(V('rect', { width: '100%', height: '100%', fill: 'url(#' + id + ')' }));
2674-
},
2675-
get: function(id) {
2676-
return this.patterns[id];
2677-
},
2678-
exist: function(id) {
2679-
return this.patterns[id] !== undefined;
2680-
}
2681-
};
2682-
}
2683-
2684-
return this._gridCache;
2685-
},
2686-
26872643
setGrid: function(drawGrid) {
2688-
2689-
this.clearGrid();
2690-
2691-
this._gridCache = null;
2692-
this._gridSettings = [];
2693-
2694-
var optionsList = Array.isArray(drawGrid) ? drawGrid : [drawGrid || {}];
2695-
optionsList.forEach(function(item) {
2696-
this._gridSettings.push.apply(this._gridSettings, this._resolveDrawGridOption(item));
2697-
}, this);
2698-
return this;
2699-
},
2700-
2701-
_resolveDrawGridOption: function(opt) {
2702-
2703-
var namespace = this.constructor.gridPatterns;
2704-
if (isString(opt) && Array.isArray(namespace[opt])) {
2705-
return namespace[opt].map(function(item) {
2706-
return assign({}, item);
2707-
});
2708-
}
2709-
2710-
var options = opt || { args: [{}] };
2711-
var isArray = Array.isArray(options);
2712-
var name = options.name;
2713-
2714-
if (!isArray && !name && !options.markup) {
2715-
name = 'dot';
2716-
}
2717-
2718-
if (name && Array.isArray(namespace[name])) {
2719-
var pattern = namespace[name].map(function(item) {
2720-
return assign({}, item);
2721-
});
2722-
2723-
var args = Array.isArray(options.args) ? options.args : [options.args || {}];
2724-
2725-
defaults(args[0], omit(opt, 'args'));
2726-
for (var i = 0; i < args.length; i++) {
2727-
if (pattern[i]) {
2728-
assign(pattern[i], args[i]);
2729-
}
2730-
}
2731-
return pattern;
2732-
}
2733-
2734-
return isArray ? options : [options];
2735-
},
2736-
2737-
drawGrid: function(opt) {
2738-
2739-
const gridSize = this.options.drawGridSize || this.options.gridSize;
2740-
if (gridSize <= 1) {
2741-
return this.clearGrid();
2742-
}
2743-
2744-
var localOptions = Array.isArray(opt) ? opt : [opt];
2745-
2746-
var ctm = this.matrix();
2747-
var refs = this._getGridRefs();
2748-
2749-
this._gridSettings.forEach(function(gridLayerSetting, index) {
2750-
2751-
var id = 'pattern_' + index;
2752-
var options = merge(gridLayerSetting, localOptions[index], {
2753-
sx: ctm.a || 1,
2754-
sy: ctm.d || 1,
2755-
ox: ctm.e || 0,
2756-
oy: ctm.f || 0
2757-
});
2758-
2759-
options.width = gridSize * (ctm.a || 1) * (options.scaleFactor || 1);
2760-
options.height = gridSize * (ctm.d || 1) * (options.scaleFactor || 1);
2761-
2762-
if (!refs.exist(id)) {
2763-
refs.add(id, V('pattern', { id: id, patternUnits: 'userSpaceOnUse' }, V(options.markup)));
2764-
}
2765-
2766-
var patternDefVel = refs.get(id);
2767-
2768-
if (isFunction(options.update)) {
2769-
options.update(patternDefVel.node.childNodes[0], options);
2770-
}
2771-
2772-
var x = options.ox % options.width;
2773-
if (x < 0) x += options.width;
2774-
2775-
var y = options.oy % options.height;
2776-
if (y < 0) y += options.height;
2777-
2778-
patternDefVel.attr({
2779-
x: x,
2780-
y: y,
2781-
width: options.width,
2782-
height: options.height
2783-
});
2784-
});
2785-
2786-
var patternUri = new XMLSerializer().serializeToString(refs.root.node);
2787-
patternUri = 'url(data:image/svg+xml;base64,' + btoa(patternUri) + ')';
2788-
2789-
this.childNodes.grid.style.backgroundImage = patternUri;
2790-
2644+
this.getLayerView(LayersNames.GRID).setGrid(drawGrid);
27912645
return this;
27922646
},
27932647

@@ -3250,10 +3104,10 @@ export const Paper = View.extend({
32503104
color: '#AAAAAA',
32513105
thickness: 1,
32523106
markup: 'rect',
3253-
update: function(el, opt) {
3107+
render: function(el, opt) {
32543108
V(el).attr({
3255-
width: opt.thickness * opt.sx,
3256-
height: opt.thickness * opt.sy,
3109+
width: opt.thickness,
3110+
height: opt.thickness,
32573111
fill: opt.color
32583112
});
32593113
}
@@ -3262,16 +3116,21 @@ export const Paper = View.extend({
32623116
color: '#AAAAAA',
32633117
thickness: 1,
32643118
markup: 'rect',
3265-
update: function(el, opt) {
3266-
var size = opt.sx <= 1 ? opt.thickness * opt.sx : opt.thickness;
3267-
V(el).attr({ width: size, height: size, fill: opt.color });
3119+
render: function(el, opt) {
3120+
V(el).attr({ fill: opt.color });
3121+
},
3122+
update: function(el, opt, paper) {
3123+
const { sx, sy } = paper.scale();
3124+
const width = sx <= 1 ? opt.thickness : opt.thickness / sx;
3125+
const height = sy <= 1 ? opt.thickness : opt.thickness / sy;
3126+
V(el).attr({ width, height });
32683127
}
32693128
}],
32703129
mesh: [{
32713130
color: '#AAAAAA',
32723131
thickness: 1,
32733132
markup: 'path',
3274-
update: function(el, opt) {
3133+
render: function(el, opt) {
32753134

32763135
var d;
32773136
var width = opt.width;
@@ -3291,7 +3150,7 @@ export const Paper = View.extend({
32913150
color: '#AAAAAA',
32923151
thickness: 1,
32933152
markup: 'path',
3294-
update: function(el, opt) {
3153+
render: function(el, opt) {
32953154

32963155
var d;
32973156
var width = opt.width;
@@ -3311,7 +3170,7 @@ export const Paper = View.extend({
33113170
thickness: 3,
33123171
scaleFactor: 4,
33133172
markup: 'path',
3314-
update: function(el, opt) {
3173+
render: function(el, opt) {
33153174

33163175
var d;
33173176
var width = opt.width;

packages/joint-core/src/dia/PaperLayer.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { View } from '../mvc/index.mjs';
22
import { addClassNamePrefix } from '../util/util.mjs';
33

44
export const LayersNames = {
5+
GRID: 'grid',
56
CELLS: 'cells',
67
BACK: 'back',
78
FRONT: 'front',

0 commit comments

Comments
 (0)