I would like to show and hide the tool using a button, but I haven't been able to make it work. The image below displays the problems that I encountered. The first problem is I am not sure how to reset environment setting (removing shadow), and the second problem is how to make the clock to work (getting local time and also shadow casting). I would appreciate your assistance.
var clock = new Clock({
el: "clock",
skin: require.toUrl('./third-party/clock.svg'),
time: sceneView.environment.lighting.date.getTime()
});
sceneView.ui.add('clock', 'bottom-right');
clock.on('time-change', function(time) {
sceneView.environment.lighting.date = time;
sceneView.environment.lighting.directShadowsEnabled = true;
});
$('#shadow').on('click', function(){
var display = $('#clock').css('display');
if (display == 'block') {
$('#clock').css('display', 'none');
// Show shadow with clock;
sceneView.ui.add('clock', 'bottom-right');
} else {
$('#clock').css('display', 'block');
// Hide shadow and clock
sceneView.ui.remove(clock);
}
})
Solved! Go to Solution.
It looks to me like .remove is not working correctly on the clock. I'm not sure if this is my mistake or a problem in the clock code.
Discounting .remove, you should still be able to toggle the clock's visibility and the lighting in the scene. You can just allow the event listener to keep running in the background. Based on your code, something like this should work:
let shadowBtn = dom.byId('shadow');
let clock = new Clock({
el: 'clock',
skin: require.toUrl('./third-party/clock.svg'),
time: sceneView.environment.lighting.date.getTime()
});
// start with lighing off as clock starts hidden
sceneView.environment.lighting.directShadowsEnabled = false;
clock.on("time-change", function (time) {
sceneView.environment.lighting.date = time;
});
sceneView.ui.add('clock', 'bottom-left');
clock.el.style.visibility = 'hidden';
shadowBtn.addEventListener('click', function(e){
if (clock.el.style.visibility !== 'hidden'){
clock.el.style.visibility = 'hidden';
sceneView.environment.lighting.directShadowsEnabled = false;
} else {
clock.el.style.visibility = 'visible';
sceneView.environment.lighting.directShadowsEnabled = true;
}
});
If your goal is to hide/show the clock, you might want to toggle "visibility: hidden" and "visibility: visible" rather than display. If you do it this way, you won't have to remove and re-add the clock each time, you'll just be hiding it.
Something like this:
let btn = <reference to HTML button to toggle clock>;
let clock = <reference to clock widget>;
btn.addEventListener('click',(e)=>{
// clock.el will be a reference to the widget's element containing
// the clock
if (clock.el.style.visibility === 'visible'){
clock.el.style.visibility = 'hidden';
} else {
clock.el.style.visibility = 'visible';
}
});
In terms of removing the environment settings, you could just use https://developers.arcgis.com/javascript/latest/api-reference/esri-views-SceneView.html#environment to toggle direct shadows on and off.
It's also possible that what you want to do is to totally remove the time and environment when the clock is toggled off. In that case, you should remove the clock.on("time-change") event. .on will return a handle which you can remove by calling .remove on the handle. Something like this:
let btn = <reference to HTML button to toggle clock>;
let clock = <reference to clock widget>;
let listener = clock.on('time-change', function(...){...});
btn.addEventListener('click',(e)=>{
// clock.el will be a reference to the widget's element containing
// the clock
if (clock.el.style.visibility === 'visible'){
clock.el.style.visibility = 'hidden';
listener.remove();
view.environment.lighting.directShadowsEnabled = false;
} else {
clock.el.style.visibility = 'visible';
listener = clock.on('time-change', function(...){...});
view.environment.lighting.directShadowsEnabled = true;
}
});
Thank you so much for quick response. The first provided code for the hide/show works perfectly, however, I am having the problem with the code removing the time and environment totally.
In line 15 (my code: line 23), I am getting an error shown as below. Unfortunately, I am having the same problem that I initiated the question. Once removed shadow (once visibility is hidden), the clock doesn't show the time correctly and casting shadow function no longer works. I tried a few things, but no luck.
let btn = <reference to HTML button to toggle clock>;
let clock = <reference to clock widget>;
let listener = clock.on('time-change', function(...){...});
btn.addEventListener('click',(e)=>{
// clock.el will be a reference to the widget's element containing
// the clock
if (clock.el.style.visibility === 'visible'){
clock.el.style.visibility = 'hidden';
listener.remove();
view.environment.lighting.directShadowsEnabled = false;
} else {
clock.el.style.visibility = 'visible';
listener = clock.on('time-change', function(...){...});
view.environment.lighting.directShadowsEnabled = true;
}
});
Here is my code:
let shadowBtn = dom.byId('shadow');
let clock = new Clock({
el: 'clock',
skin: require.toUrl('./third-party/clock.svg'),
time: sceneView.environment.lighting.date.getTime()
});
let listener = clock.on("time-change", function (time) {
sceneView.environment.lighting.date = time;
sceneView.environment.lighting.directShadowsEnabled = true;
});
sceneView.ui.add('clock', 'bottom-left');
clock.el.style.visibility = 'hidden';
shadowBtn.addEventListener('click', function(e){
// clock.el will be a reference to the widget's element containing
// the clock
if (clock.el.style.visibility === 'visible'){
clock.el.style.visibility = 'hidden';
listener.remove();
sceneView.environment.lighting.directShadowsEnabled = false;
} else {
clock.el.style.visibility = 'visible';
listener = clock.on("time-change", function (time) {
sceneView.environment.lighting.date = time;
sceneView.environment.lighting.directShadowsEnabled = true;
});
}
});
It looks to me like .remove is not working correctly on the clock. I'm not sure if this is my mistake or a problem in the clock code.
Discounting .remove, you should still be able to toggle the clock's visibility and the lighting in the scene. You can just allow the event listener to keep running in the background. Based on your code, something like this should work:
let shadowBtn = dom.byId('shadow');
let clock = new Clock({
el: 'clock',
skin: require.toUrl('./third-party/clock.svg'),
time: sceneView.environment.lighting.date.getTime()
});
// start with lighing off as clock starts hidden
sceneView.environment.lighting.directShadowsEnabled = false;
clock.on("time-change", function (time) {
sceneView.environment.lighting.date = time;
});
sceneView.ui.add('clock', 'bottom-left');
clock.el.style.visibility = 'hidden';
shadowBtn.addEventListener('click', function(e){
if (clock.el.style.visibility !== 'hidden'){
clock.el.style.visibility = 'hidden';
sceneView.environment.lighting.directShadowsEnabled = false;
} else {
clock.el.style.visibility = 'visible';
sceneView.environment.lighting.directShadowsEnabled = true;
}
});
Thank you so much for your assistance!! It is working perfectly. I added a line of code that starts the clock on 'live' mode.
shadowBtn.addEventListener('click', function(e){
if (clock.el.style.visibility === 'visible'){
clock.el.style.visibility = 'hidden';
sceneView.environment.lighting.directShadowsEnabled = false;
} else {
clock.el.style.visibility = 'visible';
sceneView.environment.lighting.directShadowsEnabled = true;
clock.mode = 'live'; // Show clock on 'live' mode
}
});