Compare commits

...

6 Commits

Author SHA1 Message Date
Matthieu Baumann
9202375d2e [skip-ci] fix ci doc deploy 2024-07-02 19:11:24 +02:00
Matthieu Baumann
b77267709d update changelog 2024-07-02 19:09:09 +02:00
Matthieu Baumann
4d8ca68f8c set rust lib version 2024-07-02 19:07:11 +02:00
Matthieu Baumann
c63284fc12 doc fixes 2024-07-02 19:02:43 +02:00
Matthieu Baumann
630f4453cc fix context sub menu deploy for small screen 2024-07-02 19:02:40 +02:00
Matthieu Baumann
c80cba8ec8 Adapt Aladin lite display for small sized devices
In particular for iphones (320px wide). This use media queries (that will be documented) that hide some UI ele
ments if aladin lite is too small. Users still can override the css if they want.
2024-07-02 19:01:33 +02:00
16 changed files with 201 additions and 161 deletions

View File

@@ -43,7 +43,7 @@ jobs:
uses: actions/upload-pages-artifact@v3
with:
# Upload entire repository
path: './doc'
path: './docs'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

View File

@@ -2,6 +2,7 @@
## 3.4.2-beta
* [impr] Improve smartphone support by setting media queries + a better logic for deploying the contextual menu sub options.
* [impr] Improve `WCS` view export with 3rd euler rotation encoding: <https://github.com/cds-astro/aladin-lite/issues/170>. Still some cases are to be handled like: crval on the equator or cylindrical with a galactic frame rotation.
* [fixed] Change `RADECSYS` to `RADESYS` for `Aladin#getViewWCS` to follow fits standard deprecation
* [feat] Add new method `Aladin#getViewImageBuffer` to get the current view as a PNG buffer

View File

@@ -1,6 +1,7 @@
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width, height=device-height, maximum-scale=1.0, initial-scale=1.0, user-scalable=no">
</head>
<body>

View File

@@ -77,11 +77,7 @@
});
</script>
<style>
.aladin-stack-control {
position: absolute;
top: 10rem;
left: 10rem;
}
.myBox {
top: unset;

View File

@@ -1,7 +1,6 @@
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width, height=device-height, maximum-scale=1.0, initial-scale=1.0, user-scalable=no">
</head>
<body>

View File

@@ -12,7 +12,7 @@
import A from '../src/js/A.js';
let aladin;
A.init.then(() => {
aladin = A.aladin('#aladin-lite-div', {target: '00 00 00 +07 00 00', fov: 130, survey: 'P/Mellinger/color', showContextMenu: true});
aladin = A.aladin('#aladin-lite-div', {target: '00 00 00 +07 00 00', fov: 130, survey: 'P/Mellinger/color', showContextMenu: true, fullScreen: true});
var moc11 = A.MOCFromURL('http://skies.esac.esa.int/HST/NICMOS/Moc.fits', {color: '#84f', lineWidth: 3}, (moc) => {
// moc is ready
console.log(moc.contains(205.9019247, +2.4492764));

View File

@@ -3,7 +3,7 @@ name = "aladin-lite"
description = "Aladin Lite v3 introduces a new graphical engine written in Rust with the use of WebGL"
license = "BSD-3-Clause"
repository = "https://github.com/cds-astro/aladin-lite"
version = "3.4.1-beta"
version = "3.4.2-beta"
authors = [ "baumannmatthieu0@gmail.com", "matthieu.baumann@astro.unistra.fr",]
edition = "2018"

View File

@@ -11,7 +11,7 @@
There can be a more supported alternative here: https://caniuse.com/?search=grid-template-columns */
/*container-type: inline-size;*/
font-size: 1rem;
font-size: 0.9rem;
}
.aladin-imageCanvas {
@@ -58,7 +58,6 @@
.aladin-measurement-div {
font-family: monospace;
font-size: 0.8rem;
display: block;
@@ -132,7 +131,7 @@
overflow-y: auto;
overflow-x: hidden;
/*font-family: monospace;*/
font-size: 11px;
color: #000;
}
.aladin-marker-measurement table {
@@ -205,8 +204,8 @@
border-radius: 2px;
position: absolute;
max-width: 15em;
font-size: inherit;
font-size: 0.8rem;
font-family: monospace;
background: #fff;
@@ -234,7 +233,7 @@ canvas {
}
.aladin-box-title {
font-size: 16px;
font-size: 1.0rem;
/*font-family: Verdana, Geneva, Tahoma, sans-serif;*/
line-height: 1.5em;
font-weight: bold;
@@ -256,7 +255,7 @@ canvas {
border: 1px solid #AEAEAE!important;
border-radius: 3px;
font-size: 13px!important;
font-size: 1rem;
background: #fff!important;
margin-right: 0.2em!important;
@@ -277,7 +276,7 @@ canvas {
border: 1px solid #AEAEAE;
border-radius: 3px;
background: #fff;
font-size: 15px;
font-size: 1.0rem;
font-weight: bold;
line-height: 0px;
padding: 8px 2px;
@@ -313,7 +312,8 @@ canvas {
margin: 0;
padding: 0.2rem;
font-size: 1rem;
font-size: inherit;
font-weight: normal;
text-align: center;
white-space: nowrap;
@@ -418,7 +418,6 @@ canvas {
.aladin-input-text.search {
background-image:none;
text-indent: 0rem;
font-size: 1rem;
line-height: 1.2rem;
}
@@ -541,7 +540,6 @@ canvas {
.aladin-window {
/*font-family: Verdana, Geneva, Tahoma, sans-serif;*/
font-size: 13px;
background: white;
border: 1px solid #bbb;
border-radius: 2px;
@@ -560,7 +558,6 @@ canvas {
.aladin-popup {
/*font-family: Verdana, Geneva, Tahoma, sans-serif;*/
font-size: 13px;
background: white;
border: 1px solid #bbb;
border-radius: 2px;
@@ -637,8 +634,6 @@ canvas {
scrollbar-width: none;
max-width: 20rem;
font-size: 1rem;
}
.aladin-sp-title a {
@@ -646,14 +641,9 @@ canvas {
color: #317d8d;
}
.aladin-sp-content {
font-size: 1rem;
}
.aladin-sp-content a {
text-decoration: none;
color: #478ade;
font-size: 11px;
}
.aladin-cuts {
@@ -704,8 +694,6 @@ canvas {
margin: 0;
padding: 0;
box-shadow: 0 0 8px rgba(0,0,0,0.2);
font-size: 0.9rem;
/*font-family: Verdana, Geneva, Tahoma, sans-serif;*/
border-radius: 3px;
@@ -754,12 +742,22 @@ canvas {
margin-left: 2px;
}
.aladin-context-menu-item:hover > .aladin-context-sub-menu {
display: block;
}
.aladin-context-menu-item:hover {
/* This is for the tooltip to appear outside the item, i.e. over the sibling item */
.aladin-context-menu-item:hover {
color: greenyellow;
}
.aladin-context-menu-item:not(hover) {
color: white;
}
.aladin-context-menu-item .aladin-context-sub-menu {
display: none;
}
.aladin-context-menu .aladin-context-menu-item span {
display: block;
white-space: nowrap;
@@ -776,20 +774,31 @@ canvas {
display: block;
}
*/
.aladin-context-menu.left .aladin-context-sub-menu {
.aladin-context-menu .aladin-context-sub-menu.left {
left: 0;
transform: translateX(-100%);
}
.aladin-context-menu.top .aladin-context-sub-menu {
.aladin-context-menu .aladin-context-sub-menu.right {
right: 0;
}
.aladin-context-menu .aladin-context-sub-menu.bottom {
top: 100%;
left: 0;
}
.aladin-context-menu .aladin-context-sub-menu.top {
top: 0;
left: 0;
transform: translateY(-100%);
}
.aladin-context-menu.left.top .aladin-context-sub-menu {
.aladin-context-menu .aladin-context-sub-menu.left.top {
transform: translate(-100%, -100%);
}
.aladin-reticle {
position: absolute;
@@ -816,7 +825,6 @@ canvas {
padding: 0.3rem;
border-radius: 5px;
font-family: monospace;
font-size: 1rem;
box-sizing: border-box;
}
@@ -835,14 +843,14 @@ canvas {
/* Reset */
border: 1px solid white;
outline: 0;
font: inherit;
/*font: inherit;*/
/* Personalize */
padding: 2px;
padding: 0.2em;
font-size: inherit;
border-radius: 0.25em;
box-shadow: 0 0 1em 0 rgba(0, 0, 0, 0.2);
cursor: pointer;
font-family: monospace;
font-size: 1rem;
width: 100%;
/* <option> colors */
/* Remove focus outline */
@@ -989,7 +997,6 @@ canvas {
position: absolute;
/*font-family: Verdana, Geneva, Tahoma, sans-serif;*/
font-size: 0.9rem;
transition-delay: 100ms;
}
@@ -1097,10 +1104,9 @@ canvas {
color: white;
font-size: 1rem;
border-radius: 5px;
height: 1.7rem;
width: 5rem;
width: 4.5rem;
}
/*
@@ -1125,18 +1131,29 @@ canvas {
.aladin-location {
position: absolute;
top: 0.2rem;
left: 5.4rem;
left: 5.0rem;
font-family: monospace;
color: white;
font-size: 1rem;
border-radius: 5px;
height: 1.7rem;
}
.aladin-input-text {
font-size: inherit;
}
.aladin-location .aladin-input-text {
width: 15rem;
width: 13.5rem;
height: 100%;
border-radius: 0 0.4rem 0.4rem 0;
}
.aladin-location .aladin-location-copy {
margin-right: -0.2rem;
border-radius: 0.4rem 0px 0px 0.4rem;
border-right: none;
}
.aladin-fov {
@@ -1148,7 +1165,6 @@ canvas {
font-family: monospace;
font-size: 1rem;
border-radius: 5px;
line-height: 1.7rem;
}
@@ -1224,6 +1240,35 @@ canvas {
}
/* Media query */
@media screen and (max-width:480px) {
/* smartphones, Android phones, landscape iPhone */
.aladin-location > .aladin-btn {
display: none;
}
.aladin-location > .aladin-input-text {
border-radius: 0.4rem;
}
.aladin-projection-control {
display: none;
}
.aladin-location .aladin-location-copy {
display: none;
}
}
@media screen and (max-width:370px) {
/* smartphones, Android phones, landscape iPhone */
.aladin-location {
left: 0.2rem;
}
.aladin-cooFrame {
display: none;
}
}
/*@media screen and (max-width: 31rem) {
.aladin-projection-control {
display: none;

View File

@@ -452,28 +452,6 @@ A.MOCFromPolygon= function (polygon, options, successCallback, errorCallback) {
return moc;
};
/**
* Represents options for configuring a catalog.
*
* @typedef {Object} CatalogOptions
* @property {string} url - The URL of the catalog.
* @property {string} [name="catalog"] - The name of the catalog.
* @property {string} [color] - The color associated with the catalog.
* @property {number} [sourceSize=8] - The size of the sources in the catalog.
* @property {number} [markerSize=12] - The size of the markers associated with sources.
* @property {string} [shape="square"] - The shape of the sources (e.g., "square", "circle", "rhomb", "triangle", "cross").
* @property {number} [limit] - The maximum number of sources to display.
* @property {function} [onClick] - The callback function to execute on a source click.
* @property {boolean} [readOnly=false] - Whether the catalog is read-only.
* @property {string} [raField] - The ID or name of the field holding Right Ascension (RA).
* @property {string} [decField] - The ID or name of the field holding Declination (dec).
* @property {function} [filter] - The filtering function for sources. Returns a boolean
* @property {boolean} [displayLabel=false] - Whether to display labels for sources.
* @property {string} [labelColumn] - The name of the column to be used for the label.
* @property {string} [labelColor] - The color of the source labels.
* @property {string} [labelFont="10px sans-serif"] - The font for the source labels.
*/
/**
* Represents a catalog with configurable options for display and interaction.
*

View File

@@ -40,34 +40,35 @@ import { Circle } from "./shapes/Circle.js";
import { Footprint } from "./Footprint.js";
/**
* Represents options for configuring a catalog.
*
* @namespace
* @typedef {Object} Catalog
* @typedef {Object} CatalogOptions
* @property {string} url - The URL of the catalog.
* @property {string} [name="catalog"] - The name of the catalog.
* @property {string} [color] - The color associated with the catalog.
* @property {number} [sourceSize=8] - The size of the sources in the catalog.
* @property {string|function|Image|HTMLCanvasElement} [shape="square"] - The shape of the sources (can be, "square", "circle", "plus", "cross", "rhomb", "triangle").
* @property {number} [limit] - The maximum number of sources to display.
* @property {string|Function} [onClick] - Whether the source data appears as a table row or a in popup. Can be 'showTable' string, 'showPopup' string or a custom user defined function that handles the click.
* @property {boolean} [readOnly=false] - Whether the catalog is read-only.
* @property {string} [raField] - The ID or name of the field holding Right Ascension (RA).
* @property {string} [decField] - The ID or name of the field holding Declination (dec).
* @property {function} [filter] - The filtering function for sources.
* @property {string} [selectionColor="#00ff00"] - The color to apply to selected sources in the catalog.
* @property {string} [hoverColor=color] - The color to apply to sources in the catalog when they are hovered.
* @property {boolean} [displayLabel=false] - Whether to display labels for sources.
* @property {string} [labelColumn] - The name of the column to be used for the label.
* @property {string} [labelColor=color] - The color of the source labels.
* @property {string} [labelFont="10px sans-serif"] - The font for the source labels.
*/
export let Catalog = (function () {
/**
* Represents a catalog with configurable options for display and interaction.
*
* @class
* @constructs Catalog
* @param {Object} options - Configuration options for the catalog.
* @param {string} options.url - The URL of the catalog.
* @param {string} [options.name="catalog"] - The name of the catalog.
* @param {string} [options.color] - The color associated with the catalog.
* @param {number} [options.sourceSize=8] - The size of the sources in the catalog.
* @param {string|function|Image|HTMLCanvasElement} [options.shape="square"] - The shape of the sources (can be, "square", "circle", "plus", "cross", "rhomb", "triangle").
* @param {number} [options.limit] - The maximum number of sources to display.
* @param {string|Function} [options.onClick] - Whether the source data appears as a table row or a in popup. Can be 'showTable' string, 'showPopup' string or a custom user defined function that handles the click.
* @param {boolean} [options.readOnly=false] - Whether the catalog is read-only.
* @param {string} [options.raField] - The ID or name of the field holding Right Ascension (RA).
* @param {string} [options.decField] - The ID or name of the field holding Declination (dec).
* @param {function} [options.filter] - The filtering function for sources.
* @param {string} [options.selectionColor] - The color to apply to selected sources in the catalog.
* @param {string} [options.hoverColor] - The color to apply to sources in the catalog when they are hovered.
* @param {boolean} [options.displayLabel=false] - Whether to display labels for sources.
* @param {string} [options.labelColumn] - The name of the column to be used for the label.
* @param {string} [options.labelColor] - The color of the source labels.
* @param {string} [options.labelFont="10px sans-serif"] - The font for the source labels.
* @param {CatalogOptions} options - Configuration options for the catalog.
*
* @example
* const catalogOptions = {

View File

@@ -34,6 +34,7 @@ import { CatalogQueryBox } from "./gui/Box/CatalogQueryBox.js";
import cameraIconUrl from '../../assets/icons/camera.svg'
import targetIconUrl from '../../assets/icons/target.svg';
import uploadIconUrl from '../../assets/icons/upload.svg';
import selectIconUrl from '../../assets/icons/select.svg';
export let DefaultActionsForContextMenu = (function () {
@@ -164,7 +165,7 @@ export let DefaultActionsForContextMenu = (function () {
files.forEach(file => {
const url = URL.createObjectURL(file);
let moc = A.MOCFromURL(url, { name: file.name, edge: true });
let moc = A.MOCFromURL(url, { name: file.name });
a.addMOC(moc);
});
};
@@ -190,6 +191,30 @@ export let DefaultActionsForContextMenu = (function () {
}
]
},
{
label: {
icon: {
monochrome: true,
url: selectIconUrl,
size: 'small',
},
content: "Select sources"
},
subMenu: [
{
label: 'Circular',
action(o) {
a.select('circle', selectObjects)
}
},
{
label: 'Rectangular',
action(o) {
a.select('rect', selectObjects)
}
}
]
},
{
label: {
icon: {
@@ -219,23 +244,6 @@ export let DefaultActionsForContextMenu = (function () {
window.open(hips2fitsUrl, '_blank');
}
},
{
label: "Select sources",
subMenu: [
{
label: 'Circular',
action(o) {
a.select('circle', selectObjects)
}
},
{
label: 'Rectangular',
action(o) {
a.select('rect', selectObjects)
}
}
]
},
]
}

View File

@@ -539,7 +539,17 @@ export class OverlayStackBox extends Box {
self.hipsSelectorBox._show({
position: self.position,
});*/
self.aladin.addNewImageLayer();
self.aladin.addNewImageLayer(
A.imageHiPS('CDS/P/DSS2/color', {
errorCallback: (e) => {
aladin.addStatusBarMessage({
duration: 2000,
type: 'info',
message: 'DSS2 colored HiPS could not plot',
})
}
})
);
},
},
{

View File

@@ -107,9 +107,6 @@ export class Location extends DOMElement {
}
},
value: parseCoo(),
cssStyle: {
borderRadius: "0px 5px 5px 0px",
}
});
let copyBtn = new ActionButton({
@@ -122,15 +119,8 @@ export class Location extends DOMElement {
action(e) {
self.copyCoordinatesToClipboard()
},
cssStyle: {
height: '1.4rem',
width: '1.4rem',
paddingRight: '0.2rem',
borderRadius: "5px 0px 0px 5px",
borderRight: 'none',
}
})
copyBtn.element().style.marginRight = 0;
copyBtn.el.classList.add("aladin-location-copy");
let el = Layout.horizontal({
layout: [

View File

@@ -91,7 +91,7 @@ export class ContextMenu extends DOMElement {
ContextMenu._menus.push(this);
}
static lastHoveredItem;
//static lastHoveredItem;
_attachOption(target, opt, e, cssStyle) {
let item = document.createElement('li');
@@ -202,7 +202,8 @@ export class ContextMenu extends DOMElement {
}
if (opt.subMenu && opt.subMenu.length > 0) {
item.appendChild(new Icon({url: nextIconSvg, size: 'small', monochrome: true}).element());
let iconElt = new Icon({url: nextIconSvg, size: 'small', monochrome: true}).element();
item.appendChild(iconElt);
item.style.display = 'flex';
item.style.alignItems = 'center';
item.style.justifyContent = 'space-between';
@@ -218,19 +219,27 @@ export class ContextMenu extends DOMElement {
}
if (opt.subMenu) {
// User
item.addEventListener('click', e => {
e.stopPropagation();
if (item.parentNode) {
let subMenus = item.parentNode.querySelectorAll(".aladin-context-sub-menu")
for (let subMenuChild of subMenus) {
subMenuChild.style.display = 'none';
}
/* Add the ability to deploy the menu/sub-menus for touch screen devices */
if (Utils.hasTouchScreen()) {
let subMenu = item.querySelector(".aladin-context-sub-menu")
let subMenuIsShown = subMenu.style.display === "block";
if (item.parentNode) {
let subMenus = item.parentNode.querySelectorAll(".aladin-context-sub-menu")
for (let subMenuChild of subMenus) {
subMenuChild.style.display = 'none';
}
}
if (!subMenuIsShown) {
subMenu.style.setProperty('display', 'block');
}
}
item.querySelector(".aladin-context-sub-menu")
.style.display = 'block';
if (opt.action && (!opt.disabled || opt.disabled === false)) {
opt.action(e, self);
}
@@ -278,7 +287,7 @@ export class ContextMenu extends DOMElement {
opt.hover(e, item);
}
if (ContextMenu.lastHoveredItem) {
/*if (ContextMenu.lastHoveredItem) {
let parent = ContextMenu.lastHoveredItem.parentNode;
if (parent && (areSiblings(parent, item) || item.contains(parent) || item === parent)) {
ContextMenu.lastHoveredItem.style.display = 'none';
@@ -289,7 +298,7 @@ export class ContextMenu extends DOMElement {
if (subMenu) {
subMenu.style.display = 'block';
ContextMenu.lastHoveredItem = subMenu;
}
}*/
})
item.addEventListener('mouseout', e => {
@@ -308,44 +317,43 @@ export class ContextMenu extends DOMElement {
target.appendChild(item);
}
_subMenuDisplay(parent) {
const {offsetWidth, offsetHeight} = this.aladin.aladinDiv;
const aladinRect = this.aladin.aladinDiv.getBoundingClientRect();
_subMenuDisplay(parent, child) {
parent.style.display = "block";
child.style.display = "block";
if (child.classList.contains('aladin-context-sub-menu')) {
const aladinRect = this.aladin.aladinDiv.getBoundingClientRect();
let leftDir = 0;
let topDir = 0;
let o = parent.getBoundingClientRect();
let c = child.getBoundingClientRect();
for (let item of parent.children) {
item.style.display = "block";
child.classList.remove('left', 'right', 'top', 'bottom');
let r = item.getBoundingClientRect();
if (r.x - aladinRect.left <= aladinRect.right - (r.x + r.width)) {
leftDir -= 1;
// First check if there is place towards the right, which is the desired behaviour
if (aladinRect.right - (o.x + o.width) >= c.width) {
// do nothing as it is by default considering this case
} else if (o.x - aladinRect.left >= c.width) {
child.classList.add('left');
} else if (aladinRect.bottom - (o.y + o.height) >= c.height) {
child.classList.add('bottom');
} else {
leftDir += 1;
child.classList.add('top');
}
if (r.y - aladinRect.top <= offsetHeight / 2.0) {
/*if (r.y - aladinRect.top <= offsetHeight / 2.0) {
topDir -= 1;
} else {
topDir += 1;
}
item.style.display = "";
}*/
}
if (leftDir > 0) {
this.el.classList.add('left');
} else {
this.el.classList.add('right');
for (let grandChild of child.children) {
this._subMenuDisplay(child, grandChild);
}
if (topDir > 0) {
this.el.classList.add('top');
} else {
this.el.classList.add('bottom');
}
child.style.display = "";
parent.style.display = "";
}
show(options) {
@@ -366,14 +374,14 @@ export class ContextMenu extends DOMElement {
let mouseCoords = options && options.e && Utils.relMouseCoords(options.e)
// Set position
const position =
options && options.position ||
{left: mouseCoords.x, top: mouseCoords.y};
options && options.position ||
{left: mouseCoords.x, top: mouseCoords.y};
this.setPosition({...position, aladin: this.aladin})
this.el.classList.remove('left')
this.el.classList.remove('top')
this._subMenuDisplay(this.el)
for (let childEl of this.el.children) {
this._subMenuDisplay(this.el, childEl);
}
super._show()
}

3
tutorials/Examples.md Normal file
View File

@@ -0,0 +1,3 @@
# JS API
A list of examples illustrating the API is available at this [link](https://aladin.cds.unistra.fr/AladinLite/doc/API/examples/)

View File

@@ -1,4 +1,4 @@
# User guide
# Customization
This is a guide for users wanting to customize the apparence of Aladin Lite user interface.