I'm using ArcGIS JSAPI 4.12 and wishing to use Spatial Illusions to draw military symbols on map.
When I add milsymbol.js
to script, the console returns error Uncaught SyntaxError: Cannot use import statement outside a module
, so I add type="module"
to the script, the it returns Uncaught ReferenceError: ms is not defined
.
Here's my code:
<link rel="stylesheet" href="https://js.arcgis.com/4.12/esri/css/main.css">
<script src="https://js.arcgis.com/4.12/">
</script><script type="module" src="milsymbol-2.0.0/src/milsymbol.js"></script>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/layers/MapImageLayer",
"esri/layers/FeatureLayer"
], function (Map, MapView, MapImageLayer, FeatureLayer) {
var symbol = new ms.Symbol("SFG-UCI----D", { size: 30 }).asCanvas(3);
var map = new Map({
basemap: "topo-vector"
});
var view = new MapView({
container: "viewDiv",
map: map,
center: [121, 23],
zoom: 7
});
});
</script>
So, whether I add type="module"
or not, there's always errors. However, in the official document of Spatial Illusions, there's no type="module"
in the script. I'm now really confused, how do they manage to get it work without adding the type?
milsymbol.js
import { ms } from "./ms.js";import Symbol from "./ms/symbol.js";ms.Symbol = Symbol;export { ms };
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>2D Milsymbol Editor Final</title>
<link rel="stylesheet" href="https://js.arcgis.com/3.29/esri/css/esri.css">
<link rel="stylesheet" href="https://js.arcgis.com/3.29/dijit/themes/claro/claro.css">
<script src="https://js.arcgis.com/3.29/"></script>
<script src="http://xxxxxxxx:8080/tacticalTactical/milsymbol2D.js"></script>
<link rel="stylesheet" href="http://xxxxxxxx:8080/tacticalTactical/milsymbol-unit-generator.css" type="text/css">
<script src="http://xxxxxxxx:8080/tacticalTactical/milsymbol-unit-generator.js"></script>
<script src="Scripts/LayoutManager.js"></script>
<link rel="stylesheet" type="text/css" href="CSS/Main.css"/>
<script>
var myMap;
var graphictactical;
var graphicLayertactical;
var graphicLayertacticalPicker;
var symbolFullList;
var svgGlobaleCodeImg;
var pElementId;
var editToolbar, ctxMenuForGraphics, ctxMenuForMap;
var tacticalFeatureLayer;
var queryParams;
var pictureMarkerSymbol;
var graphic;
var currentFeature = [];
var loadFeature = [];
var moveFeature = [];
var deleteFeature = [];
var globalSavePlanName;
var globalSaveAsPlanName;
var currentCount;
var myTacticalSymbol;
var moveGraphicFeature;
var currentGraphic;
require([
"esri/map",
"esri/geometry/Point",
"esri/geometry/Polygon",
"esri/graphic", "dojo/_base/array",
"esri/symbols/PictureMarkerSymbol",
"esri/symbols/SimpleFillSymbol",
"esri/layers/GraphicsLayer",
"esri/layers/FeatureLayer", "esri/tasks/query",
"esri/toolbars/edit",
"dijit/Menu", "dijit/MenuItem",
"dojo/domReady!"
], function (
Map,
Point, Polygon, Graphic, arrayUtils,
PictureMarkerSymbol, SimpleMarkerSymbol, GraphicsLayer, FeatureLayer, Query ,Edit, Menu, MenuItem
) {
pictureMarkerSymbol = PictureMarkerSymbol;
graphic = Graphic;
myMap = new Map("viewDiv",
{
basemap: "streets",
center: [-80, 35],
zoom: 3,
sliderPosition: "top-right"
});
dojo.connect(myMap, "onClick", addGraphicsSVG);
myMap.on("load", createToolbarAndContextMenu);
graphicLayertactical = new esri.layers.GraphicsLayer();
myMap.addLayer(graphicLayertactical);
graphicLayertacticalPicker = new esri.layers.GraphicsLayer();
myMap.addLayer(graphicLayertacticalPicker);
tacticalFeatureLayer = new FeatureLayer("https://xxxxxxx/server/rest/services/xxxxxxl/FeatureServer/0", {
//mode: FeatureLayer.SELECTION_NEW,
outFields: ["*"],
visible: false
});
myMap.addLayer(tacticalFeatureLayer);
initSymbols(symbolFullList);
queryParams = new esri.tasks.Query();
currentCount = 0;
// Adding Plan into DropDown list - Tactical Plan Load
addTacticalPlan(queryParams, tacticalFeatureLayer);
cbTacticalPlanLoad.onchange = function ()
{
var planNameValue = document.getElementById("cbTacticalPlanLoad").value;
document.getElementById("txtSave").value = planNameValue;
globalSavePlanName = planNameValue;
};
// Save Tactical Plan
saveBtnTacticalPlan.onclick = function () {
if (globalSavePlanName != "") {
saveTacticalFeature(currentFeature, globalSavePlanName);
}
else {
alert("Please fill Plan Name in order to save");
}
};
// Save As Tactical Plan
saveAsBtnTacticalPlan.onclick = function () {
globalSaveAsPlanName = document.getElementById("txtSaveAs").value;
// alert(globalSaveAsPlanName);
if (globalSaveAsPlanName != "")
{
saveTacticalFeature(currentFeature, globalSaveAsPlanName);
}
else {
alert("Enter Tactical Plan");
}
};
// Calling Save plan from Save and SaveAs Button
function saveTacticalFeature(pCurrentFeatures, pPlanName)
{
//
var addedFeatures = pCurrentFeatures.map(function (item) {
var mappedItem = item;
mappedItem.attributes["MilitarySymbologyCode"] = item.attributes.svgCode;
mappedItem.attributes["PlanName"] = pPlanName;
return mappedItem;
});
var promise = tacticalFeatureLayer.applyEdits(addedFeatures, null, null);
}
function updateCurrentFeature(pSelected) {
// console.log("Current Graphic 1 " + pSelected.geometry.x);
// console.log("Selected Graphic 2" + moveGraphicFeature.geometry.x);
// Update Feature Move geomtery
for (var i in currentFeature)
{
var tempID = moveGraphicFeature.attributes["svgCode"];
if (currentFeature.SVGCodeID == tempID)
{
console.log(currentFeature.SVGx);
console.log(currentFeature.SVGy);
currentFeature.SVGx = 102.35;
currentFeature.SVGy = 102.35;
console.log(currentFeature.SVGx);
console.log(currentFeature.SVGy);
}
}
// currentFeature.push({ SVGCodeID: moveGraphicFeature.attributes["svgCode"], SVGID: moveGraphicFeature.attributes["countID"], SVGStatus: "CURRENT", SVGx: pSelected.geometry.x, SVGy: pSelected.geometry.y})
// console.log("currentFeature: " + currentFeature);
}
// Add Graphics on Map CLick
function addGraphicsSVG(evt)
{
var svgTacticalCode = null;
// svgTacticalCode = svgGlobaleCodeImg;
svgTacticalCode = document.getElementById("svgCode").innerHTML;
console.log(svgTacticalCode);
console.log("SymbolEditorMenu : " + document.getElementById("SymbolEditorMenu").style.display);
if (document.getElementById("SymbolEditorMenu").style.display == "") {
addGraphicsOnCondition(graphicLayertactical, svgTacticalCode, evt);
} else if (document.getElementById("SymbolEditorMenu").style.display == "block") {
addGraphicsOnCondition(graphicLayertactical, svgTacticalCode, evt);
} else if (document.getElementById("SymbolPickerMenu").style.display == "block") {
addGraphicsOnCondition(graphicLayertactical, svgGlobaleCodeImg, evt);
}
}
// This function Calling by Add Graphics - On Map Click
function addGraphicsOnCondition(pGraphicsLayer, pSVGCode, pEvt)
{
var currentStatus = "CURRENT";
var mysymbol = new MS.symbol(pSVGCode, { size: 30 }).getMarker();
myTacticalSymbol = mysymbol;
var symboltactical = new PictureMarkerSymbol({
"url": mysymbol.toDataURL(),
"width": Math.floor(mysymbol.width),
"height": Math.floor(mysymbol.height),
});
currentCount += 1;
var currentGraphic = new Graphic(pEvt.mapPoint, symboltactical, { "countID": currentCount - 1, "Status": currentStatus, "svgCode": pSVGCode });
pGraphicsLayer.add(currentGraphic);
myMap.addLayer(pGraphicsLayer);
var tacticalCode = pSVGCode;
var tacticalLocationX = pEvt.mapPoint.x.toString();
var tacticalLocationY = pEvt.mapPoint.y.toString();
// console.log(tacticalCode + " " + tacticalUser + " " + tacticalLocationX + " " + tacticalLocationY);
console.log("pGraphicsLayer" + pGraphicsLayer);
console.log("currentCount" + currentCount);
var feature = { SVGCodeID: tacticalCode, SVGID: currentCount - 1, SVGStatus: currentStatus, SVGx: tacticalLocationX, SVGy: tacticalLocationY, svgGemoetry: pEvt.mapPoint };
currentFeature.push(currentGraphic)
console.log("svgFeature: " + currentFeature);
}
function createToolbarAndContextMenu() {
editToolbar = new Edit(myMap);
dojo.connect(editToolbar, 'onGraphicMoveStop', handleGraphicEditStop);
myMap.on("click", function (evt) {
editToolbar.deactivate();
});
createGraphicsMenu();
}
function handleGraphicEditStop(graphic)
{
currentGraphic = new esri.Graphic(graphic.geometry, graphic.symbol);
console.log("currentGraphic Function Call " + currentGraphic.geometry.x);
updateCurrentFeature(currentGraphic);
}
function createGraphicsMenu() {
ctxMenuForGraphics = new Menu({});
ctxMenuForGraphics.addChild(new MenuItem({
label: "Move",
onClick: function ()
{
editToolbar.activate(Edit.MOVE, selected);
moveGraphicFeature = null;
moveGraphicFeature = selected;
console.log("moveGraphicFeature : " + moveGraphicFeature.geometry.x);
// updateCurrentFeature(selected);
}
}));
ctxMenuForGraphics.addChild(new MenuItem({
label: "Delete",
onClick: function () {
graphicLayertactical.remove(selected);
}
}));
ctxMenuForGraphics.startup();
graphicLayertactical.on("mouse-over", function (evt) {
// We'll use this "selected" graphic to enable editing tools
// on this graphic when the user click on one of the tools
// listed in the menu.
selected = evt.graphic;
// Let's bind to the graphic underneath the mouse cursor
ctxMenuForGraphics.bindDomNode(evt.graphic.getDojoShape().getNode());
});
graphicLayertactical.on("mouse-out", function (evt)
{
// console.log("mouse-out" + evt)
ctxMenuForGraphics.unBindDomNode(evt.graphic.getDojoShape().getNode());
});
}
});
</script>
<script type="text/javascript">
function show(elementId) {
document.getElementById("SymbolEditorMenu").style.display = "none";
document.getElementById("SymbolProcessMenu").style.display = "none";
document.getElementById("SymbolPickerMenu").style.display = "none";
document.getElementById(elementId).style.display = "block";
pElementId = null;
pElementId = elementId;
}
function showSelection(checkedID) {
if (document.getElementById('rdLoad').checked)
{
document.getElementById("myFormLoad").style.display = "none";
document.getElementById("myFormSave").style.display = "none";
document.getElementById("myFormSaveAs").style.display = "none";
document.getElementById(checkedID).style.display = "block";
} else if (document.getElementById('rdSave').checked) {
document.getElementById("myFormLoad").style.display = "none";
document.getElementById("myFormSave").style.display = "none";
document.getElementById("myFormSaveAs").style.display = "none";
document.getElementById(checkedID).style.display = "block";
} else if (document.getElementById('rdSaveAs').checked) {
document.getElementById("myFormLoad").style.display = "none";
document.getElementById("myFormSave").style.display = "none";
document.getElementById("myFormSaveAs").style.display = "none";
document.getElementById(checkedID).style.display = "block";
}
}
</script>
<script>
function codeToSymbol(code) {
return mysymbol = new MS.symbol(code, { size: 30 }).getMarker();
}
function loadJSON(path, success, error) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
if (success)
success(JSON.parse(xhr.responseText));
// alert("Hello STart");
} else {
if (error)
error(xhr);
}
}
};
xhr.open("GET", path, true);
xhr.send();
}
//
function initSymbols(militarySymbolArray) {
var selectTacticalA = document.getElementById("tacticalIdA");
var selectTacticalB = document.getElementById("tacticalIdB");
var optionAir = document.createElement('option');
var optionGround = document.createElement('option');
var optionSEA = document.createElement('option');
var optionSUBSURFACE = document.createElement('option');
var optionFriend = document.createElement('option');
var optionHOSTILE = document.createElement('option');
var optionUNKNOWN = document.createElement('option');
var optionNEUTRAL = document.createElement('option');
optionFriend.text = "FRIEND";
optionFriend.value = 1;
selectTacticalA.add(optionFriend, 1);
optionHOSTILE.text = "HOSTILE";
optionHOSTILE.value = 2;
selectTacticalA.add(optionHOSTILE, 2);
optionUNKNOWN.text = "UNKNOWN";
optionUNKNOWN.value = 3;
selectTacticalA.add(optionUNKNOWN, 3);
optionNEUTRAL.text = "NEUTRAL";
optionNEUTRAL.value = 4;
selectTacticalA.add(optionNEUTRAL, 4);
optionAir.text = "AIR";
optionAir.value = 1;
selectTacticalB.add(optionAir, 1);
optionGround.text = "GROUND";
optionGround.value = 2;
selectTacticalB.add(optionGround, 2);
optionSEA.text = "SEA";
optionSEA.value = 3;
selectTacticalB.add(optionSEA, 3);
optionSUBSURFACE.text = "SUBSURFACE";
optionSUBSURFACE.value = 4;
selectTacticalB.add(optionSUBSURFACE, 4);
// console.log("militarySymbolArray" + militarySymbolArray);
loadJSON('https://localhost/tacticalTactical/jsonSVGTactical.json',
function (data) {
militarySymbolArray = data;
// console.log("militarySymbolArray Total Lenght : " + militarySymbolArray.length);
var tacticalIMG, container = document.getElementById("tacticalTblStyleContainer");
console.log("Before Loop : " + militarySymbolArray.length);
tacticalIdB.onchange = function () {
clearTacticalcontainer(container);
var tacticalIDA = document.getElementById("tacticalIdA").value;
var tacticalIDB = document.getElementById("tacticalIdB").value;
var tacticalIDValueA = document.getElementById("tacticalIdA").options[tacticalIDA].text;
var tacticalIDValueB = document.getElementById("tacticalIdB").options[tacticalIDB].text;
console.log("tacticalIDValue After : " + tacticalIDValueA + " : " + tacticalIDValueB);
for (let i = 0; i < militarySymbolArray.length; i++)
{
// militarySymbolArray.length
var svgCateGoryA = militarySymbolArray.CategoryA;
var svgCateGoryB = militarySymbolArray.CategoryB;
if (svgCateGoryA.toUpperCase() == tacticalIDValueA && svgCateGoryB.toUpperCase() == tacticalIDValueB) {
var svgCodeImg = militarySymbolArray.SVGCodeID;
var svgImage = codeToSymbol(svgCodeImg);
tacticalIMG = document.createElement("img");
tacticalIMG.className = "pickerItemIcon";
tacticalIMG.id = svgCodeImg;
tacticalIMG.src = svgImage.toDataURL();
tacticalIMG.height = "50";
tacticalIMG.width = "50";
tacticalIMG.onclick = function () {
svgCodeCapture(this.id);
};
container.appendChild(tacticalIMG);
}
else
{
console.log("AIR Else : " + svgCateGoryA);
console.log("FRIEND Else : " + svgCateGoryB);
}
};
}
// console.log("After Added Arry : " + militarySymbolArray);
},
function (xhr) {
console.error(xhr);
}
);
}
function svgCodeCapture(pSvgGlobaleCodeImg) {
svgGlobaleCodeImg = null;
svgGlobaleCodeImg = pSvgGlobaleCodeImg;
}
function clearTacticalcontainer(pContainer) {
try {
while (pContainer.firstChild)
pContainer.removeChild(pContainer.firstChild);
}
catch (ex) {
pContainer.innerHTML = ex;
}
}
</script>
<script>
// Adding Tactical Plan name - Call by Map Onload
function addTacticalPlan(queryParams, featureLayer)
{
queryParams.outFields = ["PlanName"];
queryParams.where = "1=1";
queryParams.returnGeometry = false;
queryParams.returnDistinctValues = true;
featureLayer.queryFeatures(queryParams, function (response) {
addPlanInSelection(response);
});
}
function addPlanInSelection(response)
{
var features = response.features;
// console.log(features.length);
for (var i = 0; i < features.length; i++)
{
var _feature = features;
var option = document.createElement("option");
option.text = _feature.attributes["PlanName"];
option.value = _feature.attributes["PlanName"];
var select = document.getElementById("cbTacticalPlanLoad");
select.appendChild(option);
}
}
// Load all Tacical Plan - Plan Name condition
function loadPlanOnMap() {
var pQueryParams = new esri.tasks.Query();
var pFeatureLayer = tacticalFeatureLayer;
var planNameStr = document.getElementById("cbTacticalPlanLoad").value;
pQueryParams.returnGeometry = true;
pQueryParams.outFields = ["*"];
pQueryParams.where = "PlanName='" + planNameStr + "'";
pFeatureLayer.queryFeatures(pQueryParams, function (response) {
addPlanOnMap(response);
});
}
function addPlanOnMap(pResponse)
{
alert("Hello");
graphicLayertactical.clear();
var features = pResponse.features;
for (var i = 0; i < features.length; i++)
{
var _feature = features;
if (_feature.geometry.x != "NaN")
{
var mysymbol = new MS.symbol(_feature.attributes["MilitarySymbologyCode"], { size: 30 }).getMarker();
console.log(_feature.geometry);
var symboltactical = new pictureMarkerSymbol({
"url": mysymbol.toDataURL(),
"width": Math.floor(mysymbol.width),
"height": Math.floor(mysymbol.height),
});
var symbol = new esri.symbol.SimpleMarkerSymbol(esri.symbol.SimpleMarkerSymbol.STYLE_SQUARE, 10,
new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID,
new esri.Color([255, 0, 0]), 1),
new esri.Color([0, 255, 0, 0.25]));
myMap.graphics.add(new graphic(_feature.geometry, symboltactical));
}
}
}
</script>
</head>
<body class="mdc-typography" onload="milsymbolUnitGenerator()" >
<div id="viewDiv">
<div style='float: right;'>Share</div>
<div id='SymbolPicker' class="symbolPanel">
<table id="tacticalTblStyle">
<tr>
<th onclick="show('SymbolEditorMenu');">Editor</th>
<th onclick="show('SymbolProcessMenu');">Plan Manager</th>
<th onclick="show('SymbolPickerMenu');">Picker</th>
</tr>
</table>
<div id='SymbolEditorMenu' style="display:block;">
<section>
<div class="demo-tabs__scroller">
<div id="tab-bar-scroller" class="mdc-tab-bar-scroller">
<div class="mdc-tab-bar-scroller__indicator mdc-tab-bar-scroller__indicator--back">
<a class="mdc-tab-bar-scroller__indicator__inner material-icons" href="#" aria-label="scroll back button">
<svg fill="rgba(0, 0, 0, .54)" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M15.41 16.09l-4.58-4.59 4.58-4.59L14 5.5l-6 6 6 6z" />
<path d="M0-.5h24v24H0z" fill="none" />
</svg>
</a>
</div>
<div class="mdc-tab-bar-scroller__scroll-frame">
<nav id="scrollable-tab-bar" class="mdc-tab-bar mdc-tab-bar-scroller__scroll-frame__tabs custom-indicator-tab-bar">
<a role="tab" aria-controls="panel-1" class="mdc-tab" href="#panel-1">MIL-STD-2525C</a>
<a role="tab" aria-controls="panel-2" class="mdc-tab" href="#panel-2">APP-6 B</a>
<a role="tab" aria-controls="panel-3" class="mdc-tab" href="#panel-3">MIL-STD-2525D</a>
<a role="tab" aria-controls="panel-4" class="mdc-tab" href="#panel-4">APP-6 D</a>
<span class="mdc-tab-bar__indicator"></span>
</nav>
</div>
<div class="mdc-tab-bar-scroller__indicator mdc-tab-bar-scroller__indicator--forward">
<a class="mdc-tab-bar-scroller__indicator__inner material-icons" href="#" aria-label="scroll forward button">
<svg fill="rgba(0, 0, 0, .54)" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z" />
<path d="M0-.25h24v24H0z" fill="none" />
</svg>
</a>
</div>
</div>
</div>
</section>
<section class="content">
<div class="panels">
<div class="panel panel-2525c" id="panel-1" role="tabpanel" aria-hidden="true">
</div>
<div class="panel panel-app6b" id="panel-2" role="tabpanel" aria-hidden="true">
</div>
<div class="panel panel-2525d" id="panel-3" role="tabpanel" aria-hidden="true">
</div>
<div class="panel panel-app6d" id="panel-4" role="tabpanel" aria-hidden="true">
</div>
</div>
</section>
</div>
<div id='SymbolProcessMenu' style="display:none;">
<div class="form-container" id="myFormRadio">
<h1>Tactical Plan - Select Process </h1>
<div id="selection" class="form-container">
<label>
<input type="radio" id="rdLoad" name='tactical' onclick="showSelection('myFormLoad');" value="Load" checked /> <strong> Load </strong>
</label>
<label>
<input type="radio" id="rdSave" name='tactical' value="Save" onclick="showSelection('myFormSave');" /> <strong> Save </strong>
</label>
<label>
<input type="radio" id="rdSaveAs" name='tactical' value="SaveAs" onclick="showSelection('myFormSaveAs');" /> <strong> Save As </strong>
</label>
</div>
</div>
<div class="form-container" id="myFormLoad" style="display:block;">
<select id="cbTacticalPlanLoad" name="cbTacticalPlanLoad" class="btn Load">
<option>SELECT</option>
</select>
<h1> </h1>
<button type="button" class="btn Load" onclick="loadPlanOnMap()">Load</button>
</div>
<div class="form-container" id="myFormSave" style="display:none;">
<input type="text" id="txtSave" style="background-color :antiquewhite;" disabled />
<h1> </h1>
<button type="button" id="saveBtnTacticalPlan" class="btn Load">Save</button>
</div>
<div class="form-container" id="myFormSaveAs" style="display:none;">
<input type="text" id="txtSaveAs" style="background-color :antiquewhite;" />
<h1> </h1>
<button type="button" id="saveAsBtnTacticalPlan" class="btn Load">Save As</button>
</div>
</div>
<div id='SymbolPickerMenu' style="display:none;" class="form-container">
<div>
<table style="width:100%">
<tr>
<td class="pickerSelectorLabal">
<label> <strong> Afliation : </strong></label>
</td>
<td class="pickerSelectorSelect">
<select id="tacticalIdA" name="TaticalA" class="btn Load">
<option>SELECT</option>
</select>
</td>
</tr>
</table>
</div>
<div>
<table style="width:100%">
<tr>
<td class="pickerSelectorLabal">
<label><strong> Dimension : </strong> </label>
</td>
<td class="pickerSelectorSelect">
<select id="tacticalIdB" name="TaticalB" class="btn Load ">
<option>SELECT</option>
</select>
</td>
</tr>
</table>
</div>
<div class="verticalSplit"></div>
<div id="tacticalTblStyleContainer" style="height:100%;overflow:auto"></div>
</div>
</div>
</div>
</body>
</html>