mirror of
https://github.com/cds-astro/aladin-lite.git
synced 2025-12-12 07:40:26 -08:00
restore zooming out feature
This commit is contained in:
committed by
bmatthieu3
parent
278bba0cb3
commit
9b098fdcdd
@@ -10,8 +10,9 @@
|
||||
import A from '../src/js/A.js';
|
||||
let aladin;
|
||||
A.init.then(() => {
|
||||
aladin = A.aladin('#aladin-lite-div', {showSettingsControl: true, survey: "P/PanSTARRS/DR1/color-z-zg-g", showReticle: false, projection: "AIT", cooFrame: 'icrs', target: "stephan's quintet", fov: 1000, showGotoControl: false, showFrame: false, fullScreen: true, showLayersControl: true, showCooGridControl: false});
|
||||
aladin.showHealpixGrid(true);
|
||||
let startFov = 1000;
|
||||
aladin = A.aladin('#aladin-lite-div', {showSettingsControl: true, survey: "P/PanSTARRS/DR1/color-z-zg-g", showReticle: false, projection: "AIT", cooFrame: 'icrs', target: "stephan's quintet", fov: startFov, showGotoControl: false, showFrame: false, fullScreen: true, showLayersControl: true, showCooGridControl: false});
|
||||
|
||||
const chft = aladin.createImageSurvey('CFHT', "CFHT deep view of NGC7331 and Stephan's quintet u+g+r", "https://cds.unistra.fr/~derriere/PR_HiPS/2022_Duc/", null, null, {imgFormat: 'png'});
|
||||
const nircamJWST = aladin.createImageSurvey('Nircam', "Stephans Quintet NIRCam+MIRI", "http://alasky.cds.unistra.fr/JWST/CDS_P_JWST_Stephans-Quintet_NIRCam+MIRI/", null, null, {imgFormat: 'png', colormap: "viridis"});
|
||||
|
||||
@@ -21,7 +22,7 @@
|
||||
aladin.getOverlayImageLayer("CFHT").toggle();
|
||||
aladin.getOverlayImageLayer("Nircam").toggle();
|
||||
|
||||
let fov = 360;
|
||||
let fov = startFov;
|
||||
let rotation = 0;
|
||||
|
||||
setInterval(function zoom() {
|
||||
|
||||
@@ -902,12 +902,12 @@ impl App {
|
||||
//let fbo_view = &self.fbo_view;
|
||||
//catalogs.draw(&gl, shaders, camera, colormaps, fbo_view)?;
|
||||
//catalogs.draw(&gl, shaders, camera, colormaps, None, self.projection)?;
|
||||
gl.blend_func_separate(
|
||||
/*gl.blend_func_separate(
|
||||
WebGl2RenderingContext::SRC_ALPHA,
|
||||
WebGl2RenderingContext::ONE,
|
||||
WebGl2RenderingContext::ONE,
|
||||
WebGl2RenderingContext::ONE,
|
||||
);
|
||||
);*/
|
||||
moc.draw(camera, projection, shaders)?;
|
||||
|
||||
gl.blend_func_separate(
|
||||
@@ -1399,7 +1399,7 @@ impl App {
|
||||
}
|
||||
|
||||
pub(crate) fn set_grid_cfg(&mut self, cfg: GridCfg) -> Result<(), JsValue> {
|
||||
self.grid.set_cfg(cfg, &self.camera, &self.projection)?;
|
||||
self.grid.set_cfg(cfg)?;
|
||||
self.request_redraw = true;
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -337,7 +337,7 @@ impl CameraViewPort {
|
||||
self.last_user_action
|
||||
};
|
||||
|
||||
let _can_unzoom_more = match proj {
|
||||
let can_unzoom_more = match proj {
|
||||
ProjectionType::Tan(_)
|
||||
| ProjectionType::Mer(_)
|
||||
//| ProjectionType::Air(_)
|
||||
@@ -351,32 +351,45 @@ impl CameraViewPort {
|
||||
|
||||
let aperture_start: Angle<f64> = ArcDeg(proj.aperture_start()).into();
|
||||
|
||||
self.aperture = aperture.min(aperture_start);
|
||||
// Compute the new clip zoom factor
|
||||
let a = aperture.abs();
|
||||
|
||||
let v0 = math::lonlat::radec_to_xyzw(-a / 2.0, Angle(0.0));
|
||||
let v1 = math::lonlat::radec_to_xyzw(a / 2.0, Angle(0.0));
|
||||
|
||||
// Vertex in the WCS of the FOV
|
||||
self.clip_zoom_factor = if self.width < self.height {
|
||||
if let (Some(p0), Some(p1)) =
|
||||
(proj.world_to_clip_space(&v0), proj.world_to_clip_space(&v1))
|
||||
{
|
||||
(0.5 * (p1.x - p0.x).abs()).min(1.0)
|
||||
self.clip_zoom_factor = if aperture > aperture_start {
|
||||
//al_core::log(&format!("a: {:?}, as: {:?}", aperture, aperture_start));
|
||||
if can_unzoom_more {
|
||||
aperture.0 / aperture_start.0
|
||||
} else {
|
||||
1.0
|
||||
}
|
||||
} else {
|
||||
if let (Some(p0), Some(p1)) =
|
||||
(proj.world_to_clip_space(&v0), proj.world_to_clip_space(&v1))
|
||||
{
|
||||
(0.5 * (p1.x - p0.x).abs()).min(1.0)
|
||||
// Compute the new clip zoom factor
|
||||
let a = aperture.abs();
|
||||
|
||||
let v0 = math::lonlat::radec_to_xyzw(-a / 2.0, Angle(0.0));
|
||||
let v1 = math::lonlat::radec_to_xyzw(a / 2.0, Angle(0.0));
|
||||
|
||||
// Vertex in the WCS of the FOV
|
||||
if self.width < self.height {
|
||||
if let (Some(p0), Some(p1)) =
|
||||
(proj.world_to_clip_space(&v0), proj.world_to_clip_space(&v1))
|
||||
{
|
||||
(0.5 * (p1.x - p0.x).abs()).min(1.0)
|
||||
} else {
|
||||
1.0
|
||||
}
|
||||
} else {
|
||||
1.0
|
||||
if let (Some(p0), Some(p1)) =
|
||||
(proj.world_to_clip_space(&v0), proj.world_to_clip_space(&v1))
|
||||
{
|
||||
(0.5 * (p1.x - p0.x).abs()).min(1.0)
|
||||
} else {
|
||||
1.0
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
self.aperture = aperture.min(aperture_start);
|
||||
//self.aperture = aperture;
|
||||
|
||||
//al_core::log(&format!("zoom factor {:?}", self.clip_zoom_factor));
|
||||
|
||||
//console_log(&format!("clip factor {:?}", self.aperture));
|
||||
|
||||
// Project this vertex into the screen
|
||||
|
||||
@@ -505,11 +505,9 @@ impl WebClient {
|
||||
/// * `fov` - The field of view in degrees
|
||||
#[wasm_bindgen(js_name = setFieldOfView)]
|
||||
pub fn set_fov(&mut self, fov: f64) -> Result<(), JsValue> {
|
||||
//let fov = fov as f32;
|
||||
let fov = ArcDeg(fov).into();
|
||||
|
||||
self.app.set_fov(fov);
|
||||
//self.projection.set_fov(&mut self.app, ArcDeg(fov).into());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -114,12 +114,7 @@ impl ProjetedGrid {
|
||||
Ok(grid)
|
||||
}
|
||||
|
||||
pub fn set_cfg(
|
||||
&mut self,
|
||||
new_cfg: GridCfg,
|
||||
_camera: &CameraViewPort,
|
||||
_projection: &ProjectionType,
|
||||
) -> Result<(), JsValue> {
|
||||
pub fn set_cfg(&mut self, new_cfg: GridCfg) -> Result<(), JsValue> {
|
||||
let GridCfg {
|
||||
color,
|
||||
opacity,
|
||||
@@ -165,10 +160,6 @@ impl ProjetedGrid {
|
||||
|
||||
if let Some(enabled) = enabled {
|
||||
self.enabled = enabled;
|
||||
|
||||
/*if !self.enabled {
|
||||
self.text_renderer.clear_text_canvas();
|
||||
}*/
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -229,12 +229,10 @@ export let DefaultActionsForContextMenu = (function () {
|
||||
},
|
||||
{
|
||||
label: "HiPS2FITS cutout", action(o) {
|
||||
let hips2fitsUrl = 'https://alasky.cds.unistra.fr/hips-image-services/hips2fits#';
|
||||
let radec = a.getRaDec();
|
||||
let fov = Math.max.apply(null, a.getFov());
|
||||
let hips2fitsUrl = 'https://alasky.cds.unistra.fr/hips-image-services/hips2fits?';
|
||||
let hipsId = a.getBaseImageLayer().id;
|
||||
let proj = a.getProjectionName();
|
||||
hips2fitsUrl += 'ra=' + radec[0] + '&dec=' + radec[1] + '&fov=' + fov + '&projection=' + proj + '&hips=' + encodeURIComponent(hipsId);
|
||||
let wcs = JSON.stringify(a.getViewWCS());
|
||||
hips2fitsUrl += 'wcs=' + encodeURIComponent(wcs) + '&hips=' + encodeURIComponent(hipsId);
|
||||
window.open(hips2fitsUrl, '_blank');
|
||||
}
|
||||
},
|
||||
|
||||
@@ -31,9 +31,9 @@ export let ProjectionEnum = {
|
||||
// Zenithal
|
||||
TAN: {id: 1, fov: 150, label: "Tangential"}, /* Gnomonic projection */
|
||||
STG: {id: 2, fov: 240, label: "Stereographic"}, /* Stereographic projection */
|
||||
SIN: {id: 3, fov: 180, label: "Spheric"}, /* Orthographic */
|
||||
SIN: {id: 3, fov: 1000, label: "Spheric"}, /* Orthographic */
|
||||
// TODO: fix why the projection disappears at fov = 360.0
|
||||
ZEA: {id: 4, fov: 359.999, label: "Zenital equal-area"}, /* Equal-area */
|
||||
ZEA: {id: 4, fov: 1000, label: "Zenital equal-area"}, /* Equal-area */
|
||||
//FEYE: {id: 5, fov: 190, label: "fish eye"},
|
||||
//AIR: {id: 6, fov: 360, label: "airy"},
|
||||
//AZP: {fov: 180},
|
||||
@@ -45,10 +45,10 @@ export let ProjectionEnum = {
|
||||
//CEA: {id: 11, fov: 360, label: "cylindrical equal area"},
|
||||
//CYP: {id: 12, fov: 360, label: "cylindrical perspective"},
|
||||
// Pseudo-cylindrical
|
||||
AIT: {id: 13, fov: 360, label: "Hammer-Aïtoff"},
|
||||
AIT: {id: 13, fov: 1000, label: "Hammer-Aïtoff"},
|
||||
//PAR: {id: 14, fov: 360, label: "parabolic"},
|
||||
//SFL: {id: 15, fov: 360, label: "sanson-flamsteed"},
|
||||
MOL: {id: 16, fov: 360, label: "Mollweide"},
|
||||
MOL: {id: 16, fov: 1000, label: "Mollweide"},
|
||||
// Conic
|
||||
//COD: {id: 17, fov: 360, label: "conic equidistant"},
|
||||
// Hybrid
|
||||
|
||||
@@ -71,6 +71,9 @@ export let View = (function () {
|
||||
// MOCs
|
||||
this.mocs = [];
|
||||
|
||||
this.outsideFov = 0;
|
||||
this.outside = false;
|
||||
|
||||
self.redrawClbk = this.redraw.bind(this);
|
||||
// Init the WebGL context
|
||||
// At this point, the view has been created so the image canvas too
|
||||
@@ -195,8 +198,7 @@ export let View = (function () {
|
||||
this.setProjection(projName)
|
||||
|
||||
// Then set the zoom properly once the projection is defined
|
||||
this.wasm.setFieldOfView(initialFov);
|
||||
this.updateZoomState();
|
||||
this.setZoom(initialFov)
|
||||
|
||||
// Target position settings
|
||||
this.viewCenter = { lon, lat }; // position of center of view
|
||||
@@ -398,6 +400,7 @@ export let View = (function () {
|
||||
this.imageCtx.canvas.style.width = this.width + "px";
|
||||
this.imageCtx.canvas.style.height = this.height + "px";
|
||||
this.wasm.resize(this.width, this.height);
|
||||
this.setZoom(this.fov)
|
||||
|
||||
pixelateCanvasContext(this.imageCtx, this.aladin.options.pixelateCanvas);
|
||||
|
||||
@@ -1130,23 +1133,15 @@ export let View = (function () {
|
||||
|
||||
// disable text selection on IE
|
||||
//Utils.on(view.aladinDiv, "selectstart", function () { return false; })
|
||||
var eventCount = 0;
|
||||
/*var eventCount = 0;
|
||||
var eventCountStart;
|
||||
var isTouchPad;
|
||||
let id;
|
||||
let id;*/
|
||||
|
||||
Utils.on(view.catalogCanvas, 'wheel', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
view.wheelTriggered = true;
|
||||
|
||||
clearTimeout(id);
|
||||
id = setTimeout(() => {
|
||||
view.wheelTriggered = false;
|
||||
view.zoom.stopAnimation();
|
||||
}, 100);
|
||||
|
||||
const xymouse = Utils.relMouseCoords(e);
|
||||
view.xy = xymouse
|
||||
ALEvent.CANVAS_EVENT.dispatchedTo(view.aladinDiv, {
|
||||
@@ -1178,7 +1173,7 @@ export let View = (function () {
|
||||
// First detect the device
|
||||
// See https://stackoverflow.com/questions/10744645/detect-touchpad-vs-mouse-in-javascript
|
||||
// for detecting the use of a touchpad
|
||||
view.isTouchPadDefined = isTouchPad || typeof isTouchPad !== "undefined";
|
||||
/*view.isTouchPadDefined = isTouchPad || typeof isTouchPad !== "undefined";
|
||||
if (!view.isTouchPadDefined) {
|
||||
if (eventCount === 0) {
|
||||
view.delta = 0;
|
||||
@@ -1195,28 +1190,23 @@ export let View = (function () {
|
||||
}
|
||||
view.isTouchPadDefined = true;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
// only ensure the touch pad test has been done before zooming
|
||||
if (!view.isTouchPadDefined) {
|
||||
/*if (!view.isTouchPadDefined) {
|
||||
return false;
|
||||
}
|
||||
}*/
|
||||
|
||||
// touch pad defined
|
||||
view.delta = e.deltaY || e.detail || (-e.wheelDelta);
|
||||
|
||||
if (isTouchPad) {
|
||||
//if (isTouchPad) {
|
||||
if (!view.throttledTouchPadZoom) {
|
||||
//let radec;
|
||||
view.throttledTouchPadZoom = () => {
|
||||
/*if (!view.zoom.isZooming && !view.wheelTriggered) {
|
||||
// start zooming detected
|
||||
radec = view.aladin.pix2world(view.xy.x, view.xy.y);
|
||||
}*/
|
||||
|
||||
const factor = 2.0;
|
||||
let newFov = view.delta > 0 ? view.fov * factor : view.fov / factor;
|
||||
|
||||
// inside case
|
||||
view.zoom.apply({
|
||||
stop: newFov,
|
||||
duration: 100
|
||||
@@ -1225,22 +1215,21 @@ export let View = (function () {
|
||||
}
|
||||
|
||||
view.throttledTouchPadZoom();
|
||||
} else {
|
||||
/*} else {
|
||||
if (!view.throttledMouseScrollZoom) {
|
||||
view.throttledMouseScrollZoom = Utils.throttle(() => {
|
||||
const factor = 5
|
||||
view.throttledMouseScrollZoom = () => {
|
||||
const factor = 2
|
||||
let newFov = view.delta > 0 ? view.fov * factor : view.fov / factor;
|
||||
// standard mouse wheel zooming
|
||||
|
||||
view.zoom.apply({
|
||||
stop: newFov,
|
||||
duration: 300
|
||||
duration: 100
|
||||
});
|
||||
}, 50);
|
||||
};
|
||||
}
|
||||
|
||||
view.throttledMouseScrollZoom()
|
||||
}
|
||||
}*/
|
||||
|
||||
return false;
|
||||
});
|
||||
@@ -1588,7 +1577,7 @@ export let View = (function () {
|
||||
}
|
||||
|
||||
this.wasm.setFieldOfView(fov);
|
||||
this.updateZoomState();
|
||||
this.updateZoomState(fov);
|
||||
};
|
||||
|
||||
View.prototype.increaseZoom = function () {
|
||||
@@ -1613,9 +1602,7 @@ export let View = (function () {
|
||||
this.gridCfg = {...this.gridCfg, ...options};
|
||||
this.wasm.setGridOptions(this.gridCfg);
|
||||
|
||||
if (!this.gridCfg.enabled) {
|
||||
this.mustClearCatalog = true;
|
||||
}
|
||||
this.mustClearCatalog = true;
|
||||
|
||||
ALEvent.COO_GRID_UPDATED.dispatchedTo(this.aladinDiv, this.gridCfg);
|
||||
|
||||
@@ -1626,12 +1613,24 @@ export let View = (function () {
|
||||
return this.gridCfg;
|
||||
}
|
||||
|
||||
View.prototype.updateZoomState = function () {
|
||||
View.prototype.updateZoomState = function (fov) {
|
||||
// Get the new zoom values from the backend
|
||||
let fov = this.wasm.getFieldOfView();
|
||||
const newFov = fov || this.wasm.getFieldOfView()
|
||||
|
||||
// Save it
|
||||
this.fov = fov;
|
||||
// Disable the coo grid labels if we are too unzoomed
|
||||
const maxFovGridLabels = 360;
|
||||
if (this.fov <= maxFovGridLabels && newFov > maxFovGridLabels) {
|
||||
let gridOptions = this.getGridOptions()
|
||||
if (gridOptions) {
|
||||
this.originalShowLabels = gridOptions.showLabels;
|
||||
this.aladin.setCooGrid({showLabels: false});
|
||||
}
|
||||
|
||||
} else if (this.fov > maxFovGridLabels && newFov <= maxFovGridLabels) {
|
||||
this.aladin.setCooGrid({showLabels:this.originalShowLabels});
|
||||
}
|
||||
|
||||
this.fov = newFov;
|
||||
this.computeNorder();
|
||||
|
||||
let fovX = this.fov;
|
||||
@@ -1942,7 +1941,8 @@ export let View = (function () {
|
||||
|
||||
// Change the projection here
|
||||
this.wasm.setProjection(projName);
|
||||
this.updateZoomState();
|
||||
let newProjFov = Math.min(this.fov, this.projection.fov);
|
||||
this.setZoom(newProjFov)
|
||||
|
||||
const projFn = this.aladin.callbacksByEventName['projectionChanged'];
|
||||
(typeof projFn === 'function') && projFn(projName);
|
||||
|
||||
@@ -43,8 +43,7 @@ import { requestAnimFrame } from "./libs/RequestAnimationFrame.js";
|
||||
return;
|
||||
|
||||
// clamp the zoom to the view params minFov and maxFov and the projection bounds
|
||||
finalZoom = Math.min(finalZoom, this.view.projection.fov);
|
||||
|
||||
//finalZoom = Math.min(finalZoom, this.view.projection.fov);
|
||||
// then clamp the fov between minFov and maxFov
|
||||
const minFoV = this.view.minFoV;
|
||||
const maxFoV = this.view.maxFoV;
|
||||
@@ -94,31 +93,31 @@ import { requestAnimFrame } from "./libs/RequestAnimationFrame.js";
|
||||
let self = this;
|
||||
// Recursive function to perform interpolation for each frame
|
||||
function interpolateFrame() {
|
||||
//fps = 1000 / self.dt;
|
||||
//totalFrames = interpolationDuration * fps; // Total number of frames
|
||||
self.x = ( performance.now() - self.startTime ) / interpolationDuration;
|
||||
// Calculate step size for each frame
|
||||
//stepSize = (desiredZoom - currentZoom) / totalFrames;
|
||||
interpolatedZoom = Zoom.hermiteCubic.f(self.x, self.x1, self.x2, self.y1, self.y2, self.m1, self.m2);
|
||||
// Clamp the interpolation in case it is < 0 for a time
|
||||
interpolatedZoom = Math.max(0, interpolatedZoom);
|
||||
|
||||
// Apply zoom level to map or perform any necessary rendering
|
||||
self.view.setZoom(interpolatedZoom);
|
||||
|
||||
self.fov = interpolatedZoom;
|
||||
|
||||
// Check if interpolation is complete
|
||||
if (self.stop) {
|
||||
console.log("stop")
|
||||
self.isZooming = false;
|
||||
self.stop = false;
|
||||
} else if (self.x >= self.x2 || Math.abs(interpolatedZoom - self.finalZoom) < 1e-4) {
|
||||
self.view.setZoom(self.finalZoom);
|
||||
|
||||
self.isZooming = false;
|
||||
} else {
|
||||
// Request the next frame
|
||||
self.requestAnimID = requestAnimFrame(interpolateFrame);
|
||||
self.x = ( performance.now() - self.startTime ) / interpolationDuration;
|
||||
interpolatedZoom = Zoom.hermiteCubic.f(self.x, self.x1, self.x2, self.y1, self.y2, self.m1, self.m2);
|
||||
// Clamp the interpolation in case it is < 0 for a time
|
||||
interpolatedZoom = Math.max(0, interpolatedZoom);
|
||||
|
||||
// Apply zoom level to map or perform any necessary rendering
|
||||
self.view.setZoom(interpolatedZoom);
|
||||
|
||||
self.fov = interpolatedZoom;
|
||||
|
||||
if (self.x >= self.x2 || Math.abs(interpolatedZoom - self.finalZoom) < 1e-4) {
|
||||
console.log("finish")
|
||||
self.view.setZoom(self.finalZoom);
|
||||
|
||||
self.isZooming = false;
|
||||
} else {
|
||||
// Request the next frame
|
||||
self.requestAnimID = requestAnimFrame(interpolateFrame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 237 KiB After Width: | Height: | Size: 236 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 352 KiB After Width: | Height: | Size: 352 KiB |
Reference in New Issue
Block a user