OpenLayers Vector tiles Styling Optimization - openlayers-6

I am new to openlayers and vector layer and i am facing performance problem. I have 3 layers and each layer containing thousands of features. Is it the correct way of styling the layer or is there anything else we can do to further make it even faster even on low end computer. What else can be done in case of geoserver layergroup. How can we efficiently style it since it has many layers and how to get the layers from the layer group.
var gridsetName = "EPSG:900913";
var baseUrl = "http://localhost:8080/geoserver/gwc/service/wmts";
var style = "";
var format = "application/vnd.mapbox-vector-tile";
var layerCache = {};
var gardening_area_uncertainity = new Style({
stroke: new Stroke({
color: "rgba(200,20,20,0.8)",
width: 2,
}),
});
var gardening_point = new Style({
image: new Circle({
stroke: new Stroke({
width: 1,
color: "red",
}),
radius: 2,
}),
});
var layers = [
{
layer: "city:gardenings_point_uncertainity",
style: gardening_area_uncertainity,
},
{ layer: "city:gardening_aiming_area", style: gardening_area_uncertainity },
{ layer: "city:gardening_aiming_point", style: gardening_point },
];
var key = 0;
var styleForLayer = null;
var layerFeature = function (feature) {
//console.log("Type is:",feature.type_)
if (feature.get("layer") === "gardening_aiming_point") key = 1;
else if (feature.get("layer") === "gardenings_point_uncertainity") key = 2;
else if (feature.get("layer") === "gardening_aiming_area") key = 3;
styleForLayer = layerCache[key];
if (!styleForLayer) {
switch (feature.get("layer")) {
case "gardening_aiming_area":
styleForLayer = gardening_area_uncertainity;
break;
case "gardenings_point_uncertainity":
styleForLayer = gardening_area_uncertainity;
break;
case "gardening_aiming_point":
styleForLayer = gardening_point;
break;
}
layerCache[key] = styleForLayer;
}
return styleForLayer;
};
var i;
var view = new View({
center: [0, 0],
zoom: 2,
// constrainResolution:true,
extent: [-20037508.34, -20037508.34, 20037508.34, 20037508.34],
});
var map = new Map({
layers: [
new TileLayer({
preload: Infinity,
source: new OSM({ cacheSize: 20000 }),
}),
],
target: "map",
view: view,
});
map
.getView()
.fit([-20037508.34, -20037508.34, 20037508.34, 20037508.34], map.getSize());
map.on("moveend", (evt) => {
console.log(map.getView().getZoom());
});
function constructSource() {
var url = baseUrl + "?";
for (var param in params) {
url = url + param + "=" + params[param] + "&";
}
url = url.slice(0, -1);
var source = new VectorTileSource({
url: url,
format: new MVT({}),
tileGrid: new WMTS({
tileSize: [256, 256],
origin: [-2.003750834e7, 2.003750834e7],
resolutions: resolutions,
}),
});
return source;
}
for (i = 0; i < layers.length; i++) {
//console.log('Layer',layers[i])
var params = {
REQUEST: "GetTile",
SERVICE: "WMTS",
VERSION: "1.0.0",
LAYER: layers[i].layer,
STYLE: style,
TILEMATRIX: gridsetName + ":{z}",
TILEMATRIXSET: gridsetName,
FORMAT: format,
TILECOL: "{x}",
TILEROW: "{y}",
};
var layer = new VectorTileLayer({
source: constructSource(),
preload: Infinity,
renderMode: "image",
style: layers[i].style,
});
map.addLayer(layer);
}

Related

ArcGIS map polygon store in ArcGIS

I have to store the created polygon in ArcGIS. Once the polygon is stored in ArcGIS, it returns an ID (Object ID). With the object ID, the administrator can access the polygon in ArcGIS. I found a piece of code in one of our old systems the code is written in version 3xx.
function SendFeaturesToParent()
{
editingEnabled = false;
editToolbar.deactivate();
lyrMeters.clearSelection();
polygon = currentEVT.graphic.geometry;
var query = new Query();
query.geometry = polygon;
lyrAreas.applyEdits(null, [currentEVT.graphic], null);
var attributes = [];
var featureValues = [];
for (var x = 0; x < selectedfeatures.length; x++) {
featureValues.push("METER_ID: " + selectedfeatures[x].attributes["METER_ID"] + ", Type: " + selectedfeatures[x].attributes["Type"]);
attributes.push(selectedfeatures[x].attributes);
}
console.log("attributes"+ attributes);
//Send the array of meter values back to the parent page.
var objectId = lyrAreas._defnExpr;
objectId = objectId.split('=');
window.parent.postMessage(
{
event_id: 'my_cors_message',
data: attributes,
objectId: objectId[1]
},
"*" //or "www.parentpage.com"
);
$('#modelConfirm').modal('hide');
}
I need to implement in latest version of arcGIS API 4.23. What are the applyEdits do?
/**** modified code in 4.23 */
var token = '';
const PermitAreaURL = "url_1";
const locatorUrl = "url_2";
const streetmapURL = "url_3";
const streetmapLebelsURL = "url_4";
const MetersURL = "url_5";
const MetersWholeURL = "url_6";
require(["esri/config",
"esri/Map",
"esri/views/MapView",
"esri/layers/FeatureLayer",
"esri/layers/TileLayer",
"esri/layers/VectorTileLayer",
"esri/layers/GraphicsLayer",
"esri/widgets/Search",
"esri/widgets/Sketch/SketchViewModel",
"esri/geometry/geometryEngineAsync",
],
function (esriConfig, Map, MapView, FeatureLayer, TileLayer, VectorTileLayer, GraphicsLayer, Search, SketchViewModel, geometryEngineAsync) {
esriConfig.apiKey = "AAPK3f43082c24ae493196786c8b424e9f43HJcMvP1NYaqIN4p63qJnCswIPsyHq8TQHlNtMRLWokqJIWYIJjga9wIEzpy49c9v";
const graphicsLayer = new GraphicsLayer();
const streetmapTMLayer = new TileLayer({
url: streetmapURL
});
const streetmapLTMLayer = new VectorTileLayer({
url: streetmapLebelsURL
});
const lyrwholeMeters = new FeatureLayer({
url: MetersWholeURL,
outFields: ["*"],
});
const lyrMeters = new FeatureLayer({
url: MetersURL,
outFields: ["*"],
});
// const permitAreaUrl = new FeatureLayer({
// url: PermitAreaURL,
// outFields: ["*"],
// });
// console.log(lyrMeters);
const map = new Map({
basemap: "arcgis-topographic", // Basemap layer service
layers: [streetmapTMLayer, streetmapLTMLayer, lyrMeters, lyrwholeMeters, graphicsLayer]
});
const view = new MapView({
map: map,
center: [-95.9406, 41.26],
zoom: 16,
maxZoom: 21,
minZoom: 13,
container: "viewDiv" // Div element
});
view.when(() => {
const polygonSymbol = {
type: "simple-fill", // autocasts as new SimpleFillSymbol()
color: [207, 34, 171, 0.5],
outline: {
// autocasts as new SimpleLineSymbol()
color: [247, 34, 101, 0.9],
}
};
const sketchViewModel = new SketchViewModel({
view: view,
layer: graphicsLayer,
polygonSymbol: polygonSymbol,
});
sketchViewModel.create("polygon", { mode: "hybrid" });
// Once user is done drawing a rectangle on the map
// use the rectangle to select features on the map and table
sketchViewModel.on("create", async (event) => {
if (event.state === "complete") {
// this polygon will be used to query features that intersect it
const geometries = graphicsLayer.graphics.map(function (graphic) {
return graphic.geometry
});
const queryGeometry = await geometryEngineAsync.union(geometries.toArray());
selectFeatures(queryGeometry);
}
});
});
// This function is called when user completes drawing a rectangle
// on the map. Use the rectangle to select features in the layer and table
function selectFeatures(geometry) {
console.log(geometry.rings);
// create a query and set its geometry parameter to the
// rectangle that was drawn on the view
const query = {
geometry: geometry,
outFields: ["*"]
};
lyrwholeMeters.queryFeatures(query).then(function (results) {
var lyr = results.features;
console.log(lyr);
// save the polygon
lyr.applyEdits({
addFeatures: [geometry] /*updates*/
});
lyr.forEach(element => {
console.log(`MeterID-${element.attributes.METER_ID}, OBJECTID-${element.attributes.OBJECTID}, Passport_ID-${element.attributes.Passport_ID}`);
});
});
}
// search widget
const searchWidget = new Search({
view: view,
});
view.ui.add(searchWidget, {
position: "top-left",
index: 2
});
});
applyEdits method is the way you to add/update/delete features in a feature layer. Both version of the library have the method although in version 4 takes an object that contain the edits instead of the separated parameters. In your code, version 3, it is,
lyrAreas.applyEdits(null, [currentEVT.graphic], null);
first parameter is for new features, second for updates on features and third for features to delete.
While in version 4 it should be,
lyrAreas.applyEdits({
updateFeatures: [currentEVT.graphic] /*updates*/
});
the object goes all the informations about the edits, in this case you only have updates.
I am not completely sure about this line,
var objectId = lyrAreas._defnExpr;
objectId = objectId.split('=');
I am guessing is the definition expression of the feature layer, a sql expression, that is why in the next line it is split, to use later the value. Version 3 library did not expose the property but gives set and get methods.
Version 4 have the property and works in similar way. In this case for latest version it should be,
var objectId = lyrAreas.definitionExpression;
objectId = objectId.split('=');
So I do not think you will have
ArcGIS API v3 - FeatureLayer
ArcGIS API v4 - FeatureLayer

How to get value for selected place in particular area when draw polyline or polygon through Javascript ArcGIS Api from TileLayer?

Actually I am using ArcGIS API for JavaScript 4.7 and i have a custom internal layer . I want to get name of place particular area when draw polyline the column name is (PLC_NAME) . How to achieve that ?
Suppose I draw a area through polyline. In this area there are places . Now I need to get name of these places .
you can find the using code in below i am using the TileLayer.
require([
"esri/views/MapView",
"esri/Map",
"esri/Basemap",
"esri/layers/TileLayer",
"esri/layers/MapImageLayer",
"esri/widgets/Sketch/SketchViewModel",
"esri/geometry/geometryEngine",
"esri/widgets/CoordinateConversion",
"esri/geometry/support/webMercatorUtils",
"esri/Graphic",
"esri/layers/GraphicsLayer",
"esri/config",
"esri/core/urlUtils",
"esri/widgets/Search",
"esri/tasks/Locator",
"esri/layers/FeatureLayer",
"esri/widgets/Expand",
"dojo/domReady!"
], function (
MapView, Map, Basemap, TileLayer, MapImageLayer,
SketchViewModel,
geometryEngine,
CoordinateConversion,
webMercatorUtils,
Graphic, GraphicsLayer, esriConfig, urlUtils,Search,Locator,FeatureLayer,Expand
) {
esriConfig.request.proxyUrl = "xxxxxxxxxxxxxxx";
urlUtils.addProxyRule({
urlPrefix: "xxxxxxxxxxxxxxxxxxx",
proxyUrl: "xxxxxxxxxxxxxxxxxx"
});
var tempGraphicsLayer = new GraphicsLayer();
var saveGraphicsLayer = new GraphicsLayer();
var updateGraphic;
let highlight = null;
'xxxxxxxxxxxxxxxxxxxxxxxxx';
var myMap;
var layer = new TileLayer({
url: mapUrl
});
var towerLayer = new MapImageLayer({
url: 'xxxxxxxxxxxxxxxxxxxxxxx'
});
myMap = new Map({
layers: [layer, tempGraphicsLayer, saveGraphicsLayer]
});
myMap.add(towerLayer);
view = new MapView({
center: [-55.1683665, 39.951817],
container: "viewDiv",
map: myMap,
zoom: 14
});
var ccWidget = new CoordinateConversion({
view: view
});
// Adds the search widget below other elements in
// the top left corner of the view
view.ui.add(searchWidget, {
position: "top-right",
index: 1
});
view.ui.add(ccWidget, "bottom-left");
view.ui.add("topbar", "top-right");
var pointSymbol = { // symbol used for points
type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
style: "square",
color: "#8A2BE2",
size: "16px",
outline: { // autocasts as new SimpleLineSymbol()
color: [255, 255, 255],
width: 3 // points
}
}
var polylineSymbol = { // symbol used for polylines
type: "simple-line", // autocasts as new SimpleLineSymbol()
color: "#8A2BE2",
width: "4",
style: "dash"
}
var polygonSymbol = { // symbol used for polygons
type: "simple-fill", // autocasts as new SimpleFillSymbol()
color: "rgba(138,43,226, 0.8)",
style: "solid",
outline: {
color: "white",
width: 1
}
}
var polygonBoundrySymbol = { // symbol used for polygons
type: "simple-line", // autocasts as new SimpleFillSymbol()
color: "red"
}
// ################## U R HERE ################## ################## U R HERE ##################
################## U R HERE ##################
let drawBoundry = function(){
//let boundryJson = '&G_GEO_LIMITS.';
let boundryJson = $v('P0_USER_LIMITS');
if(boundryJson){
// let boundry = Graphic.fromJSON(JSON.parse('&G_GEO_LIMITS.'));
let boundry = Graphic.fromJSON(JSON.parse(boundryJson));
boundry.symbol = polygonBoundrySymbol;
tempGraphicsLayer.add(boundry);
return boundry;
}
}
/*
let boundry = drawBoundry();
*/
view.when(function () {
$('.esri-view-root').on('click', '.esri-print__export-button', function(e){
//console.log('event bubbling', e);
//console.log('event bubbling this', this);
e.preventDefault();
saveExportedImg();
});
// create a new sketch view model
var sketchViewModel = new SketchViewModel({
view: view,
layer: tempGraphicsLayer,
pointSymbol: pointSymbol,
polylineSymbol: polylineSymbol,
polygonSymbol: polygonSymbol
});
//setUpClickHandler();
// ************************************************************
// Get the completed graphic from the event and add it to view.
// This event fires when user presses
// * "C" key to finish sketching point, polygon or polyline.
// * Double-clicks to finish sketching polyline or polygon.
// * Clicks to finish sketching a point geometry.
// ***********************************************************
sketchViewModel.on("draw-complete", addGraphic);
sketchViewModel.on("update-complete", addGraphic);
sketchViewModel.on("update-cancel", addGraphic);
sketchViewModel.on("vertex-add", addGraphic);
function addGraphic(evt) {
// console.log ('graphic.geometry',evt.geometry)
//let currentGraphic = popActiveGraphic(tempGraphicsLayer);
let currentGraphic = saveGraphicsLayer.graphics.items.pop();
var geometry = evt.geometry;
var vertices = evt.vertices;
var symbol;
var attr = {
Name: "Selected Area",
X: $v('P24_X'),
Y: $v('P24_Y')
};
// Choose a valid symbol based on return geometry
switch (geometry.type) {
case "point":
symbol = pointSymbol;
break;
case "polyline":
symbol = polylineSymbol;
break;
default:
symbol = polygonSymbol;
break;
}
// Create a new graphic; add it to the GraphicsLayer
// console.log("b4 graphic");
geometry = webMercatorUtils.webMercatorToGeographic(geometry)
/*if(boundry){
var contains = geometryEngine.contains(boundry.geometry, geometry);
var within = geometryEngine.within(geometry, boundry.geometry);
} else {*/
var within = true;
//}
if(within){
let graphic = new Graphic({
geometry: geometry,
symbol: symbol,
//attributes: attr,
popupTemplate: {
title: "{Name}",
content: [{
type: "fields",
fieldInfos: [{
fieldName: "X"
}, {
fieldName: "Y"
}]
}]
}
});
tempGraphicsLayer.add(graphic);
if(currentGraphic){
//currentGraphic.geometry.rings.push(geometry.rings[0]);
geometry.rings.forEach( ring => currentGraphic.geometry.addRing(ring));
//currentGraphic.geometry.addRing(geometry.rings);
//console.log('current active', geometry);
// console.log('current graphic', currentGraphic.geometry);
graphic = currentGraphic;
}
var saveObj = graphic.toJSON();
// console.log('saveObj', saveObj);
$x('P24_JSON').value = JSON.stringify(saveObj);
} else {
apex.message.alert('&G_MAP_BOUNDRY_MSG.');
}
updateGraphic = null;
}
function addMultiGraph(evt1) {
//let currentGraphic = popActiveGraphic(tempGraphicsLayer);
let currentGraphic = saveGraphicsLayer.graphics.items.pop();
var geometry = evt1.geometry;
var vertices = evt1.vertices;
var symbol;
// Choose a valid symbol based on return geometry
switch (geometry.type) {
case "point":
symbol = pointSymbol;
break;
case "polyline":
symbol = polylineSymbol;
break;
default:
symbol = polygonSymbol;
break;
}
//console.log("ring",geometry.rings )
let graphic = new Graphic({
geometry: geometry,
symbol: symbol,
//attributes: attr,
popupTemplate: {
title: "{Name}",
content: [{
type: "fields",
fieldInfos: [{
fieldName: "X"
}, {
fieldName: "Y"
}]
}]
}
});
tempGraphicsLayer.add(graphic);
if(currentGraphic){
geometry.rings.forEach( ring => currentGraphic.geometry.addRing(ring));
}
var saveObj1 = graphic.toJSON();
//console.log('saveObj', graphic);
$x('P24_JSON').value = JSON.stringify(saveObj1);
updateGraphic = null;
}
window.loadGraphic = function(polygon){
if(polygon===undefined || polygon === ''){
console.error('no polygon');
} else {
var graphic = Graphic.fromJSON(JSON.parse(polygon));
if (graphic.geometry){
addMultiGraph(graphic);
//*********************************************************************
view.center.longitude = graphic.geometry.centroid.longitude;
view.center.latitude = graphic.geometry.centroid.latitude;
view.center = [graphic.geometry.centroid.longitude,
graphic.geometry.centroid.latitude];
view.zoom = 12;
}
}
}
// *************************************
// activate the sketch to create a point
// *************************************
var drawPointButton = document.getElementById("pointButton");
drawPointButton.onclick = function () {
// set the sketch to create a point geometry
sketchViewModel.create("point");
setActiveButton(this);
};
// ****************************************
// activate the sketch to create a polyline
// ****************************************
var drawLineButton = document.getElementById("polylineButton");
drawLineButton.onclick = function () {
// set the sketch to create a polyline geometry
sketchViewModel.create("polyline");
setActiveButton(this);
};
var drawPolygonButton = document.getElementById("polygonButton");
drawPolygonButton.onclick = function () {
// set the sketch to create a polygon geometry
sketchViewModel.create("polygon");
setActiveButton(this);
};
// ***************************************
// activate the sketch to create a rectangle
// ***************************************
var drawRectangleButton = document.getElementById(
"rectangleButton");
drawRectangleButton.onclick = function () {
// set the sketch to create a polygon geometry
sketchViewModel.create("rectangle");
setActiveButton(this);
};
document.getElementById("resetBtn").onclick = function () {
sketchViewModel.reset();
tempGraphicsLayer.removeAll();
saveGraphicsLayer.removeAll();
setActiveButton();
drawBoundry();
};
function setActiveButton(selectedButton) {
// focus the view to activate keyboard shortcuts for sketching
view.focus();
var elements = document.getElementsByClassName("active");
for (var i = 0; i < elements.length; i++) {
elements[i].classList.remove("active");
}
if (selectedButton) {
selectedButton.classList.add("active");
}
}
// ************************************************************************************
// set up logic to handle geometry update and reflect the update on "tempGraphicsLayer"
// ************************************************************************************
function setUpClickHandler() {
view.on("click", function (evt) {
view.hitTest(evt).then(function (response) {
var results = response.results;
// Found a valid graphic
if (results.length && results[results.length - 1]
.graphic) {
// Check if we're already editing a graphic
if (!updateGraphic) {
// Save a reference to the graphic we intend to update
updateGraphic = results[results.length - 1].graphic;
// Remove the graphic from the GraphicsLayer
// Sketch will handle displaying the graphic while being updated
tempGraphicsLayer.remove(updateGraphic);
sketchViewModel.update(updateGraphic.geometry);
}
}
});
});
}
function errorCallback(error) {
console.log('error:', error);
}
// ************************************************************************************
// returns graphic object if drawn on the map to contcat new graphics to it
// ************************************************************************************
function popActiveGraphic(graphicsLayer){
let length = graphicsLayer.graphics.length;
let count = 0;
if($v('P0_USER_LIMITS').length > 0){
count++;
}
if(length > count){ //active drawing detected
let result = graphicsLayer.graphics.items[length-1];
graphicsLayer.remove(result);
return result;
}
}
});
});
OK, you can resolve the queries on the client or on the server. Depends on your task what options you can pick on.
If you are going to use a spatial query, like the one you mention, and you will apply it on a FeatureLayer, you could solve it on the client. This is a good solution because you already have the features, you are seeing them. Here you have a question whis this situation, how-to-get-get-name-of-hospital-or-street-in-particular-area-when-draw-polyline.
Now, If you need to query something that might not be in your extent (you don't have the features) or you are not using a FeatureLayer, you probably will need to command the server to do this. But don't worry the library has several tools to work with, like QueryTask.
Here you have the same example of the answer link before but using QueryTask.
<html>
<head>
<meta charset='utf-8'>
<meta name='viewport' content='initial-scale=1, maximum-scale=1, user-scalable=no'>
<title>Select Feature With Polygon</title>
<style>
html,
body {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
#viewDiv {
padding: 0;
margin: 0;
height: 400px;
width: 100%;
}
#namesDiv {
margin: 10px;
height: 200px;
width: 100%;
font-style: italic;
font-weight: bold;
font-family: Arial, Helvetica, sans-serif;
font-size: 16px;
color: green;
overflow: auto;
}
</style>
<link rel='stylesheet' href='https://js.arcgis.com/4.15/esri/css/main.css'>
<script src='https://js.arcgis.com/4.15/'></script>
<script>
require([
'esri/Map',
'esri/views/MapView',
'esri/layers/MapImageLayer',
'esri/layers/GraphicsLayer',
'esri/widgets/Sketch/SketchViewModel',
'esri/Graphic',
'esri/widgets/Expand',
'esri/tasks/QueryTask',
'esri/tasks/support/Query'
], function (
Map,
MapView,
MapImageLayer,
GraphicsLayer,
SketchViewModel,
Graphic,
Expand,
QueryTask,
Query
) {
let highlight = null;
const states = new MapImageLayer({
url: 'https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer'
});
const queryTask = new QueryTask({
url: 'https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/2'
});
const polygonGraphicsLayer = new GraphicsLayer();
const selected = new GraphicsLayer();
const map = new Map({
basemap: 'streets',
layers: [states, polygonGraphicsLayer, selected]
});
const view = new MapView({
container: 'viewDiv',
map: map,
center: [-75.1683665, 39.951817],
zoom: 8
});
const sketchViewModel = new SketchViewModel({
view: view,
layer: polygonGraphicsLayer,
pointSymbol: {
type: 'simple-marker',
color: [255, 255, 255, 0],
size: '1px',
outline: {
color: 'gray',
width: 0
}
}
});
sketchViewModel.on('create', function (event) {
if (event.state === 'complete') {
polygonGraphicsLayer.remove(event.graphic);
selectFeatures(event.graphic.geometry);
}
});
const namesDiv = document.getElementById('namesDiv');
view.ui.add('select-by-polygon', 'top-left');
const selectButton = document.getElementById('select-by-polygon');
selectButton.addEventListener('click', function () {
clearUpSelection();
sketchViewModel.create('polygon');
});
function selectFeatures(geometry) {
selected.removeAll();
const query = new Query();
query.returnGeometry = true;
query.outFields = ['*'];
query.geometry = geometry;
queryTask
.execute(query)
.then(function (results) {
const graphics = results.features.map(r => {
r.symbol = {
type: 'simple-fill',
fill: 'none',
outline: {
color: 'cyan',
width: 2
}
};
return r;
});
selected.addMany(graphics);
namesDiv.innerHTML = graphics.map(g => g.attributes.NAME).join(',');
})
.catch(errorCallback);
}
function clearUpSelection() {
selected.removeAll();
namesDiv.innerHTML = null;
}
function errorCallback(error) {
console.log('error:', error);
}
});
</script>
</head>
<body>
<div id='viewDiv'>
<div
id="select-by-polygon"
class="esri-widget esri-widget--button esri-widget esri-interactive"
title="Select counties by polygon"
>
<span class="esri-icon-checkbox-unchecked"></span>
</div>
</div>
<div id="namesDiv"></div>
</body>
</html>
To close I leave you this link to the documentation that explains very well all the possibilities, pros and cons.

Adding graphic layer to map in arcgis java script api

I am using arcgis js api.I have called all necessary esri class modules and all class name in order. I am using query task to add points to map as a graphic layer.I am getting error for graphic.I am not able to trace the error.
var map;
var toc;
var mapserviceurl = "http://......./arcgisserver/rest/services/CRD/CRD1/MapServer";
require(["dojo/parser",
"dojo/on", "esri/map","esri/dijit/HomeButton",
"esri/dijit/Measurement", "dojo/_base/lang","esri/layers/ArcGISDynamicMapServiceLayer",
"esri/layers/FeatureLayer","esri/graphic","esri/layers/GraphicsLayer",
"esri/dijit/Scalebar","esri/dijit/BasemapGallery","esri/toolbars/navigation",
"esri/dijit/OverviewMap","esri/geometry/Extent","esri/SpatialReference",
"esri/geometry/webMercatorUtils","esri/tasks/query","esri/tasks/QueryTask",
"esri/toolbars/draw","esri/symbols/SimpleLineSymbol","esri/symbols/SimpleFillSymbol",
"esri/symbols/PictureMarkerSymbol","esri/symbols/SimpleMarkerSymbol",
"esri/renderers/SimpleRenderer","esri/geometry/Point","esri/Color",
"agsjs/dijit/TOC","esri/InfoTemplate", "esri/tasks/IdentifyTask",
"esri/tasks/IdentifyParameters", "esri/dijit/Popup", "dojo/dom-construct",
"esri/tasks/locator","dojo/_base/array", "dojo/domReady!"],
function (parser, on, Map, HomeButton, Measurement,lang, ArcGISDynamicMapServiceLayer, FeatureLayer, graphic, GraphicsLayer, Scalebar, BasemapGallery, Navigation, OverviewMap, Extent, SpatialReference,
webMercatorUtils, Query, QueryTask, DrawToolbar, SimpleLineSymbol, SimpleFillSymbol,
PictureMarkerSymbol, SimpleMarkerSymbol, SimpleRenderer,Point,Color,TOC,InfoTemplate,IdentifyTask,IdentifyParameters,
Popup,domConstruct,Locator,arrayUtils) {
parser.parse();
createDialogs();
var identifyTask, identifyParams;
var intialextent = new Extent(7778597.959975056, 1564947.1810059766, 9217107.340624947, 2133123.2518000016, new SpatialReference({ wkid: 102100 }));
map = new Map("divMap", {
basemap: "streets",
center: [75, 14],
zoom: 7,
extent: intialextent,
logo: false,
fitExtent: true,
slider: true
});
var operationalLayer = new ArcGISDynamicMapServiceLayer(mapserviceurl);
var samplelocations = new GraphicsLayer({ id: "Samplelocations" });
var samplelocationsSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 10, SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([239, 107, 0]), 1), new Color([239, 107, 0]));
var samplelocationrenderer = new SimpleRenderer(samplelocations);
samplelocations.setRenderer(samplelocationrenderer);
var home = new HomeButton({
map: map
}, "HomeButton");
home.startup();
map.on('layers-add-result', function (evt) {
try {
var toc = new TOC({
map: map,
layerInfos: [{
layer: pointFeatureLayer,
title: "My Feature"
}, {
layer: operationalLayer,
title: "Dynamic Map"
}]
}, "tocDiv");
toc.startup();
toc.on("load", function () {
console.log("TOC loaded");
});
}
catch (e) {
console.error(e.message);
}
});
map.addLayers([operationalLayer, pointFeatureLayer, samplelocations]);
var basemapGallery = new BasemapGallery({
showArcGISBasemaps: true,
map: map
}, "basemapGallery");
basemapGallery.on("load", function () {
basemapGallery.remove('basemap_1');
basemapGallery.remove('basemap_2');
basemapGallery.remove('basemap_3');
basemapGallery.remove('basemap_4');
basemapGallery.remove('basemap_5');
basemapGallery.remove('basemap_8');
});
basemapGallery.startup();
var Scalebar = new Scalebar({
map: map,
scalebarUnit: 'metric',
scalebarStyle: 'line'
});
var measurement = new Measurement({
map: map
}, measurementDiv);
measurement.startup();
map.on("mouse-move", showcoordiantes);
map.on("mouse-drag", showcoordiantes);
//overview tools
var OverviewMap = new OverviewMap({
map: map,
attachTo: "bottom-right",
color: " #D84E13",
opacity: .40
});
OverviewMap.startup();
function showcoordiantes(evt) {
var p = webMercatorUtils.webMercatorToGeographic(evt.mapPoint);
$("#latlong").html("Lat,Long : " + p.y.toFixed(4) + "," + p.x.toFixed(4));
}
$("#ClearGraphics").click(function (e) {
e.preventDefault();
// drawtools.deactivate();
map.infoWindow.hide();
map.setMapCursor("default");
map.graphics.clear();
});
var navToolbar = new Navigation(map);
//zoom In
$("#ZoomInTool").click(function (e) {
e.preventDefault();
map.setMapCursor("url('images/cursors/zoomin.cur'), auto");
navToolbar.activate(Navigation.ZOOM_IN);
});
//ZoomOut
$("#ZoomOutTool").click(function (e) {
e.preventDefault();
map.setMapCursor("url('images/cursors/zoomout.cur'), auto");
navToolbar.activate(Navigation.ZOOM_OUT);
});
//Pan
$("#panTool").click(function (e) {
e.preventDefault();
map.setMapCursor("url('images/cursors/pan.cur'), auto");
navToolbar.activate(Navigation.PAN);
});
//FullExtent
$("#zoomfullext").click(function (e) {
e.preventDefault();
map.setMapCursor("default");
navToolbar.deactivate();
// navToolbar.zoomToFullExtent();
map.setExtent(intialextent, true);
});
//Zoom to previous
$("#zoomtoPrevExtent").click(function (e) {
e.preventDefault();
map.setMapCursor("default");
navToolbar.deactivate();
navToolbar.zoomToPrevExtent();
});
//Zoom to Next
$("#zoomtoNextExtent").click(function (e) {
e.preventDefault();
map.setMapCursor("default");
navToolbar.deactivate();
navToolbar.zoomToNextExtent();
});
map.on("load", showresults)
function showresults() {
var queryTask = new esri.tasks.QueryTask('http://......./arcgisserver/rest/services/CRD/CRD2/MapServer/0');
var query = new esri.tasks.Query();
symbol = new esri.symbol.SimpleMarkerSymbol();
symbol.setStyle(esri.symbol.SimpleMarkerSymbol.STYLE_SQUARE);
symbol.setSize(10);
symbol.setColor(new dojo.Color([255, 255, 0, 0.5]));
query.returnGeometry = true;
query.outFields = ["*"];
query.outSpatialReference = map.spatialReference;
query.where = "objectid = '" + 5281902 + "'";
map.graphics.clear();
queryTask.execute(query, addPointsToMap);
function addPointsToMap(featureSet) {
var graphic = featureSet.features;
graphic.setSymbol(symbol);
map.graphics.add(graphic);
var extent = esri.graphicsExtent(features);
if (extent) {
map.setExtent(extent)
}
}
}
});
I am getting error as
You are assigning an array to the graphic variable:
var graphic = featureSet.features;
Select a single feature of the array and set the symbol then e.g.
var graphic = featureSet.features[0];

Cluster Layer in Arcgis

Can someone please help me out of this problem. What's wrong in the above code it will not shows any error but cluster layer not displaying.Remaining features are working.I am using this example https://github.com/nickcam/FlareClusterLayer
var dojoConfig = {
async: true,
packages: [{
name: 'extras',
location: location.pathname.replace(/[^\/]+$/, '') + 'JS/extras'
}]
};
var findTask, findParams;
ready(function () {
parser.parse();
var clusterLayer;
// registry.byId("ddlDistrict").on("onchange", doFind);
var intialextent = new Extent(8245227.8765913, 1297819.43274543, 8758703.79511306, 2095175.01113784, new SpatialReference({ wkid: 102100 }));
var AgricultureBoundary = new ArcGISDynamicMapServiceLayer("http://[myserver]/arcgisserver/rest/services/CRD/CRD1/MapServer", {
opacity: 0.75
});
var pointFeatureLayer = new FeatureLayer("http://[myserver]/arcgisserver/rest/services/CRD/CRD2/FeatureServer/0", {
id: "Points"
});
map = new Map("mapDiv", {
center: [77.2, 14],
zoom: 7,
extent: intialextent,
basemap: "streets",
});
map.addLayers([AgricultureBoundary, pointFeatureLayer]);
var queryTask = new esri.tasks.QueryTask("http://[myserver]/arcgisserver/rest/services/CRD/CRD2/FeatureServer/0");
var query = new esri.tasks.Query();
query.returnGeometry = true;
query.where = "pointcollected = 'No'";
query.outFields = ["*"];
dojo.connect(queryTask, "onComplete", function (featureSet) {
var inputInfo = {};
inputInfo.data = dojo.map(featureSet.features, function (feature) {
var pointX = feature.geometry.x;
var pointY = feature.geometry.y;
var att = feature.attributes;
return { "x": pointX, "y": pointY, "attributes": att };
});
clusterLayer = new ClusterFeatureLayer({
"data": inputInfo.data,
"distance": 1,
"id": "clusters",
"labelColor": "#fff",
"labelOffset": 10,
"resolution": map.extent.getWidth() / map.width,
"singleColor": "#888",
"singleTemplate": infoTemplate
});
var defaultSym = new esri.symbol.SimpleMarkerSymbol().setSize(4);
var renderer = new esri.renderer.ClassBreaksRenderer(defaultSym, "clusterCount");
var blue = new esri.symbol.PictureMarkerSymbol("http://static.arcgis.com/images/Symbols/Shapes/BluePin1LargeB.png", 32, 32).setOffset(0, 15);
var green = new esri.symbol.PictureMarkerSymbol("http://static.arcgis.com/images/Symbols/Shapes/GreenPin1LargeB.png", 64, 64).setOffset(0, 15);
var red = new esri.symbol.PictureMarkerSymbol("http://static.arcgis.com/images/Symbols/Shapes/RedPin1LargeB.png", 72, 72).setOffset(0, 15);
renderer.addBreak(0, 2, blue);
renderer.addBreak(2, 200, green);
renderer.addBreak(200, 1001, red);
clusterLayer.setRenderer(renderer);
map.addLayer(clusterLayer);
});
});
Passing data in the constructor like that won't do anything (although it probably should handle it).
Try the below instead:
dojo.connect(queryTask, "onComplete", function (featureSet) {
var inputInfo = {};
inputInfo.data = dojo.map(featureSet.features, function (feature) {
var pointX = feature.geometry.x;
var pointY = feature.geometry.y;
var att = feature.attributes;
return { "x": pointX, "y": pointY, "attributes": att };
});
clusterLayer = new ClusterFeatureLayer({
"distance": 1,
"id": "clusters",
"labelColor": "#fff",
"labelOffset": 10,
"resolution": map.extent.getWidth() / map.width,
"singleColor": "#888",
"singleTemplate": infoTemplate
});
var defaultSym = new esri.symbol.SimpleMarkerSymbol().setSize(4);
var renderer = new esri.renderer.ClassBreaksRenderer(defaultSym, "clusterCount");
var blue = new esri.symbol.PictureMarkerSymbol("http://static.arcgis.com/images/Symbols/Shapes/BluePin1LargeB.png", 32, 32).setOffset(0, 15);
var green = new esri.symbol.PictureMarkerSymbol("http://static.arcgis.com/images/Symbols/Shapes/GreenPin1LargeB.png", 64, 64).setOffset(0, 15);
var red = new esri.symbol.PictureMarkerSymbol("http://static.arcgis.com/images/Symbols/Shapes/RedPin1LargeB.png", 72, 72).setOffset(0, 15);
renderer.addBreak(0, 2, blue);
renderer.addBreak(2, 200, green);
renderer.addBreak(200, 1001, red);
clusterLayer.setRenderer(renderer);
map.addLayer(clusterLayer);
clusterLayer.addData(inputInfo.data);
});

KineticJs-how to update x and y position of the multiple images after resizing the stage layer

As I am new to KineticJs so, I have tried implementing the functionality using Kinectic js for drawing the multiple image on different- different x and y. Now I wanted to resize the stage layer or canvas. I have done that by using the code given below
window.onresize = function (event) {
stage.setWidth(($('#tab' + tabId).innerWidth() / 100) * 80);
var _images = layer.getChildren();
for (var i = 0; i < _images.length; i++) {
if (typeof _images[i].getId() != 'undefined') {
//alert(stage.getScale().x);
_images[i].setX(_images[i].getX() * stage.getScale().x);
layer.draw();
}
}
}
but now the problem is the are being defined and now if browser resize than stage is resized but the images on the prev x and y are fixed . I would like to keep them fixed on the position on resizing of stage layer or canvas.Here are the link of the image before resize and after resizing.beforeresize and afterResize .
Here is my entire code given below:-
$("#tabs li").each(function () {
$(this).live("click", function () {
clearInterval(_timer);
var tabname = $(this).find("a").attr('name');
tabname = $.trim(tabname.replace("#tab", ""));
var tabId = $(this).find("a").attr('href');
tabId = $.trim(tabId.replace("#", ""));
$.ajax({
url: "/Home/GetTabsDetail",
dataType: 'json',
type: 'GET',
data: { tabId: tabId },
cache: false,
success: function (data) {
var bayStatus = [];
var i = 0;
var image_array = [];
var BayExist = false;
var BayCondition;
var imgSrc;
var CanvasBacgroundImage;
var _X;
var _bayNumber;
var _Y;
var _ZoneName;
$(data).each(function (i, val) {
i = i + 1;
if (!BayExist) {
bayStatus = val.BayStatus;
CanvasBacgroundImage = val.TabImageLocation;
BayExist = true;
}
$.each(val, function (k, v) {
if (k == "BayNumber") {
BayCondition = bayStatus[v];
_bayNumber = v;
if (BayCondition == "O")
imgSrc = "../../images/Parking/OccupiedCar.gif"
else if (BayCondition == "N")
imgSrc = "../../images/Parking/OpenCar.gif";
}
if (k == "BayX")
_X = v;
if (k == "BayY")
_Y = v;
if (k == "ZoneName")
_ZoneName = v;
});
image_array.push({ img: imgSrc, xAxis: _X, yAxis: _Y, toolTip: _bayNumber, ZoneName: _ZoneName });
});
var imageUrl = CanvasBacgroundImage;
if ($('#tab' + tabId).length) {
// $('#tab' + tabId).css('background-image', 'url("../../images/Parking/' + imageUrl + '")');
var stage = new Kinetic.Stage({
container: 'tab' + tabId,
width: ($('#tab' + tabId).innerWidth() / 100) * 80, // 80% width of the window.
height: 308
});
window.onresize = function (event) {
stage.setWidth(($('#tab' + tabId).innerWidth() / 100) * 80);
}
$('#tab' + tabId).find('.kineticjs-content').css({ 'background-image': 'url("../../images/Parking/' + imageUrl + '")', 'background-repeat': ' no-repeat', 'background-size': '100% 100%' });
var layer = new Kinetic.Layer();
var planetOverlay;
function writeMessage(message, _x, _y) {
text.setX(_x + 20);
text.setY(_y + 1);
text.setText(message);
layer.draw();
}
var text = new Kinetic.Text({
fontFamily: 'Arial',
fontSize: 14,
text: '',
fill: '#000',
width: 200,
height: 60,
align: 'center'
});
var opentooltip = new Opentip(
"div#tab" + tabId, //target element
"dummy", // will be replaced
"", // title
{
showOn: null // I'll manually manage the showOn effect
});
Opentip.styles.win = {
borderColor: "black",
shadow: false,
background: "#EAEAEA"
};
Opentip.defaultStyle = "win";
// _timer = setInterval(function () {
for (i = 0; i < image_array.length; i++) {
img = new Image();
img.src = image_array[i].img;
planetOverlay = new Kinetic.Image({
x: image_array[i].xAxis,
y: image_array[i].yAxis,
image: img,
height: 18,
width: 18,
id: image_array[i].toolTip,
name: image_array[i].ZoneName
});
planetOverlay.on('mouseover', function () {
opentooltip.setContent("<span style='color:#87898C;'><b>Bay:</b></span> <span style='color:#25A0D3;'>" + this.getId() + "</span><br> <span style='color:#87898C;'><b>Zone:</b></span><span style='color:#25A0D3;'>" + this.getName() + "</span>");
//writeMessage("Bay: " + this.getId() + " , Zone: " + this.getName(), this.getX(), this.getY());//other way of showing tooltip
opentooltip.show();
$("#opentip-1").offset({ left: this.getX(), top: this.getY() });
});
planetOverlay.on('mouseout', function () {
opentooltip.hide();
// writeMessage('');
});
planetOverlay.createImageHitRegion(function () {
layer.draw();
});
layer.add(planetOverlay);
layer.add(text);
stage.add(layer);
}
// clearInterval(_timer);
//$("#tab3 .kineticjs-content").find("canvas").css('background-image', 'url("' + imageUrl + '")');
// },
// 500)
}
}
,
error: function (result) {
alert('error');
}
});
});
});
I want to keep the icons on the position where they were before resizing. I have tried but could not get the right solution to get this done.
How can How can I update x,y position for the images . Any suggestions would be appreciated.
Thanks is advance.
In window.resize, you're changing the stage width by a scaling factor.
Save that scaling factor.
Then multiply the 'x' coordinate of your images by that scaling factor.
You can reset the 'x' position of your image like this:
yourImage.setX( yourImage.getX() * scalingFactor );
layer.draw();
In the above mentioned code for window.onresize. The code has been modified which as follow:-
window.onresize = function (event) {
_orignalWidth = stage.getWidth();
var _orignalHeight = stage.getHeight();
// alert(_orignalWidth);
// alert($('#tab' + tabId).outerHeight());
stage.setWidth(($('#tab' + tabId).innerWidth() / 100) * 80);
//stage.setHeight(($('#tab' + tabId).outerHeight() / 100) * 80);
_resizedWidth = stage.getWidth();
_resizedHeight = stage.getHeight();
// alert(_resizedWidth);
_scaleFactorX = _resizedWidth / _orignalWidth;
var _scaleFactorY = _resizedHeight / _orignalHeight;
//alert(_scaleFactor);
var _images = layer.getChildren();
for (var i = 0; i < _images.length; i++) {
if (typeof _images[i].getId() != 'undefined') {
//alert(stage.getScale().x);
_images[i].setX(_images[i].getX() * _scaleFactorX);
//_images[i].setY(_images[i].getY() * _scaleFactorY);
layer.draw();
}
}
}