Skip to content

Commit ccdf392

Browse files
#763 Vector Layer Updates Cause Features to Flash (#764)
1 parent 1816cb6 commit ccdf392

File tree

5 files changed

+114
-66
lines changed

5 files changed

+114
-66
lines changed

src/essence/Ancillary/TimeControl.js

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -386,33 +386,46 @@ var TimeControl = {
386386
// refresh time enabled layers
387387
let reloadedLayers = []
388388
let savedActiveFeature = null
389-
389+
390390
// Save active feature if it belongs to a time-enabled layer
391391
if (L_.activeFeature) {
392392
const activeLayerName = L_.activeFeature.layerName
393393
const activeLayer = L_.layers.data[activeLayerName]
394-
395-
if (activeLayer && activeLayer.time && activeLayer.time.enabled === true) {
394+
395+
if (
396+
activeLayer &&
397+
activeLayer.time &&
398+
activeLayer.time.enabled === true
399+
) {
396400
// Save the active feature details for restoration
397401
savedActiveFeature = {
398402
layerName: activeLayerName,
399-
feature: JSON.parse(JSON.stringify(L_.activeFeature.feature))
403+
feature: JSON.parse(
404+
JSON.stringify(L_.activeFeature.feature)
405+
),
400406
}
401-
407+
402408
// If the layer has useKeyAsId or useKeyAsName, save the key/value
403-
const keyProp = activeLayer.variables?.useKeyAsId || activeLayer.variables?.useKeyAsName
409+
const keyProp =
410+
activeLayer.variables?.useKeyAsId ||
411+
activeLayer.variables?.useKeyAsName
404412
if (keyProp && L_.activeFeature.feature.properties) {
405413
// keyProp might be a path like "properties.id" or just "id"
406-
const keyPath = keyProp.includes('.') ? keyProp.split('.') : [keyProp]
407-
const keyValue = F_.getIn(L_.activeFeature.feature.properties, keyPath)
414+
const keyPath = keyProp.includes('.')
415+
? keyProp.split('.')
416+
: [keyProp]
417+
const keyValue = F_.getIn(
418+
L_.activeFeature.feature.properties,
419+
keyPath
420+
)
408421
if (keyValue != null) {
409422
savedActiveFeature.key = keyProp
410423
savedActiveFeature.value = keyValue
411424
}
412425
}
413426
}
414427
}
415-
428+
416429
for (let layerName in L_.layers.data) {
417430
const layer = L_.layers.data[layerName]
418431
if (
@@ -424,37 +437,51 @@ var TimeControl = {
424437
reloadedLayers.push(layer.name)
425438
}
426439
}
427-
440+
428441
// Restore active feature after layers reload
429-
if (savedActiveFeature && reloadedLayers.includes(savedActiveFeature.layerName)) {
442+
if (
443+
savedActiveFeature &&
444+
reloadedLayers.includes(savedActiveFeature.layerName)
445+
) {
430446
setTimeout(() => {
431447
// Try to restore using key/value if available
432448
if (savedActiveFeature.key && savedActiveFeature.value) {
433449
L_.selectPoint({
434450
layerUUID: savedActiveFeature.layerName,
435451
key: savedActiveFeature.key,
436-
value: savedActiveFeature.value
452+
value: savedActiveFeature.value,
437453
})
438-
} else if (savedActiveFeature.feature.geometry && savedActiveFeature.feature.geometry.coordinates) {
454+
} else if (
455+
savedActiveFeature.feature.geometry &&
456+
savedActiveFeature.feature.geometry.coordinates
457+
) {
439458
// Fallback to selecting by coordinates
440-
const coords = savedActiveFeature.feature.geometry.coordinates
459+
const coords =
460+
savedActiveFeature.feature.geometry.coordinates
441461
let lat, lon
442462
if (savedActiveFeature.feature.geometry.type === 'Point') {
443463
lon = coords[0]
444464
lat = coords[1]
445-
} else if (savedActiveFeature.feature.geometry.type === 'LineString' ||
446-
savedActiveFeature.feature.geometry.type === 'Polygon') {
465+
} else if (
466+
savedActiveFeature.feature.geometry.type ===
467+
'LineString' ||
468+
savedActiveFeature.feature.geometry.type === 'Polygon'
469+
) {
447470
// Get first coordinate or centroid
448-
const firstCoord = savedActiveFeature.feature.geometry.type === 'Polygon' ? coords[0][0] : coords[0]
471+
const firstCoord =
472+
savedActiveFeature.feature.geometry.type ===
473+
'Polygon'
474+
? coords[0][0]
475+
: coords[0]
449476
lon = firstCoord[0]
450477
lat = firstCoord[1]
451478
}
452-
479+
453480
if (lat != null && lon != null) {
454481
L_.selectPoint({
455482
layerUUID: savedActiveFeature.layerName,
456483
lat: lat,
457-
lon: lon
484+
lon: lon,
458485
})
459486
}
460487
}

src/essence/Ancillary/TimeUI.js

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -938,7 +938,7 @@ const TimeUI = {
938938
.css('left', `${(left / timelineBCR.width) * 100}%`)
939939
}
940940
},
941-
_refreshIntervals() {
941+
_refreshIntervals(dontChange) {
942942
clearInterval(TimeUI.playInterval)
943943
if (TimeUI.play) {
944944
TimeUI._loopTime()
@@ -950,10 +950,9 @@ const TimeUI = {
950950

951951
clearInterval(TimeUI.presentTimeInterval)
952952
if (TimeUI.now) {
953-
TimeUI.presentTimeInterval = setInterval(
954-
TimeUI._setCurrentTime,
955-
TimeUI.intervalValues[TimeUI.intervalIndex]
956-
)
953+
TimeUI.presentTimeInterval = setInterval(() => {
954+
TimeUI._setCurrentTime(null, null, dontChange)
955+
}, TimeUI.intervalValues[TimeUI.intervalIndex])
957956
}
958957
TimeUI._refreshLiveProgress()
959958
},
@@ -1112,7 +1111,7 @@ const TimeUI = {
11121111
TimeUI.clearFollowedFeature()
11131112
}
11141113
}
1115-
TimeUI._refreshIntervals()
1114+
TimeUI._refreshIntervals(true)
11161115
},
11171116
toggleFollowFeature() {
11181117
if (!TimeUI.followEnabled) {
@@ -1325,7 +1324,7 @@ const TimeUI = {
13251324
}
13261325

13271326
const layerName = L_.FUTURES.activePoint.layerName
1328-
1327+
13291328
// Check if we can follow this layer
13301329
if (!TimeUI.canFollowLayer(layerName)) {
13311330
console.log(
@@ -1345,7 +1344,7 @@ const TimeUI = {
13451344
setTimeout(waitForActiveFeature, 500)
13461345
}
13471346
}
1348-
1347+
13491348
waitForActiveFeature()
13501349
},
13511350
_remakeTimeSlider(ignoreHistogram) {
@@ -1616,7 +1615,7 @@ const TimeUI = {
16161615
const parsedNow = TimeUI.endTempus.dates.parseInput(
16171616
new Date(offsetNowDate)
16181617
)
1619-
1618+
//disableChange = true
16201619
TimeUI.setCurrentTime(parsedNow, disableChange)
16211620
//TimeUI._remakeTimeSlider(true)
16221621
TimeUI.endTempus.dates.setValue(parsedNow)

src/essence/Basics/Layers_/Layers_.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2886,8 +2886,8 @@ const L_ = {
28862886
if (layerName in L_.layers.layer) {
28872887
const layerObj = L_.layers.data[layerName]
28882888
if (L_._layersBeingMade[layerName] === true) {
2889-
console.error(
2890-
`ERROR - updateVectorLayer: Cannot make layer ${layerObj.display_name}/${layerObj.name} as it's already being made!`
2889+
console.warn(
2890+
`WARNING - updateVectorLayer: Cannot make layer ${layerObj.display_name}/${layerObj.name} as it's already being made!`
28912891
)
28922892
return false
28932893
}

src/essence/Basics/Map_/Map_.js

Lines changed: 48 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -531,31 +531,25 @@ let Map_ = {
531531
L_.layers.data[L_._layersOrdered[i]].type == 'vector' &&
532532
L_.layers.data[L_._layersOrdered[i]].name == layerObj.name
533533
) {
534+
// Original
534535
if (L_._layersBeingMade[layerObj.name] !== true) {
535-
const wasOn = L_.layers.on[layerObj.name]
536-
537-
if (wasOn)
538-
L_.toggleLayer(
539-
L_.layers.data[layerObj.name],
540-
skipOrderedBringToFront
541-
) // turn off if on
542-
543-
// fake on
536+
// makeLayer now handles all layer swapping internally for refresh operations
544537
L_.layers.on[layerObj.name] = true
545-
await makeLayer(layerObj, true, null, null, null, stopLoops)
538+
await makeLayer(
539+
layerObj,
540+
true,
541+
null,
542+
null,
543+
null,
544+
stopLoops,
545+
true
546+
)
546547
L_.addVisible(Map_, [layerObj.name])
547548

548-
// turn off if was off
549-
if (wasOn) L_.layers.on[layerObj.name] = false
550-
L_.toggleLayer(
551-
L_.layers.data[layerObj.name],
552-
skipOrderedBringToFront
553-
) // turn back on/off
554-
555549
L_.enforceVisibilityCutoffs()
556550
} else {
557-
console.error(
558-
`ERROR - refreshLayer: Cannot make layer ${layerObj.display_name}/${layerObj.name} as it's already being made!`
551+
console.warn(
552+
`WARNING - refreshLayer: Cannot make layer ${layerObj.display_name}/${layerObj.name} as it's already being made!`
559553
)
560554
if (typeof cb === 'function') cb()
561555
return false
@@ -677,7 +671,8 @@ async function makeLayer(
677671
forceGeoJSON,
678672
id,
679673
forceMake,
680-
stopLoops
674+
stopLoops,
675+
isRefresh = false
681676
) {
682677
return new Promise(async (resolve, reject) => {
683678
const layerName = L_.asLayerUUID(layerObj.name)
@@ -700,7 +695,8 @@ async function makeLayer(
700695
layerObj,
701696
evenIfOff,
702697
null,
703-
forceGeoJSON
698+
forceGeoJSON,
699+
isRefresh
704700
)
705701
break
706702
case 'velocity':
@@ -874,7 +870,8 @@ async function makeVectorLayer(
874870
layerObj,
875871
evenIfOff,
876872
useEmptyGeoJSON,
877-
forceGeoJSON
873+
forceGeoJSON,
874+
isRefresh = false
878875
) {
879876
return new Promise((resolve, reject) => {
880877
if (forceGeoJSON) add(forceGeoJSON)
@@ -947,9 +944,27 @@ async function makeVectorLayer(
947944
onEachFeatureDefault,
948945
Map_
949946
)
947+
948+
// For refresh operations, toggle off old layer and handle seamless swap
949+
let wasOnForRefresh = false
950+
if (
951+
isRefresh &&
952+
L_.layers.on[layerObj.name] &&
953+
L_.layers.layer[layerObj.name] &&
954+
L_.Map_.map.hasLayer(L_.layers.layer[layerObj.name])
955+
) {
956+
wasOnForRefresh = true
957+
L_.toggleLayer(L_.layers.data[layerObj.name], true)
958+
}
959+
950960
L_.layers.attachments[layerObj.name] = vl.sublayers
951961
L_.layers.layer[layerObj.name] = vl.layer
952962

963+
// For refresh operations, turn the new layer back on if the old one was on
964+
if (isRefresh && wasOnForRefresh) {
965+
L_.toggleLayer(L_.layers.data[layerObj.name], true)
966+
}
967+
953968
d3.selectAll('.' + F_.getSafeName(layerObj.name)).data(
954969
data.features
955970
)
@@ -1770,21 +1785,27 @@ function makeVideoLayer(layerObj) {
17701785
)
17711786

17721787
// Add updateFilter function to video layer for CSS filter support
1773-
L_.layers.layer[layerObj.name].updateFilter = function(filterArray) {
1788+
L_.layers.layer[layerObj.name].updateFilter = function (filterArray) {
17741789
const videoElement = this.getElement()
17751790
if (videoElement) {
17761791
let cssFilters = []
17771792

1778-
filterArray.forEach(filter => {
1793+
filterArray.forEach((filter) => {
17791794
const [property, value] = filter.split(':')
17801795
// Skip blend mode for videos - only handle CSS filters
17811796
if (property !== 'mix-blend-mode') {
17821797
if (property === 'saturate') {
1783-
cssFilters.push(`saturate(${parseFloat(value) * 100}%)`)
1798+
cssFilters.push(
1799+
`saturate(${parseFloat(value) * 100}%)`
1800+
)
17841801
} else if (property === 'brightness') {
1785-
cssFilters.push(`brightness(${parseFloat(value) * 100}%)`)
1802+
cssFilters.push(
1803+
`brightness(${parseFloat(value) * 100}%)`
1804+
)
17861805
} else if (property === 'contrast') {
1787-
cssFilters.push(`contrast(${parseFloat(value) * 100}%)`)
1806+
cssFilters.push(
1807+
`contrast(${parseFloat(value) * 100}%)`
1808+
)
17881809
}
17891810
}
17901811
})

src/essence/Basics/Viewer_/Viewer_.js

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ var Viewer_ = {
409409
console.log('here')
410410
}
411411
})
412-
} else if (o.isVideo || (extLow === 'webm' || extLow === 'mp4')) {
412+
} else if (o.isVideo || extLow === 'webm' || extLow === 'mp4') {
413413
this.imageVideo.style('display', 'inherit')
414414
this.imagePDF.style('display', 'none')
415415
this.imagePanorama.style('display', 'none')
@@ -428,11 +428,11 @@ var Viewer_ = {
428428
// Handle loading events
429429
Viewer_.toolBarLoading.style('opacity', '1')
430430

431-
videoElement.onloadeddata = function() {
431+
videoElement.onloadeddata = function () {
432432
Viewer_.toolBarLoading.style('opacity', '0')
433433
}
434434

435-
videoElement.onerror = function() {
435+
videoElement.onerror = function () {
436436
Viewer_.toolBarLoading.html('Error loading video')
437437
setTimeout(() => {
438438
Viewer_.toolBarLoading.style('opacity', '0')
@@ -457,11 +457,11 @@ var Viewer_ = {
457457
// Handle loading events
458458
Viewer_.toolBarLoading.style('opacity', '1')
459459

460-
imgElement.onload = function() {
460+
imgElement.onload = function () {
461461
Viewer_.toolBarLoading.style('opacity', '0')
462462
}
463463

464-
imgElement.onerror = function() {
464+
imgElement.onerror = function () {
465465
Viewer_.toolBarLoading.html('Error loading GIF')
466466
setTimeout(() => {
467467
Viewer_.toolBarLoading.style('opacity', '0')
@@ -506,10 +506,11 @@ var Viewer_ = {
506506
if (setLocAfter) {
507507
setTimeout(function () {
508508
//Because openseadragon's simple image open event is broken
509-
var l = L_.FUTURES.viewerLoc
510-
Viewer_.imageViewerMap.viewport.fitBounds(
511-
new OpenSeadragon.Rect(l[0], l[1], l[2], l[3])
512-
)
509+
const l = L_.FUTURES.viewerLoc
510+
if (l)
511+
Viewer_.imageViewerMap.viewport.fitBounds(
512+
new OpenSeadragon.Rect(l[0], l[1], l[2], l[3])
513+
)
513514
L_.FUTURES.viewerLoc = null
514515
}, 2000)
515516
}

0 commit comments

Comments
 (0)