I'm developing an application in DevExtreme Mobile. In application, I use DXMap in this application. How can I use the marker clusterer structure in DevExtreme Mobile App?
You can use Google Maps Marker Clusterer API to create and manage per-zoom-level clusters for a large number of DevExtreme dxMap markers. Here is an example:
dxMap Marker Clusterer
This example is based on the approach described in the Google Too Many Markers! article
Here is sample code:
$("#dxMap").dxMap({
zoom: 3,
width: "100%",
height: 800,
onReady: function (s) {
var map = s.originalMap;
var markers = [];
for (var i = 0; i < 100; i++) {
var dataPhoto = data.photos[i];
var latLng = new google.maps.LatLng(dataPhoto.latitude, dataPhoto.longitude);
var marker = new google.maps.Marker({
position: latLng
});
markers.push(marker);
}
var markerCluster = new MarkerClusterer(map, markers);
}
});
The kry is to use the google maps api. I did it for my app, here how.
This the html, very simple:
<div data-options="dxView : { name: 'map', title: 'Punti vendita', pane: 'master', secure:true } ">
<div data-bind="dxCommand: { id: 'back', behavior: 'back', type: 'back', visible: false }"></div>
<div data-options="dxContent : { targetPlaceholder: 'content' } ">
<div style="width: 100%; height: 100%;">
<div data-bind="dxMap:options"></div> <!--this for the map-->
<div id="large-indicator" data-bind="dxLoadIndicator: {height: 60,width: 60}" style="display:inline;z-index:99;" />
<div data-bind="dxPopover: {
width: 200,
height: 'auto',
visible: visible,
}">
</div>
</div>
</div>
</div>
When the page loads, the app read the gps coordinates:
function handleViewShown() {
navigator.geolocation.getCurrentPosition(onSuccess, onError, options);
jQuery("#large-indicator").css("display", "none"); //this is just a gif to indicate the user to wait the end of the operation
}
If the gps location is correctly read, I save the coordinates (the center of the map):
function onSuccess(position) {
var lat1 = position.coords.latitude;
var lon1 = position.coords.longitude;
center([lat1, lon1]);
}
And these are the options I set to my dxMap:
options: {
showControls: true,
key: { google: "myGoogleApiKey" },
center: center,
width: "100%",
height: "100%",
zoom: zoom,
provider: "google",
mapType: "satellite",
autoAdjust: false,
onReady: function (s) {
LoadPoints();
var map = s.originalMap;
var markers = [];
for (var i = 0; i < MyPoints().length; i++) {
var data = MyPoints()[i];
var latLng = new google.maps.LatLng(data.location[0], data.location[1]);
var marker = createMarker(latLng, data.title, map, data.idimp);
markers.push(marker);
}
var markerCluster = new MarkerClusterer(map, markers, { imagePath: 'images/m' });
}
},
Where MyPoints is populated calling LoadPoints:
function LoadPoints() {
$.ajax({
type: "POST",
async:false,
contentType: "application/json",
dataType: "json",
url: myApiUrl,
success: function (Response) {
var tempArray = [];
for (var point in Response) {
var location = [Response[p]["latitudine"], Response[p]["longitudine"]];
var title = Response[p]["name"] + " - " + Response[p]["city"];
var temp = { title: title, location: location, tooltip: title, onClick: GoToNavigator, idpoint: Response[p]["id"] };
tempArray.push(temp);
}
MyPoints(tempArray);
},
error: function (Response) {
jQuery("#large-indicator").css("display", "none");
var mex = Response["responseText"];
DevExpress.ui.notify(mex, "error");
}
});
}
Note that in the folder Myproject.Mobile/images I included the images m1.png, m2.png, m3.png, m4.png and m5.png.
You can found them here.
Related
I am trying to save Fabric.js canvas and reload it using loadFromJson. But I am getting error patternSourceCanvas is not defined. I thought I should make it global so I removed var.
How to set the global variable in Fabric JS and use var patternSourceCanvas?
When I use the code below, then everything is working fine and the JSON is loaded easily.
var t = https://image.freepik.com/free-photo/roof-texture_21206171.jpg
fabric.util.loadImage(t, function(t) {
var svg_width = i.width;
console.log('svg widh' + i.width + 'svg height' + i.height);
console.log('img width t'+ t.width + ' img height' + t.height);
if(svg_width >= 300){
if (i.isSameColor && i.isSameColor() || !i.paths) {
i.setPatternFill({
source: t, repeat: 'repeat', offsetX:200 , offsetY : -110 // working
}), e.fabric.renderAll();
console.log('in if image 300 up ', t);
} else if (i.paths){
for (var r = 0; r < i.paths.length; r++)
i.paths[r].setPatternFill({
source: t, repeat: 'repeat' , offsetX: -100 , offsetY:-110
}), e.fabric.renderAll();
console.log('in image elseeee 300 up ', t);
}
}
})
But when I fill some other new shape with the new patternSourceCanvas variable then it's not working. Kindly help me with dynamic patterns.
var t = https://image.freepik.com/free-photo/roof-texture_21206171.jpg
fabric.Image.fromURL(t, function (img) {
img.scaleToHeight(200);
var patternSourceCanvas = new fabric.StaticCanvas();
patternSourceCanvas.add(img);
patternSourceCanvas.renderAll();
var pattern = new fabric.Pattern({
source: function() {
patternSourceCanvas.setDimensions({
width: img.getScaledWidth() ,
height: img.getScaledHeight()
});
patternSourceCanvas.renderAll();
return patternSourceCanvas.getElement();
},
repeat: r
});
console.log('pattern', pattern);
//p.set('fill', pattern);
canvas.renderAll();
if (i.isSameColor && i.isSameColor() || !i.paths) {
i.setPatternFill(pattern);
} else if(i.paths) {
for (var r = 0; r < i.paths.length; r++) {
i.paths[r].setPatternFill(pattern);
}
}
e.fabric.renderAll();
});
You need to put patternSourceCanvas to global scope/ scope where loadFromJSON can access patternSourceCanvas. Else you can use cors enabled image directly.
DEMO
var imageUrl = 'https://upload.wikimedia.org/wikipedia/commons/2/22/Wikimapia_logotype.svg';
var canvas = new fabric.Canvas('canvas');
var rect = new fabric.Rect({
width: 200,
height: 200,
strokeWidth: 2,
stroke: '#000'
})
canvas.add(rect);
fabric.Image.fromURL(imageUrl, function(img) {
img.scaleToHeight(200);
var patternSourceCanvas = new fabric.StaticCanvas();
patternSourceCanvas.add(img);
patternSourceCanvas.setDimensions({
width: img.getScaledWidth(),
height: img.getScaledHeight()
});
patternSourceCanvas.renderAll();
var pattern = new fabric.Pattern({
source: patternSourceCanvas.getElement()
},
function(patternObj) {
rect.fill = patternObj;
rect.dirty = true;
canvas.renderAll();
});
}, {
crossOrigin: 'annonymous'
});
function loadfromjson() {
var json = canvas.toJSON();
canvas.clear();
setTimeout(function() {
canvas.loadFromJSON(json, canvas.renderAll.bind(canvas));
}, 1000)
}
canvas{
border:2px solid #000;
}
<canvas id="canvas" width="300" height="300"></canvas><br>
<button onclick="loadfromjson()">loadfromjson </button>
<script src='https://rawgit.com/kangax/fabric.js/master/dist/fabric.js'></script>
I am adding a plugin which insert twitter embed code. the problem is that I can see the tweet on the editor but not in the source code and preview. And I can't save it. I saw in forum that I have to add 'http:' to '//platform.twitter.com/widgets.js' and put it before , unfortunately, it's not working. This is the code I put:
tinymce.PluginManager.add('twitter', function(editor, url) {
editor.on('init', function (args) {
editor_id = args.target.id;
});
editor.addButton('twitter', {
text: 'Twitter',
icon: false,
onclick: function () {
editor.windowManager.open({
title: 'Twitter Embed',
body: [
{ type: 'textbox',
size: 40,
height: '100px',
name: 'twitter',
label: 'twitter'
}
],
onsubmit: function(e) {
var embedCode = e.data.twitter;
var script = embedCode.match(/<script.*<\/script>/)[0];
var scriptSrc = script.match(/".*\.js/)[0].split("\"")[1];
console.log(script);
var sc = document.createElement("script");
sc.setAttribute("src", "https:"+scriptSrc);
sc.setAttribute("type", "text/javascript");
var iframe = document.getElementById(editor_id + "_ifr");
var iframeHead = iframe.contentWindow.document.getElementsByTagName('head')[0];
var iframeBody = iframe.contentWindow.document.getElementsByTagName('body')[0];
embedCode1 = embedCode.replace('//platform.twitter.com/widgets.js','https://platform.twitter.com/widgets.js');
iframeBody.appendChild(sc);
editor.insertContent(embedCode1);
iframeHead.appendChild(sc);
// setTimeout(function() {
// iframe.contentWindow.twttr.widgets.load();
// }, 1000)
}
});
}
});
});
I have been working on a project in which I used Cytoscape.js with Angular.js. I am facing an issue regarding the loading of the graph. The problem I am facing is that the graph doesn't load on first attempt when the page is refreshed.
The specific scenario is when I am on a view with graph in the view's html, If I refresh the page from that view, the next time I open the graph, the graph shows correctly. But when I am not on a view with graph in it's html, the graph won't load if I refresh my page from that view.
I have searched and found an almost similar problem someone else faced but the solution is not helping me.
Cytoscape.js, graph is not displayed with correct settings
Here is my HTML Code.
<div class="col-sm-12" style="height:100%;width:100%;margin-top:5px;">
<div ng-show="cyLoaded" ng-model="cyLoaded" id="cy" ng-init="ShowProjectRelationGraph(1)" ></div>
<div ng-show="!cyLoaded" ng-model="cyLoaded" class="row" style="align-items:center;margin-top:100px;">
<div class="col-sm-5"></div>
<div class="col-sm-2" style="padding-left:6%">
<div class="spinner-lg">
<div class="double-bounce1"></div>
<div class="double-bounce2"></div>
</div>
</div>
</div>
</div>
Here is my .js code
angular.module("VPMWeb")
.factory('nodesGraph', ['$q', function($q) {
var cy;
var nodesGraph = function(elements, signal) {
var deferred = $q.defer();
// put people model in cy.js
var eles = [];
for (var i = 0; i < elements.nodes.length; i++) {
eles.push({
group: 'nodes',
data: {
id: elements.nodes[i].data.id,
parent: elements.nodes[i].data.parent,
s_id: elements.nodes[i].data.s_id
}
});
}
for (var i = 0; i < elements.edges.length; i++) {
eles.push({
group: 'edges',
data: {
id: elements.edges[i].data.id,
source: elements.edges[i].data.source,
target: elements.edges[i].data.target,
}
});
}
$(function() { // on dom ready
cy = cytoscape({
container: $("#cy")[0],
//zoomingEnabled: false,
userZoomingEnabled: false,
style: cytoscape.stylesheet()
.selector('node')
.css({
'content': 'data(s_id)',
'text-valign': 'center',
'text-halign': 'center',
'padding-top': '10px',
'padding-left': '10px',
'padding-bottom': '10px',
'padding-right': '10px',
'text-valign': 'top',
'text-halign': 'center',
})
.selector('edge')
.css({
'target-arrow-shape': 'triangle'
})
.selector(':selected')
.css({
'background-color': 'black',
'line-color': 'black',
'target-arrow-color': 'black',
'source-arrow-color': 'black'
}),
layout: {
name: 'cose',
padding: 10,
fit: true,
randomize: true
},
elements: eles,
ready: function() {
deferred.resolve(this);
}
});
cy.center();
}); // on dom ready
return deferred.promise;
};
nodesGraph.listeners = {};
function fire(e, args) {
var listeners = nodesGraph.listeners[e];
for (var i = 0; listeners && i < listeners.length; i++) {
var fn = listeners[i];
fn.apply(fn, args);
}
}
function listen(e, fn) {
var listeners = nodesGraph.listeners[e] = nodesGraph.listeners[e] || [];
listeners.push(fn);
}
return nodesGraph;
}]);
Can someone please have a look and help with it. Thanks in advance.
If you're not setting the dimensions of the Cytoscape.js div properly in advance, then you'll have to call cy.resize().
Refs:
http://js.cytoscape.org/#getting-started/including-cytoscape.js
http://js.cytoscape.org/#cy.resize
I am using angularjs-google-map http://angular-ui.github.io/angular-google-maps/#!/api
I can add multiple markers with showing infoWindow by cliking on a marker, but now I need to show the marker infoWindow when the mouse enters the area of the marker icon and hide it when the mouse leaves the area of the marker icon instead of using the click event.
You can look on this example on Jsfiddle https://jsfiddle.net/meher12/bgb36q7b/ to get idea about my purpose !
My HTML code:
<ui-gmap-google-map center="map.center" zoom="map.zoom" dragging="map.dragging" bounds="map.bounds"
events="map.events" options="map.options" pan="true" control="map.control">
<ui-gmap-markers models="map.randomMarkers" coords="'self'" icon="'icon'"
doCluster="map.doClusterRandomMarkers" clusterOptions="map.clusterOptions" modelsbyref="true"
events="map.markersEvents" options="'options'"
>
<ui-gmap-windows show="'showWindow'" ng-cloak>
<div>
<p>This is an info window</p>
</div>
</ui-gmap-windows>
</ui-gmap-markers>
</ui-gmap-google-map>
</div>
My JS code:
myApp.controller('MainController', function ($scope,uiGmapGoogleMapApi) {
$scope.numOfMarkers = 25;
uiGmapGoogleMapApi.then(function(maps) { $scope.googleVersion = maps.version; });
$scope.map = {
center: {
latitude: 45,
longitude: -73
},
zoom: 10,
options: {
streetViewControl: false,
panControl: false,
maxZoom: 20,
minZoom: 3
},
dragging: false,
bounds: {},
randomMarkers: [],
doClusterRandomMarkers: true,
currentClusterType: 'standard',
clusterOptions: {
title: 'Hi I am a Cluster!', gridSize: 60, ignoreHidden: true, minimumClusterSize: 2
}
};
$scope.map.markersEvents = {
mouseover: function (marker, eventName, model, args) {
model.options.labelContent = "Position - lat: " + model.latitude + " lon: " + model.longitude;
marker.showWindow = true;
$scope.$apply();
},
mouseout: function (marker, eventName, model, args) {
model.options.labelContent = " ";
marker.showWindow = false;
$scope.$apply();
}
};
var genRandomMarkers = function (numberOfMarkers, scope) {
var markers = [];
for (var i = 0; i < numberOfMarkers; i++) {
markers.push(createRandomMarker(i, scope.map.bounds))
}
scope.map.randomMarkers = markers;
};
var createRandomMarker = function (i, bounds, idKey) {
var lat_min = bounds.southwest.latitude,
lat_range = bounds.northeast.latitude - lat_min,
lng_min = bounds.southwest.longitude,
lng_range = bounds.northeast.longitude - lng_min;
if (idKey == null)
idKey = "id";
var latitude = lat_min + (Math.random() * lat_range);
var longitude = lng_min + (Math.random() * lng_range);
var ret = {
latitude: latitude,
longitude: longitude,
title: 'm' + i,
showWindow: false,
options: {
labelContent: ' ',
labelAnchor: "22 0",
labelClass: "marker-labels",
draggable: true
}
};
ret[idKey] = i;
return ret;
};
$scope.genRandomMarkers = function (numberOfMarkers) {
genRandomMarkers(numberOfMarkers, $scope);
};
$scope.removeMarkers = function () {
$scope.map.randomMarkers = [];
};
});
Like you see on my JS code I have created markerEvents and I can get the marker label changed on mouse events but still not showing the infoWindow attached to each marker on the map when the mouse Event is fired, despite its value is changing and take the correct value.
Someone Have an idea to resolve this issue ?
Feel free to put your changes to my Jsfiddle code :)
You must set model.showWindow instead of marker.showWindow
You can set model.show = true instead of model.showWindow, in html remove show =showWindow.
I wrote this code to create chart, table and toolbar.
google.load("visualization", "1", { packages: ["corechart"] });
google.load('visualization', '1', { packages: ['table'] });
//google.setOnLoadCallback(drawChart);
function drawChart() {
$.ajax({
type: "GET",
url: '#Url.Action("GunlukOkumalar", "Enerji")',
data: "startDate=" + $('#start_date').val() + "&endDate=" + $('#end_date').val() + "&sayac_id=" + $("#sayaclar").val(), //belirli aralıklardaki veriyi cekmek için
success: function (result) {
if (result.success) {
var evalledData = eval("(" + result.chartData + ")");
var opts = { curveType: "function", width: '100%', height: 500, pointSize: 5 };
new google.visualization.LineChart($("#chart_div").get(0)).draw(new google.visualization.DataTable(evalledData, 0.5), opts);
$('#chart_div').show();
var visualization;
var data;
var options = { 'showRowNumber': true };
data = new google.visualization.DataTable(evalledData, 0.5);
// Set paging configuration options
// Note: these options are changed by the UI controls in the example.
options['page'] = 'enable';
options['pageSize'] = 10;
options['pagingSymbols'] = { prev: 'prev', next: 'next' };
options['pagingButtonsConfiguration'] = 'auto';
// Create and draw the visualization.
visualization = new google.visualization.Table(document.getElementById('table'));
visualization.draw(data, options);
var components = [
{ type: 'html', datasource: data },
{ type: 'csv', datasource: data }
];
var container = document.getElementById('toolbar_div');
google.visualization.drawToolbar(container, components);
return false;
}
else {
$('#chart_div').html('<span style="color:red;"><b>' + result.Error + '</b></span>');
$('#chart_div').show();
$('#table').html('<span style="color:red;"><b>' + result.Error + '</b></span>');
$('#table').show();
return false;
}
}
});
}
Google example
function drawToolbar() {
var components = [
{type: 'igoogle', datasource: 'https://spreadsheets.google.com/tq?key=pCQbetd-CptHnwJEfo8tALA',
gadget: 'https://www.google.com/ig/modules/pie-chart.xml',
userprefs: {'3d': 1}},
{type: 'html', datasource: 'https://spreadsheets.google.com/tq?key=pCQbetd-CptHnwJEfo8tALA'},
{type: 'csv', datasource: 'https://spreadsheets.google.com/tq?key=pCQbetd-CptHnwJEfo8tALA'},
{type: 'htmlcode', datasource: 'https://spreadsheets.google.com/tq?key=pCQbetd-CptHnwJEfo8tALA',
gadget: 'https://www.google.com/ig/modules/pie-chart.xml',
userprefs: {'3d': 1},
style: 'width: 800px; height: 700px; border: 3px solid purple;'}
];
var container = document.getElementById('toolbar_div');
google.visualization.drawToolbar(container, components);
};
Google get dataSource from url, but I get dataSource dynamicly from controller. When I try to export It forwards page to another page like this:
http://localhost:49972/Enerji/%5Bobject%20Object%5D?tqx=out%3Acsv%3B
How can I use exporting toolbar for dynamic Json data? Is there any example about this topic?
I also had this problem and after a lot of trawling I found this!
https://developers.google.com/chart/interactive/docs/dev/implementing_data_source
I haven't implemented it yet but I reckon it's the way to go.