var graph = new joint.dia.Graph(); var paper = new joint.dia.Paper({ el: $('#paper'), width: 600, height: 400, gridSize: 10, drawGrid: true, model: graph, defaultConnectionPoint: { name: 'anchor' } }); var elements = [ new joint.shapes.standard.Path({ position: { x: 75, y: 175 }, size: { width: 100, height: 40 }, attrs: { label: { text: 'joint' }, body: { refD: 'M 0 0 L 100 0 80 20 100 40 0 40 Z' } } }), new joint.shapes.standard.Path({ position: { x: 200, y: 275 }, size: { width: 100, height: 40 }, attrs: { label: { text: 'dia' }, body: { refD: 'M 20 0 L 100 0 80 20 100 40 20 40 0 20 Z' } } }), new joint.shapes.standard.Path({ position: { x: 200, y: 75 }, size: { width: 100, height: 40 }, attrs: { label: { text: 'util' }, body: { refD: 'M 20 0 L 100 0 80 20 100 40 20 40 0 20 Z' } } }), new joint.shapes.standard.Path({ position: { x: 200, y: 175 }, size: { width: 100, height: 40 }, attrs: { label: { text: 'shapes' }, body: { refD: 'M 20 0 L 100 0 80 20 100 40 20 40 0 20 Z' } } }), new joint.shapes.standard.Path({ position: { x: 325, y: 175 }, size: { width: 100, height: 40 }, attrs: { label: { text: 'basic' }, body: { refD: 'M 20 0 L 100 0 80 20 100 40 20 40 0 20 Z' } } }), new joint.shapes.standard.Path({ position: { x: 450, y: 150 }, size: { width: 100, height: 40 }, attrs: { label: { text: 'Path' }, body: { refD: 'M 20 0 L 100 0 100 40 20 40 0 20 Z' } } }), new joint.shapes.standard.Path({ position: { x: 450, y: 200 }, size: { width: 100, height: 40 }, attrs: { label: { text: 'Text' }, body: { refD: 'M 20 0 L 100 0 100 40 20 40 0 20 Z' } } }), new joint.shapes.standard.Path({ position: { x: 325, y: 250 }, size: { width: 100, height: 40 }, attrs: { label: { text: 'Paper' }, body: { refD: 'M 20 0 L 100 0 100 40 20 40 0 20 Z' } } }), new joint.shapes.standard.Path({ position: { x: 325, y: 300 }, size: { width: 100, height: 40 }, attrs: { label: { text: 'Graph' }, body: { refD: 'M 20 0 L 100 0 100 40 20 40 0 20 Z' } } }), new joint.shapes.standard.Path({ position: { x: 325, y: 100 }, size: { width: 100, height: 40 }, attrs: { label: { text: 'getByPath' }, body: { refD: 'M 20 0 L 100 0 100 40 20 40 0 20 Z' } } }), new joint.shapes.standard.Path({ position: { x: 325, y: 50 }, size: { width: 100, height: 40 }, attrs: { label: { text: 'setByPath' }, body: { refD: 'M 20 0 L 100 0 100 40 20 40 0 20 Z' } } }) ]; // add all elements to the graph graph.resetCells(elements); var linkEnds = [ { source: 0, target: 1 }, { source: 0, target: 2 }, { source: 0, target: 3 }, { source: 1, target: 7 }, { source: 1, target: 8 }, { source: 2, target: 9 }, { source: 2, target: 10 }, { source: 3, target: 4 }, { source: 4, target: 5 }, { source: 4, target: 6 } ]; // add all links to the graph linkEnds.forEach(function(ends) { new joint.shapes.standard.Link({ source: { id: elements[ends.source].id }, target: { id: elements[ends.target].id }, z: -1 // make sure all links are displayed under the elements }).addTo(graph); }); // cache important html elements var $ox = $('#ox'); var $oy = $('#oy'); var $sx = $('#sx'); var $sy = $('#sy'); var $w = $('#width'); var $h = $('#height'); var $ftcPadding = $('#ftc-padding'); var $ftcGridW = $('#ftc-grid-width'); var $ftcGridH = $('#ftc-grid-height'); var $ftcNewOrigin = $('#ftc-new-origin'); var $stfPadding = $('#stf-padding'); var $stfMinScale = $('#stf-min-scale'); var $stfMaxScale = $('#stf-max-scale'); var $stfScaleGrid = $('#stf-scale-grid'); var $stfRatio = $('#stf-ratio'); var $bboxX = $('#bbox-x'); var $bboxY = $('#bbox-y'); var $bboxW = $('#bbox-width'); var $bboxH = $('#bbox-height'); var $grid = $('#grid'); // cache important svg elements var svg = V(paper.svg); var svgVertical = V('path').attr('d', 'M -10000 -1 L 10000 -1'); var svgHorizontal = V('path').attr('d', 'M -1 -10000 L -1 10000'); var svgRect = V('rect'); var svgAxisX = svgVertical.clone().addClass('axis'); var svgAxisY = svgHorizontal.clone().addClass('axis'); var svgBBox = svgRect.clone().addClass('bbox'); svgBBox.hide = joint.util.debounce(function() { svgBBox.removeClass('active'); }, 500); // svg Container - contains all non-jointjs svg elements var svgContainer = []; svgContainer.showAll = function() { this.forEach(function(v) { v.addClass('active'); }); }; svgContainer.hideAll = function() { this.forEach(function(v) { v.removeClass('active'); }); }; svgContainer.removeAll = function() { while (this.length > 0) { this.pop().remove(); } }; // Axis has to be appended to the svg, so it won't affect the viewport. svg.append([svgAxisX, svgAxisY, svgBBox]); function fitToContent() { svgContainer.removeAll(); var padding = parseInt($ftcPadding.val(), 10); var gridW = parseInt($ftcGridW.val(), 10); var gridH = parseInt($ftcGridH.val(), 10); var allowNewOrigin = $ftcNewOrigin.val(); paper.fitToContent({ padding: padding, gridWidth: gridW, gridHeight: gridH, allowNewOrigin: allowNewOrigin }); var bbox = paper.getContentBBox(); var translatedX = allowNewOrigin == 'any' || (allowNewOrigin == 'positive' && bbox.x - paper.options.origin.x >= 0) || (allowNewOrigin == 'negative' && bbox.x - paper.options.origin.x < 0); var translatedY = allowNewOrigin == 'any' || (allowNewOrigin == 'positive' && bbox.y - paper.options.origin.y >= 0) || (allowNewOrigin == 'negative' && bbox.y - paper.options.origin.y < 0); if (padding) { var svgPaddingRight = svgHorizontal.clone().addClass('padding') .translate(paper.options.width - padding / 2, 0, { absolute: true }) .attr('stroke-width', padding); var svgPaddingBottom = svgVertical.clone().addClass('padding') .translate(0, paper.options.height - padding / 2, { absolute: true }) .attr('stroke-width', padding); svg.append([svgPaddingBottom, svgPaddingRight]); svgContainer.push(svgPaddingBottom, svgPaddingRight); } if (padding && (translatedX || translatedY)) { var paddings = []; if (translatedY) { var svgPaddingTop = svgVertical.clone().addClass('padding') .translate(0, padding / 2, { absolute: true }) .attr('stroke-width', padding); paddings.push(svgPaddingTop); } if (translatedX) { var svgPaddingLeft = svgHorizontal.clone().addClass('padding') .translate(padding / 2, 0, { absolute: true }) .attr('stroke-width', padding); paddings.push(svgPaddingLeft); } if (paddings.length) { svg.append(paddings); svgContainer.push.apply(svgContainer, paddings); } } if (gridW > 2) { var x = gridW; if (translatedX) x += padding; do { var svgGridX = svgHorizontal.clone().translate(x, 0, { absolute: true }).addClass('grid'); svg.append(svgGridX); svgContainer.push(svgGridX); x += gridW; } while (x < paper.options.width - padding); } if (gridH > 2) { var y = gridH; if (translatedY) y += padding; do { var svgGridY = svgVertical.clone().translate(0, y, { absolute: true }).addClass('grid'); svg.append(svgGridY); svgContainer.push(svgGridY); y += gridH; } while (y < paper.options.height - padding); } svgContainer.showAll(); } function scaleToFit() { svgContainer.removeAll(); var padding = parseInt($stfPadding.val(), 10); paper.scaleContentToFit({ padding: padding, minScale: parseFloat($stfMinScale.val()), maxScale: parseFloat($stfMaxScale.val()), scaleGrid: parseFloat($stfScaleGrid.val()), preserveAspectRatio: $stfRatio.is(':checked') }); paper.viewport.getBoundingClientRect(); // MS Edge hack to fix the invisible text. if (padding) { var svgPaddingRight = svgHorizontal.clone().addClass('padding') .translate(paper.options.width - padding / 2, 0, { absolute: true }) .attr('stroke-width', padding); var svgPaddingBottom = svgVertical.clone().addClass('padding') .translate(0, paper.options.height - padding / 2, { absolute: true }) .attr('stroke-width', padding); var svgPaddingLeft = svgVertical.clone().addClass('padding') .translate(0, padding / 2, { absolute: true }) .attr('stroke-width', padding); var svgPaddingTop = svgHorizontal.clone().addClass('padding') .translate(padding / 2, 0, { absolute: true }) .attr('stroke-width', padding); svg.append([svgPaddingBottom, svgPaddingRight, svgPaddingTop, svgPaddingLeft]); svgContainer.push(svgPaddingBottom, svgPaddingRight, svgPaddingTop, svgPaddingLeft); } svgContainer.showAll(); } function updateBBox() { var bbox = paper.getContentBBox(); $bboxX.text(Math.round(bbox.x - paper.options.origin.x)); $bboxY.text(Math.round(bbox.y - paper.options.origin.y)); $bboxW.text(Math.round(bbox.width)); $bboxH.text(Math.round(bbox.height)); svgBBox.attr(bbox).addClass('active').hide(); } /* events */ $('#fit-to-content input, #fit-to-content select').on('input change', fitToContent); $('#scale-to-fit input').on('input change', scaleToFit); $ox.on('input change', function() { paper.setOrigin(parseInt(this.value, 10), parseInt($oy.val(), 10)); }); $oy.on('input change', function() { paper.setOrigin(parseInt($ox.val(), 10), parseInt(this.value, 10)); }); $sx.on('input change', function() { paper.scale(parseFloat(this.value), parseFloat($sy.val())); }); $sy.on('input change', function() { paper.scale(parseFloat($sx.val()), parseFloat(this.value)); }); $w.on('input change', function() { paper.setDimensions(parseInt(this.value, 10), parseInt($h.val(),10)); }); $h.on('input change', function() { paper.setDimensions(parseInt($w.val(), 10), parseInt(this.value, 10)); }); $grid.on('input change', function() { paper.options.gridSize = this.value; paper.drawGrid(); }); $('.range').on('input change', function() { $(this).next().text(this.value); }); paper.on({ scale: function(sx, sy) { $sx.val(sx).next().text(sx.toFixed(2)); $sy.val(sy).next().text(sy.toFixed(2)); svgContainer.hideAll(); }, translate: function(ox, oy) { $ox.val(ox).next().text(Math.round(ox)); $oy.val(oy).next().text(Math.round(oy)); // translate axis svgAxisX.translate(0, oy, { absolute: true }); svgAxisY.translate(ox, 0, { absolute: true }); svgContainer.hideAll(); }, resize: function(width, height) { $w.val(width).next().text(Math.round(width)); $h.val(height).next().text(Math.round(height)); svgContainer.hideAll(); } }); graph.on('change', function() { svgContainer.hideAll(); updateBBox(); }); updateBBox(); var bgImageDataURL = 'data:image/png;base64,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'; $('#bg-toggle, #bg-color, #bg-repeat, #bg-opacity, #bg-size, #bg-position').on('change input', function() { paper.drawBackground({ color: $('#bg-color').val(), image: $('#bg-toggle').is(':checked') ? bgImageDataURL : '', position: JSON.parse($('#bg-position').val().replace(/'/g, '"')), size: JSON.parse($('#bg-size').val().replace(/'/g, '"')), repeat: $('#bg-repeat').val(), opacity: $('#bg-opacity').val() }); }); var _inputRenderer = function(gridTypes, onChange) { var currentOpt = {}; var formTypes = { 'color': function(inputDef, container) { var input = $('', { type: 'color' }).val(inputDef.value).on('change input', function() { inputDef.onChange($(this).val(), currentOpt); onChange(currentOpt); }).trigger('change'); container.append($('').text(inputDef.name)); container.append(input); }, 'number': function(inputDef, container) { var input = $('', { type: 'range' }) .val(inputDef.value) .attr({ step: inputDef.step, min: inputDef.min, max: inputDef.max }) .on('change input', function() { var value = parseFloat($(this).val()).toFixed(2); $('output', $(this).parent()).text(value); inputDef.onChange(value, currentOpt); onChange(currentOpt); }).trigger('change'); container.append($('').text(inputDef.name)); container.append(input); container.append($('').text(input.val())); } }; var renderInput = function(formType, container) { return formTypes[formType.type](formType, container); }; return { renderSettings: function(gridTypeName) { currentOpt.name = gridTypeName; currentOpt.args = [{}, {}]; gridTypes[gridTypeName].inputs.forEach(function(x) { var element = $('
').addClass('form-group').appendTo($gridTypesOpt); renderInput(x, element); }); onChange(currentOpt); } }; }; var gridTypes = { 'dot': { inputs: [{ type: 'color', name: 'Color', value: '#000000', onChange: function(value, ref) { ref.args[0].color = value; } }, { type: 'number', name: 'Thickness', value: 1, step: 0.5, min: 0.5, max: 10, onChange: function(value, ref) { ref.args[0].thickness = value; } }] }, 'fixedDot': { inputs: [{ type: 'color', name: 'Color', value: '#000000', onChange: function(value, ref) { ref.args[0].color = value; } }, { type: 'number', name: 'Thickness', value: 1, step: 0.5, min: 0.5, max: 10, onChange: function(value, ref) { ref.args[0].thickness = value; } }] }, 'mesh': { inputs: [{ type: 'color', name: 'Color', value: '#000000', onChange: function(value, ref) { ref.args[0].color = value; } }, { type: 'number', prop: 'thickness', name: 'Thickness', value: 1, step: 0.5, min: 0.5, max: 10, onChange: function(value, ref) { ref.args[0].thickness = value; } }] }, 'doubleMesh': { inputs: [{ type: 'color', name: 'Primary Color', value: '#AAAAAA', onChange: function(value, ref) { ref.args[0].color = value; } }, { type: 'number', name: 'Primary Thickness', value: 1, step: 0.5, min: 0.5, max: 5, onChange: function(value, ref) { ref.args[0].thickness = value; } }, { type: 'color', name: 'Secondary Color', value: '#000000', onChange: function(value, ref) { ref.args[1].color = value; } }, { type: 'number', name: 'Secondary Thickness', value: 3, step: 0.5, min: 0.5, max: 5, onChange: function(value, ref) { ref.args[1].thickness = value; } }, { type: 'number', name: 'Scale Factor', value: 5, step: 1, min: 1, max: 10, onChange: function(value, ref) { ref.args[1].scaleFactor = value; } }] } }; var renderer = _inputRenderer(gridTypes, function(gridOpt) { paper.setGrid(gridOpt); paper.drawGrid(); }); var $gridTypesOpt = $('.grid-types-opt'); $('#grid-type').on('change input', function() { $gridTypesOpt.empty(); renderer.renderSettings($(this).val()); }); renderer.renderSettings($('#grid-type').val());