Need to integrate mxGraph with react js - reactjs

Is there any sample or example projects that explain how to integrate mxGraph with react js?

import React, {Component} from "react";
import PropTypes from "prop-types";
import ReactDOM from "react-dom";
import {
mxGraph,
mxParallelEdgeLayout,
mxConstants,
mxEdgeStyle,
mxLayoutManager,
mxCell,
mxGeometry,
mxRubberband,
mxDragSource,
mxKeyHandler,
mxCodec,
mxClient,
mxConnectionHandler,
mxUtils,
mxToolbar,
mxEvent,
mxImage,
mxFastOrganicLayout
} from "mxgraph-js";
class mxGraphGridAreaEditor extends Component {
constructor(props) {
super(props);
this.state = {
};
this.LoadGraph = this
.LoadGraph
.bind(this);
}
LoadGraph(data) {
var container = ReactDOM.findDOMNode(this.refs.divGraph);
var zoomPanel = ReactDOM.findDOMNode(this.refs.divZoom);
// Checks if the browser is supported
if (!mxClient.isBrowserSupported()) {
// Displays an error message if the browser is not supported.
mxUtils.error("Browser is not supported!", 200, false);
} else {
// Disables the built-in context menu
mxEvent.disableContextMenu(container);
// Creates the graph inside the given container
var graph = new mxGraph(container);
// Enables rubberband selection
new mxRubberband(graph);
// Gets the default parent for inserting new cells. This is normally the first
// child of the root (ie. layer 0).
var parent = graph.getDefaultParent();
// Enables tooltips, new connections and panning
graph.setPanning(true);
//graph.setTooltips(true); graph.setConnectable(true);
graph.setEnabled(false);
// Autosize labels on insert where autosize=1
graph.autoSizeCellsOnAdd = true;
// Allows moving of relative cells
graph.isCellLocked = function (cell) {
return this.isCellsLocked();
};
graph.isCellResizable = function (cell) {
var geo = this
.model
.getGeometry(cell);
return geo == null || !geo.relative;
};
// Truncates the label to the size of the vertex
graph.getLabel = function (cell) {
var label = this.labelsVisible
? this.convertValueToString(cell)
: "";
var geometry = this
.model
.getGeometry(cell);
if (!this.model.isCollapsed(cell) && geometry != null && (geometry.offset == null || (geometry.offset.x == 0 && geometry.offset.y == 0)) && this.model.isVertex(cell) && geometry.width >= 2) {
var style = this.getCellStyle(cell);
var fontSize = style[mxConstants.STYLE_FONTSIZE] || mxConstants.DEFAULT_FONTSIZE;
var max = geometry.width / (fontSize * 0.625);
if (max < label.length) {
return label.substring(0, max) + "...";
}
}
return label;
};
// Enables wrapping for vertex labels
graph.isWrapping = function (cell) {
return this
.model
.isCollapsed(cell);
};
// Enables clipping of vertex labels if no offset is defined
graph.isLabelClipped = function (cell) {
var geometry = this
.model
.getGeometry(cell);
return (geometry != null && !geometry.relative && (geometry.offset == null || (geometry.offset.x == 0 && geometry.offset.y == 0)));
};
var layout = new mxParallelEdgeLayout(graph);
// Moves stuff wider apart than usual
layout.forceConstant = 140;
//// Adds cells to the model in a single step
graph
.getModel()
.beginUpdate();
try {
//mxGrapg componnent
var doc = mxUtils.createXmlDocument();
var node = doc.createElement('YES')
node.setAttribute('ComponentID', '[P01]');
var vx = graph.insertVertex(graph.getDefaultParent(), null, node, 240, 40, 150, 30);
var v1 = graph.insertVertex(parent, null, 'Example_Shape_01', 20, 120, 80, 30);
var v2 = graph.insertVertex(parent, null, 'Example_Shape_02', 300, 120, 80, 30);
var v3 = graph.insertVertex(parent, null, 'Example_Shape_03', 620, 180, 80, 30);
var e1 = graph.insertEdge(parent, null, 'Example Edge name_01', v1, v2);
var e2 = graph.insertEdge(parent, null, 'Example Edge name_02', v2, v3);
var e3 = graph.insertEdge(parent, null, 'Example Edge name_02', v1, v3);
// Gets the default parent for inserting new cells. This is normally the first
// child of the root (ie. layer 0).
var parent = graph.getDefaultParent();
// Executes the layout
layout.execute(parent);
//data
} finally {
// Updates the display
graph
.getModel()
.endUpdate();
}
// Automatically handle parallel edges
var layout = new mxParallelEdgeLayout(graph);
var layoutMgr = new mxLayoutManager(graph);
// Enables rubberband (marquee) selection and a handler for basic keystrokes
var rubberband = new mxRubberband(graph);
var keyHandler = new mxKeyHandler(graph);
}
}
render() {
return (
<div className="graph-container" ref="divGraph" id="divGraph"/>
);
}
}
export default mxGraphGridAreaEditor;
NOTE: This code doesn't work properly when you run here. It's a sample guidelines to integrate mxgraph with react js

Here you go:
run:
npm i --save-dev script-loader
npm i mxgraph
on your code:
/* eslint import/no-webpack-loader-syntax: off */
/* eslint no-undef: off */
import mxClient from "script-loader!mxgraph/javascript/mxClient";
and you will have access to all its objects:
export default class DG {
static drawGraph(vertexes){
let container = document.createElement("div")
// Disables the built-in context menu
mxEvent.disableContextMenu(container);
// Creates the graph inside the given container
var graph = new mxGraph(container);;
// Gets the default parent for inserting new cells. This
// is normally the first child of the root (ie. layer 0).
var parent = graph.getDefaultParent();
var selectionCells= [];
// Adds cells to the model in a single step
graph.getModel().beginUpdate();
...
...
If you don't want to use the built-in stylesheets and resources add to your index.html file:
<script type="text/javascript"> var mxLoadResources = false; var mxLoadStylesheets = false;</script>

There is a grunt file in the mxGraph repo which can be useful for you.
First commit message of this file:
Make objects available via CommonJS require, and create a package.json file for npm
For the usage there is the Anchors example (file)
Please share your experience about the integration with us.

The following on codesandbox might be of some help to you:

Related

How to group GLTF element and drag and drop in 3js

Single GLTF element i can drag and drop. but group of element i can't drag. I am using following code
var loader = new THREE.GLTFLoader();
loader.load( 'W3030/W3030.gltf', ( gltf ) => {
gltf.scene.traverse( function( child ) {
if(child.type === "Group")
{
newObject = true;
GLTFobjects.push(child);
}
if ( child.isMesh ) {
child.receiveShadow = true;
child.castShadow = true;
child.material.transparent = true;
child.material.opacity = 1;
}
});
scene.add(GLTFobjects);
gltf.scene.scale.set(1, 1, 1);
});
I'm afraid instances of Group are not supported by DragControls since there is no Group.raycast() method.
You can implement a workaround by replacing groups with invisible meshes. However, instead of setting Object3D.visible to false, you do this for Material.visible. Otherwise the raycasting logic will not perform the intersection test. It's then necessary to use a geometry that is large enough to enclose the respective children.
three.js R110
Hi Thanks for your support. Now i drag.
Use following code to drag multi mesh GLTF. It is Work for me.
var dragobjects =[];
//add following code in init function
var gltfobject = addGLTFObjectIntoScene();
scene.add(gltfobject);
dragControls = new THREE.DragControls(dragobjects, camera, renderer.domElement);
dragControls.addEventListener('dragstart', onDragStart, false);
dragControls.addEventListener('drag', onDrag , false);
dragControls.addEventListener('dragend', onDragEnd, false);
//end init function code
//add following function after or before init function
function drawBox(objectwidth,objectheight,objectdepth){
var geometry, material, box;
geometry = new THREE.BoxGeometry(objectwidth,objectheight,objectdepth);
material = new THREE.MeshBasicMaterial({color: 0xffff00, transparent: true, opacity: 0,depthTest:false});
box = new THREE.Mesh(geometry, material);
dragobjects.push(box);
box.position.set(0, 0, 0);
return box;
};
function addGLTFObjectIntoScene(){
group = new THREE.Group();
var loader = new THREE.GLTFLoader();
loader.load( 'W1230/W1230.gltf', ( gltf ) => {
mesh = gltf.scene;
mesh.scale.set( 30, 30, 30);
var gltfbox = new THREE.Box3().setFromObject( mesh );
var objectwidth = Math.floor(gltfbox.getSize().x);
var objectheight = Math.floor(gltfbox.getSize().y);
var objectdepth = Math.floor(gltfbox.getSize().z);
objectwidth = objectwidth + parseInt(2);
objectheight = objectheight + parseInt(2);
objectdepth = objectdepth + parseInt(1);
mesh.position.set(0, -objectheight/2, 0);
box = drawBox(objectwidth,objectheight,objectdepth);
group.add(box);
group.name = "quadrant";
console.log(mesh);
box.add( mesh);
});
return group;
};

Angular js : TypeError: Cannot read property 'elem' of undefined

I drew a polygon on an image and I want to move it with the mouse click, i have this error and i can not do them have you an idea please. for this problem i used the librairie Two.js and i can not do that
$scope.DrawPolygon = function (id, json)
{
var elem = document.getElementById('ImgCamera' + id);
if (elem != null)
{
elem.innerHTML = "";
var two = new Two({
type: Two.Types.canvas,
fullscreen: false,
width: 640,
height: 480,
}).appendTo(elem);
var canvas = two.renderer.domElement;
var img = $scope.spotCAMImageLoaded[_GetCameraNumberFromPolygonNumber(id)];
var texture = new Two.Texture(img, function () { });
var rect = two.makeRectangle(canvas.width / 2, canvas.height / 2, canvas.width, canvas.height);
rect.fill = texture;
rect.noStroke();
var jsonPoly = null;
var camera = json.Camera2;
if (_GetCameraNumberFromPolygonNumber(id) == 0)
camera = json.Camera1;
if (camera != null)
{
jsonPoly = camera[_GetPolygonNumberFromCameraNumber(id)];
var polygon = two.makePath([new Two.Anchor(jsonPoly.P1.x, jsonPoly.P1.y)
, new Two.Anchor(jsonPoly.P2.x, jsonPoly.P2.y)
, new Two.Anchor(jsonPoly.P3.x, jsonPoly.P3.y)
, new Two.Anchor(jsonPoly.P4.x, jsonPoly.P4.y)])
polygon.fill = "#008bbe";
polygon.opacity = 0.5;
polygon.stroke = "#00435c";
polygon.linewidth = 10;
polygon.renderer.elem.style.cursor = 'pointer';
two.update();
}
}
Not familiar with Two.js and you didn't post any DOM structure, but there's a lot going on in this function. Consider breaking it down into smaller functions. Also use as much angularjs DSL as possible, eg :
use angular.element(<selector) instead of document.<selectorMethod>
use a truthy check of elem if(elem), values of 0 null or undefined will be guarded against, same for the camera check
Unfortunately undefined and null are different values in JavaScript.
In the first statement, document.getElementById('ImgCamera' + id) is returning undefined.
Try changing the first if statement to this:
if (elem != undefined && != null) {

How to use Babylonjs in Reactjs Application?

I have tried import babylonjs in react but its is not working. Does any body know how to import and use the babylonjs in reactjs application.
Thanks.
Not sure if you have found the answer on your own, however there are several ways now as babylon has matured. There is actually a Node package for using babylon.js with react here: https://www.npmjs.com/package/react-babylonjs
Also there is an install guide for React in Babylon.js in the docs:
https://doc.babylonjs.com/resources/babylonjs_and_reactjs
Hope that helps!
Babylon JS is available as npm package. You can easily build a simple React Component around a canvas and Babylon JS
I have created a minimal example with React+ Babylon:
/* Babylon JS is available as **npm** package.
You can easily build a simple `React` Component around a `canvas` and Babylon JS
I have created a minimal example with React+ Babylon:
*/
import React, { Component } from "react";
import * as BABYLON from "babylonjs";
var scene;
var boxMesh;
/**
* Example temnplate of using Babylon JS with React
*/
class BabylonScene extends Component {
constructor(props) {
super(props);
this.state = { useWireFrame: false, shouldAnimate: false };
}
componentDidMount = () => {
// start ENGINE
this.engine = new BABYLON.Engine(this.canvas, true);
//Create Scene
scene = new BABYLON.Scene(this.engine);
//--Light---
this.addLight();
//--Camera---
this.addCamera();
//--Meshes---
this.addModels();
//--Ground---
this.addGround();
// Add Events
window.addEventListener("resize", this.onWindowResize, false);
// Render Loop
this.engine.runRenderLoop(() => {
scene.render();
});
//Animation
scene.registerBeforeRender(() => {
boxMesh.rotation.y += 0.01;
boxMesh.rotation.x += 0.01;
});
};
componentWillUnmount() {
window.removeEventListener("resize", this.onWindowResize, false);
}
onWindowResize = event => {
this.engine.resize();
};
/**
* Add Lights
*/
addLight = () => {
//---------- LIGHT---------------------
// Create a basic light, aiming 0,1,0 - meaning, to the sky.
var light = new BABYLON.HemisphericLight(
"light1",
new BABYLON.Vector3(0, 10, 0),
scene
);
};
/**
* Add Camera
*/
addCamera = () => {
// ---------------ArcRotateCamera or Orbit Control----------
var camera = new BABYLON.ArcRotateCamera(
"Camera",
Math.PI / 2,
Math.PI / 4,
4,
BABYLON.Vector3.Zero(),
scene
);
camera.inertia = 0;
camera.angularSensibilityX = 250;
camera.angularSensibilityY = 250;
// This attaches the camera to the canvas
camera.attachControl(this.canvas, true);
camera.setPosition(new BABYLON.Vector3(5, 5, 5));
};
/**
* Create Stage and Skybox
*/
addGround = () => {
// Create a built-in "ground" shape.
var ground = BABYLON.MeshBuilder.CreateGround(
"ground1",
{ height: 6, width: 6, subdivisions: 2 },
scene
);
var groundMaterial = new BABYLON.StandardMaterial("grass0", scene);
groundMaterial.diffuseTexture = new BABYLON.Texture(
"./assets/ground.jpeg",
scene
);
ground.material = groundMaterial;
//Add SkyBox
var photoSphere = BABYLON.Mesh.CreateSphere("skyBox", 16.0, 50.0, scene);
var skyboxMaterial = new BABYLON.StandardMaterial("smat", scene);
skyboxMaterial.emissiveTexture = new BABYLON.Texture(
"assets/skybox.jpeg",
scene,
1,
0
);
skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
skyboxMaterial.emissiveTexture.uOffset = -Math.PI / 2; // left-right
skyboxMaterial.emissiveTexture.uOffset = 0.1; // up-down
skyboxMaterial.backFaceCulling = false;
photoSphere.material = skyboxMaterial;
};
/**
* Add Models
*/
addModels = () => {
// Add BOX
boxMesh = BABYLON.MeshBuilder.CreateBox(
"box",
{ height: 1, width: 1, depth: 1 },
scene
);
boxMesh.position.y = 1;
var woodMaterial = new BABYLON.StandardMaterial("wood", scene);
woodMaterial.diffuseTexture = new BABYLON.Texture(
"./assets/portal_cube.png",
scene
);
boxMesh.material = woodMaterial;
};
render() {
return (
<canvas
style={{ width: window.innerWidth, height: window.innerHeight }}
ref={canvas => {
this.canvas = canvas;
}}
/>
);
}
}
export default BabylonScene;
Live Demo:
https://codesandbox.io/s/babylonjs-react-template-w2i1k

Extjs - drag drop restriction

How do I restrict the drag operation not exceeding certain boundary. Is there any config in extjs (version 3), I saw that, Ext.dd.DragZone class is used. But Im not sure what is the usability. I saw a method dropNotAllowed. Is that the method, that has to be used? if so, how should I use that? Please provide some examples.
Im looking for something similar to (jquery UI's draggable containment property)
http://docs.sencha.com/extjs/3.4.0/#!/api/Ext.dd.DragZone-cfg-dropNotAllowed
I tried using the set X and Y constraints, but it did not work-out:
abc.prototype.initDrag = function(v) {
v.dragZoneobj = new Ext.dd.DragZone(v.getEl(), {
getDragData : function(e) {
var sourceEl = e.getTarget(v.itemSelector, 10);
// sourceEl.setXConstraint( 0, 10 );
var t = e.getTarget();
var rowIndex = abc.grid.getView().findRowIndex(t);
var columnIndex = abc.grid.getView().findCellIndex(t);
if ((rowIndex !== false) && (columnIndex !== false)) {
if (sourceEl) {
abc.isDragged = true;
abc.scriptGrid.isDraggableForObject = false;
abc.scriptGrid.dragRowIndex = false;
d = sourceEl.cloneNode(true);
d.id = Ext.id();
d.textContent = sourceEl.innerHTML;
// d.setXConstraint( 0, 10 );
// d.setYConstraint( 0, 10 );
return {
ddel : d,
sourceEl : d,
sourceStore : v.store
}
}
}
},
getRepairXY : function() {
return this.dragData.repairXY;
},
});
}
Both are commented in the above code. The above code is initiated when the panel is rendered.
edit:
How these setX and setYcontraints have to be used?
By default, the element can be dragged any place on the screen. In the doc there are two methods setXConstraint( iLeft, iRight, iTickSize) and setYConstraint( iUp, iDown, iTickSize )
These two methods is used to set to limit the vertical travel and horizental travel of the element.

How many markers can I import from .js file?

I'm trying to import markers from .js file into my Google Maps.
I use Google Maps Javascript API v3.
If the .js file has too many markers, the map doesn't show any marker.
When I delete some markers in .js file, the map shows all markers from .js file.
What's wrong with this?
I want to import 1,000 ~ 3,000 markers from .js file and show the markers only in the visible bound on the map.
Is there any limitation of the markers while reading .js file?
I don't use JQuery, node.js.
Do I have to callback function? Please help me.
Thanks in advance.
a.html
...
<script src="js/markers.js"></script>
...
<script type="text/javascript">
var mymap; // one map
...
function showMarker(eachLocations) {
// get the center of the map and zoom level
var new_center = mymap.getCenter();
defaultLat = new_center.lat();
defaultLon = new_center.lng();
var zoomLevel = mymap.getZoom();
var marker,i;
var pin_image_url = "/common/images/marker_img.png";
var myMarkerIcon;
var bounds = mymap.getBounds();
var ne = bounds.getNorthEast(); // LatLng of the north-east corner
var sw = bounds.getSouthWest(); // LatLng of the south-west corder
var nw = new google.maps.LatLng(ne.lat(), sw.lng());
var se = new google.maps.LatLng(sw.lat(), ne.lng());
// for each location
for (i = 0; i < eachLocations.length; i++) {
// custom marker
myMarkerIcon = new
google.maps.MarkerImage(pin_image_url,null,null,null,new
google.maps.Size(32,37));
if (eachLocations[i][1] >= se.lat() && eachLocations[i][1] <= nw.lat() && eachLocations[i][2] >= nw.lng() && eachLocations[i][2] <= se.lng()) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(eachLocations[i][1], eachLocations[i][2]),
map: mymap,
icon: myMarkerIcon
});
markers.push(marker);
// listner for marker
google.maps.event.addListener(marker, 'click', (function(marker, i) {
// click,dblclick,mouseup,mousedown,mouseout
return function() {
// if any infowindow has already shown, hides it and shows the new one
if (infowindow) infowindow.close();
// make the infoWindow of the first marker
infowindow = new google.maps.InfoWindow({
map: mymap,
position: new google.maps.LatLng(eachLocations[i][1], eachLocations[i][2])
});
infowindow.setContent('<div style="width:250px;text-align: center;font-size:10pt;font-family:Arial,Verdana;font-weight:bold";>'+eachLocations[i][0]+'</div>');
infowindow.open(mymap, marker);
}
})(marker, i));
} // end of if the location is in the bounds
} // end of for each locations
} // end of function
function initialize() {
var mapDiv=document.getElementById("mapholder");
var myOptions={
center:new google.maps.LatLng(defaultLat,defaultLon),
zoom:defaultZoomLevel,
mapTypeId:google.maps.MapTypeId.ROADMAP,
zoomControl: true, // by default
zoomControlOptions: {style: google.maps.ZoomControlStyle.LARGE},
mapTypeControl:false,
navigationControlOptions:
{style:google.maps.NavigationControlStyle.SMALL}
};
// make map instance
mymap=new google.maps.Map(mapDiv,myOptions);
// Create the DIV to hold the control and
// call the CenterControl() constructor passing in this DIV
var centerControlDiv = document.createElement('div');
var centerControl = new CenterControl(centerControlDiv, mymap);
centerControlDiv.index = 1;
mymap.controls[google.maps.ControlPosition.BOTTOM_LEFT].push( centerControlDiv);
getLocation();
google.maps.event.addListener(mymap, 'idle', function(ev){
var new_center = mymap.getCenter();
defaultLat = new_center.lat();
defaultLon = new_center.lng();
// you may have too many markers problem
// so, before sending array, you have to rearrange markers to show
var bounds = mymap.getBounds();
var ne = bounds.getNorthEast(); // LatLng of the north-east corner
var sw = bounds.getSouthWest(); // LatLng of the south-west corder
var nw = new google.maps.LatLng(ne.lat(), sw.lng());
var se = new google.maps.LatLng(sw.lat(), ne.lng());
var markers2show = [];
var lengthofarray = myLocations.length;
for (i=0;i<myLocations.length;i++) {
// limit the markers for the new bound
if (myLocations[i][1] >= se.lat() && myLocations[i][1] <= nw.lat() && myLocations[i][2] >= nw.lng() && myLocations[i][2] <= se.lng()) {
markers2show.push(myLocations[i]);
}
}
showMarker(markers2show);
});
// close the previous info window of marker when click the map
google.maps.event.addListener(mymap, 'click', function() {
infowindow.close();
});
showMarker(myLocations);
}
...
<body onload="initialize()">
...
js/markers.js
var myLocations = [
['A Location',37.007756,140.750864],
['B Location',37.111598,140.424843],
['C Location',36.881268,140.025215]
];

Resources