Hyperlink on a Graphic element in ArcGis - graphics

i need your help please.
I would like to be able to click on a point added on an ArcGis map so that when I click on it I am redirected to another web page
I have been following the tutorials:
https://developers.arcgis.com/javascript/latest/display-a-map/
Display a map
Add a point
add a feature layer
Display a popup
This is the code so far:
require([
"esri/config",
"esri/Map",
"esri/views/MapView",
"esri/Graphic",
"esri/layers/GraphicsLayer",
"esri/layers/FeatureLayer"
], function(esriConfig,Map, MapView, Graphic, GraphicsLayer, FeatureLayer) {
esriConfig.apiKey = "YOUR_KEY";
const map = new Map({
basemap: "arcgis-topographic"
});
const view = new MapView({
container: "DivCarte",
map: map,
center: [-83.54500,19.02700],
zoom: 6
});
const graphicsLayer = new GraphicsLayer();
map.add(graphicsLayer);
const point = { //Create a point
type: "point",
longitude: -86.900000,
latitude: 21.201278
};
const simpleMarkerSymbol = {
type: "simple-marker",
color: [226, 119, 40], // Orange
outline: {
color: [255, 255, 255], // White
width: 1
}
};
const popupTemplate = {
title: "Cancun",
content: "<a href=http://travelwithnico.com>Site</a>"
}
const attributes = {
Name: "AttGraphic",
Description: "Ilalala"
}
const pointGraphic = new Graphic({
geometry: point,
symbol: simpleMarkerSymbol,
attributes: attributes,
popupTemplate: popupTemplate
});
graphicsLayer.add(pointGraphic);
I managed to open a popup showing the link but it opens on a new tab.
How can I force it to move to the link in the same window?
Thank you for your help.
Nico

Have you tried inlining a JavaScript inside an onclick event? Something like this:
...
content: 'Site'
...
I'm not sure if this will work, but it worths trying.

Related

Is there a way to avoid this lighting effect using tile-maps in Phaser?

Is there a way to get smooth gradient from the lighting?
I'm creating a survival game using PhaserJs 3. I'm using the LightsManager and a tileset I modified from one of the example tilesets included in the examples.
Currently the tile grid is visible because of how the lighting is working with the tiles.
If possible, I would like to have the lighting be smooth similar to the picture below:
My grass tile is 32x32:
and the normal map is the following image
which was generated using this normal map generator site.
var config = {
type: Phaser.WEBGL,
width: 800,
height: 600,
pixelArt: true,
backgroundColor: '#000000',
scene: {
preload: preload,
create: create,
update: update,
},
physics: {
default: 'arcade',
arcade: {
gravity: { y: 0, x:0 },
debug: false
}
},
};
var light;
var layer;
var game = new Phaser.Game(config);
function preload ()
{
this.load.image('tiles', ['assets/tilemap.png','assets/tilemap_n.png']);
...
}
function create ()
{
var level = [ // The grass tile is #29 in the tileset
[29,29,29,29,29,29],
[29,29,29,29,29,29],
[29,29,29,29,29,29],
[29,29,29,29,29,29],
[29,29,29,29,29,29],
[29,29,29,29,29,29]]
var map = this.make.tilemap({ data: level, tileWidth: 32, tileHeight: 32 });
var tiles = map.addTilesetImage('tiles');
layer = map.createStaticLayer(0, tiles, 0, 0).setScale(2)
layer.setPipeline('Light2D');
light = this.lights.addLight(390,223.3, 150).setIntensity(.8);
}
I'm not sure if this is the best (or most performant) way, but you could use this plugin to create a post pipeline blur.
here a working demo of this plugin: https://codepen.io/rexrainbow/pen/zYzzYVw
Basically you would have to load the plugin, in preload:
function preload (){
...
this.load.plugin('rexkawaseblurpipelineplugin', 'https://raw.githubusercontent.com/rexrainbow/phaser3-rex-notes/master/dist/rexkawaseblurpipelineplugin.min.js', true);
}
And apply the plugin in to the specific camera, or gameobject:
function create (){
var postFxPlugin = this.plugins.get('rexkawaseblurpipelineplugin');
var postFxPipeline = postFxPlugin.add(this.cameras.main, {
blur: 1,
quality: 3
});
...
}
Or you could fake, the gradient with multiple lights and may be add a specific ambientColor:
light1 = this.lights.addLight(390,300, 150, 0xffffff, .80);
light2 = this.lights.addLight(390,300, 250, 0xffffff, .75);
light3 = this.lights.addLight(390,300, 350, 0xffffff, .70);
this.lights.enable().setAmbientColor(0x555555);

How to make a tooltip appear when hovering mouse over a Phaser.GameObject.Image?

In my Phaser 3 game I'm using Phaser.GameObjects.Image 's as things that a user can click on. When a user's mouse hovers over an image I would like a tooltip with text to fade in and appear. When the mouse moves off the image, I'd like the tooltip to disappear.
How can I implement this behavior in Phaser? I'm new to Phaser and I don't see a ToolTip class in the framework.
You could:
use the pointer events for detecting, that the pointer is over an object
and animate/tween the alpha property on the over event
you can alter the speed with the tween duration
and hide the toolTip on the out event
Here the docs to the Input events: https://photonstorm.github.io/phaser3-docs/Phaser.Input.Events.html
Here a mini example:
var config = {
type: Phaser.WEBGL,
parent: 'phaser-example',
width: 800,
height: 600,
scene: {
create: create
}
};
var game = new Phaser.Game(config);
var toolTip;
var toolTipText;
function create ()
{
let objectWithToolTip = this.add.rectangle( 100, 100, 100, 100, 0xffffff).setInteractive();
toolTip = this.add.rectangle( 0, 0, 250, 50, 0xff0000).setOrigin(0);
toolTipText = this.add.text( 0, 0, 'This is a white rectangle', { fontFamily: 'Arial', color: '#000' }).setOrigin(0);
toolTip.alpha = 0;
this.input.setPollOnMove();
this.input.on('gameobjectover', function (pointer, gameObject) {
this.tweens.add({
targets: [toolTip, toolTipText],
alpha: {from:0, to:1},
repeat: 0,
duration: 500
});
}, this);
this.input.on('gameobjectout', function (pointer, gameObject) {
toolTip.alpha = 0;
toolTipText.alpha = 0;
});
objectWithToolTip.on('pointermove', function (pointer) {
toolTip.x = pointer.x;
toolTip.y = pointer.y;
toolTipText.x = pointer.x + 5;
toolTipText.y = pointer.y + 5;
});
}
<script src="//cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.min.js"></script>
Info: if you want to dig deeper into the phaser events you can checkout some examples on the offical home page: https://phaser.io/examples/v3/category/input/mouse are really good, and explore may use cases.
Extra Info: If you don't want to re-invent the wheel, there are several plugins, that can be loaded into phaser(that add special functionality to phaser).
It is always good to check this page(https://phaserplugins.com/), before implementing so common feature/function. There is even on specially for tooltips https://github.com/netgfx/Phaser-tooltip

How to implement drag and connect feature provided by Rappid with pure JointJS?

There is a feature in Rappid (the paid version of JointJS) which allows you to drag a button from the toolbox of an element and connect that element to another element where you release your mouse button.
I want to implement this feature with JointJS core library. I've managed to create a tool box with elementTools and added two buttons, one for removing the element and one for this drag and connect feature.
The Picture of element with element toolbox
The problem is the button for drag fires only when I click on the button. It doesn't allow me to drag and have x, y coordinates of the mouse.
There is a similar question which was left unanswered in stackoverflow:
Creating a ToolElement for every object JointJS
Here is my snippet for the button:
const InfoButton = joint.elementTools.Button.extend({
name: 'info-button',
options: {
focusOpacity: 0.5,
distance: 60,
action: function (evt: JQueryEventObject, elementView, buttonView) {
// alert('View id: ' + this.id + '\n' + 'Model id: ' + this.model.id);
const link = new Models.SequenceFlow();
link.set('source', { id: elementView.model.get('id') });
link.set('target', new joint.g.Point(evt.pageX, evt.pageY));
// const alev = jQuery.Event()
// evt.preventDefault();
// paper.trigger('AliEvt', evt);
link.addTo(model);
// link.se(this.model);
// link.target(new joint.g.Point(0, 0));
},
markup: [
{
tagName: 'circle',
selector: 'button',
attributes: {
r: 7,
fill: '#001DFF',
cursor: 'pointer',
},
},
{
tagName: 'path',
selector: 'icon',
attributes: {
d: 'M -2 4 2 4 M 0 3 0 0 M -2 -1 1 -1 M -1 -4 1 -4',
fill: 'none',
stroke: '#FFFFFF',
'stroke-width': 2,
'pointer-events': 'none',
},
},
],
},
});
const infoButton = new InfoButton();
const toolsView = new joint.dia.ToolsView({
name: 'basic-tools',
tools: [removeButton, boundaryTool, infoButton],
});
Any help would be appreciated.

Saving layer from OpenLayer 3 Map created by user

I'm trying to correctly save an OpenLayer 3 Map layer created by a user in order to display it another map using geoJSON, but I'm having troubles with this.
On the client side I save the dinamic layer in this function:
function addInteractions() {
draw = new ol.interaction.Draw({
source: source,
type: typeSelect.value
});
draw.on("drawend", function(e) {
var f = e.feature;
features.push(f);
geoJson = format.writeFeatures(features);
console.log(geoJson);
document.getElementById('js-textarea').value = geoJson;
});
map.addInteraction(draw);
snap = new ol.interaction.Snap({source: source});
map.addInteraction(snap);
}
Then the geoJSON object is saved into a .json file, but when I try to display it, it doesn't appear on the map.
Here his my display function:
var geoDataUrl = '/data/' + '{{percorso._id}}' + '.json';
var vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
url: geoDataUrl,
format: new ol.format.GeoJSON()
}),
style: new ol.style.Style({
fill: new ol.style.Fill({
color: 'rgba(255, 255, 255, 0.2)'
}),
stroke: new ol.style.Stroke({
color: '#ffcc33',
width: 2
}),
image: new ol.style.Circle({
radius: 7,
fill: new ol.style.Fill({
color: '#ffcc33'
})
})
})
});
var raster = new ol.layer.Tile({
source: new ol.source.OSM()
});
var map = new ol.Map({
layers: [raster, vectorLayer],
target: 'map',
view: new ol.View({
center: {{#if percorso.mapCenter}}[{{percorso.mapCenter}}] {{else}} ol.proj.transform([9.688053, 45.362760], 'EPSG:4326', 'EPSG:3857'){{/if}},
zoom: {{#if percorso.zoomLevel}}{{percorso.zoomLevel}} {{else}} 13{{/if}}
})
});
I also tested the display function with other layers (for example the provided one on the OpenLayer examples website ) and it works fine
On the server side I save the geoJSONobject with this function, where oggetto_mappa is the dinamic geoJSON object:
var jsonMappa = JSON.stringify(eval("(" + oggetto_mappa + ")"));
require("fs").writeFile("./public/data/" + id_perc + ".json", jsonMappa, 'utf8', function(f_err) {
if(f_err)
console.log(f_err);
});
For refernce this is what my function saves onto the .json file:
{
"type":"FeatureCollection",
"features":[
{
"type":"Feature",
"id" : "aa",
"geometry":
{
"type":"LineString",
"coordinates":[
[1073328.751180445,5680150.227413875],
[1077857.6451063417,5682481.556776573],
[1070385.9255914658,5679156.546046168],
[1076825.7452244917,5680226.66444216],
[1073328.751180445,5680169.336670946]
]
},
"properties":null
},
{
"type":"Feature",
"id" : "ab",
"geometry":
{
"type":"LineString",
"coordinates":[
[1073328.751180445,5680169.336670946],
[1071628.0273010998,5677130.96479661]
]
},
"properties":null}
]
}
To get things working, replace
geoJson = format.writeFeatures(features)
with
geoJson = format.writeFeatures(features, {featureProjection: 'EPSG:3857'})
You may wonder why?
When you draw in OpenLayers, you are drawing in the projection of the map (the default is EPSG:3857) whereas when you consume a GeoJSON the expected projection is EPSG:4326.
See the API documentation from ol.format.GeoJSON writeFeatures to understand better
Some additional informations:
when you consume the GeoJSON from your drawing as the coordinates are not in decimal degrees (EPSG:4326) but in meters (EPSG:3857)
the order of magnitude for coordinates is different (millions for EPSG:3857 and less than some hundred for EPSG:4326) without accounting for the positive/negative coordinates

Restrict qtip2 inside a container

How to keep all the qtips inside a container (I have already tried position.container, position.viewport and position.adjust.method) without any luck, my best guess is that I am not using them correctly.
Update:1 I have created a sample app with more details on below url
http://secure.chiwater.com/CodeSample/Home/Qtip
Update:2 I have created jsfiddle link too. http://jsfiddle.net/Lde45mmv/2/
Please refer below screen shot for layout details.
I am calling the area shown between two lines as $container in my js code.
So far I have tried tweaking viewport, adjust method but nothing helped. I am hoping this is possible and I would greatly appreciate any help.
Below is my javascript code which creates qtip2.
//Now create tooltip for each of this Comment number
$('#cn_' + num).qtip({
id: contentElementID,
content: {
text: .....
var $control = $('<div class="qtip-parent">' +
' <div class="qtip-comment-contents">......</div>' +
' <div class="clearfix"></div>' +
' <div class="qtip-footer"><span class="qtip-commenter">...</span><span class="pull-right">...</span></div>' +
'</div>'
);
return $control;
},
button: false
},
show: 'click',
hide: {
fixed: true,
event: 'unfocus'
},
position: {
my: 'top right',
at: 'bottom right',
target: $('#cn_' + num),
container: $container,
//viewport: true,
adjust: { method: 'shift none' }
},
style: {
tip: {
corner: true,
mimic: 'center',
width: 12,
height: 12,
border: true, // Detect border from tooltip style
//offset: 25
},
classes: 'qtip-comment'
},
events: {
show: function (event, api) {
...
},
hide: function (event, api) {
...
}
}
});
Example of jalopnik page which shows what I am looking for (FWIW jalopnik example doesn't use qtip2).
I don't think qtip API supports this functionality. I ended up re-positioning the tooltip on visible event.
I have updated the demo page and jsfiddle link below is code for doing this.
events: {
visible: function (event, api) {
var $qtipControl = $(event.target);
$qtipControl.css({ 'left': contentPosition.left + "px" });
var $qtipTipControl = $qtipControl.find(".qtip-tip");
var $target = api.get("position.target");
$qtipTipControl.css({ "right": 'auto' });
//I am using jquery.ui position
$qtipTipControl.position({
my: "center top",
at: "center bottom",
of: $target
});
}
}
Problem with this approach is that there is noticeable jump when I re-position the qTip. But in lack of any other option for time being I will settle with this.
The ideal approach would be to allow callback method thru position.adjust currently it only supports static values for x and y, if a method was allowed here it would make things much smoother.

Resources