@@ -26,24 +26,24 @@ import {
2626 getShiftedOpacityFromPreset ,
2727} from ' @/src/utils/vtk-helpers' ;
2828import { useVolumeThumbnailing } from ' @/src/composables/useVolumeThumbnailing' ;
29- import { useViewStore } from ' @/src/store/views' ;
3029
3130const WIDGET_WIDTH = 250 ;
3231const WIDGET_HEIGHT = 150 ;
3332const THUMBNAIL_SIZE = 80 ;
3433
3534export default defineComponent ({
3635 name: ' VolumeRendering' ,
37- setup() {
36+ props: {
37+ viewId: {
38+ type: String ,
39+ default: null ,
40+ },
41+ },
42+ setup(props ) {
3843 const volumeColoringStore = useVolumeColoringStore ();
3944 const editorContainerRef = ref <HTMLElement | null >(null );
4045 const pwfEditorRef = ref <HTMLElement | null >(null );
41- const viewStore = useViewStore ();
42- const viewId = computed (() => {
43- const view = viewStore .getView (viewStore .activeView );
44- if (view ?.type === ' 3D' ) return view .id ;
45- return null ;
46- });
46+ const viewId = computed (() => props .viewId );
4747
4848 let recurseGuard = false ;
4949
@@ -280,36 +280,56 @@ export default defineComponent({
280280
281281 // --- mapping range editing --- //
282282
283- const rangeShift = ref (0 );
284- const rangeWidth = ref (0 );
285-
286283 onKeyDown (' Control' , () => pwfWidget .setShiftOpacityValues (true ));
287284 onKeyUp (' Control' , () => pwfWidget .setShiftOpacityValues (false ));
288285
286+ const rangeShift = ref (0 );
287+ const rangeWidth = ref (0 );
288+
289289 const reset = () => {
290290 rangeShift .value = 0 ;
291291 rangeWidth .value = fullMappingRangeWidth .value ;
292292 };
293- // reset case
293+
294+ // Reset when preset or image changes
294295 watch ([selectedPreset , currentImageID ], reset , { immediate: true });
295296
296297 useResetViewsEvents ().onClick (reset );
297298
299+ // Sync slider values from mappingRange when it changes (e.g., when switching views)
300+ watch (
301+ () => colorTransferFunctionRef .value ?.mappingRange ,
302+ (mappingRange ) => {
303+ if (! mappingRange ) return ;
304+
305+ const fullRange = fullMappingRange .value ;
306+ const fullCenter = (fullRange [0 ] + fullRange [1 ]) / 2 ;
307+ const currentCenter = (mappingRange [0 ] + mappingRange [1 ]) / 2 ;
308+
309+ rangeWidth .value = mappingRange [1 ] - mappingRange [0 ];
310+ rangeShift .value = currentCenter - fullCenter ;
311+ }
312+ );
313+
314+ // Update store when sliders change (using center-based math to avoid drift)
298315 watch ([rangeShift , rangeWidth ], ([shift , width ]) => {
299- if (! viewId .value ) return ;
300- const imageID = currentImageID .value ;
301- const config = volumeColoringStore .getConfig (viewId .value , imageID );
302- // wait for config to be initialized with preset "all view default" for particular image
303- if (! imageID || ! config ) return ;
316+ if (! viewId .value || ! currentImageID .value ) return ;
304317
305318 const fullRange = fullMappingRange .value ;
306- const fullWidth = fullMappingRangeWidth . value ;
307- const min = fullRange [ 0 ] + Math . floor (( fullWidth - width ) / 2 ) + shift ;
308- const max = fullRange [ 1 ] - Math . ceil (( fullWidth - width ) / 2 ) + shift ;
319+ const fullCenter = ( fullRange [ 0 ] + fullRange [ 1 ]) / 2 ;
320+ const newCenter = fullCenter + shift ;
321+ const halfWidth = width / 2 ;
309322
310- volumeColoringStore .updateColorTransferFunction (viewId .value , imageID , {
311- mappingRange: [min , max ],
312- });
323+ const min = newCenter - halfWidth ;
324+ const max = newCenter + halfWidth ;
325+
326+ volumeColoringStore .updateColorTransferFunction (
327+ viewId .value ,
328+ currentImageID .value ,
329+ {
330+ mappingRange: [min , max ],
331+ }
332+ );
313333 });
314334
315335 return {
0 commit comments