@@ -164,38 +164,35 @@ def _build_legend_html(
164164 )
165165
166166
167- def _interior_plane_transform (axis : str , index : int , meta : Dict [str , int ], size_px : int ) -> str :
168- half = size_px / 2
167+ def _interior_plane_transform (axis : str , index : int , meta : Dict [str , int ], size_css : str ) -> str :
169168 nt = max (meta .get ("nt" , 1 ) - 1 , 1 )
170169 ny = max (meta .get ("ny" , 1 ) - 1 , 1 )
171170 nx = max (meta .get ("nx" , 1 ) - 1 , 1 )
172171 if axis == "time" :
173172 frac = index / nt
174- z = - half + frac * size_px
175- return f"translate3d(0px, 0px, { z :.2f } px )"
173+ z = f"calc(-0.5 * { size_css } + { frac :.6f } * { size_css } )"
174+ return f"translate3d(0px, 0px, { z } )"
176175 if axis == "x" :
177176 frac = index / nx
178- x_off = - half + frac * size_px
179- return f"rotateY(90deg) translateZ({ x_off :.2f } px )"
177+ x_off = f"calc(-0.5 * { size_css } + { frac :.6f } * { size_css } )"
178+ return f"rotateY(90deg) translateZ({ x_off } )"
180179 if axis == "y" :
181180 frac = index / ny
182- y_off = - half + frac * size_px
183- return f"rotateX(90deg) translateZ({ y_off :.2f } px )"
181+ y_off = f"calc(-0.5 * { size_css } + { frac :.6f } * { size_css } )"
182+ return f"rotateX(90deg) translateZ({ y_off } )"
184183 return ""
185184
186185
187- def _vase_panel_transform (panel : VasePanel , size_px : int ) -> str :
188- half = size_px / 2
189-
190- def _offset (norm : float ) -> float :
191- return - half + float (norm ) * size_px
186+ def _vase_panel_transform (panel : VasePanel , size_css : str ) -> str :
187+ def _offset (norm : float ) -> str :
188+ return f"calc(-0.5 * { size_css } + { float (norm ):.6f} * { size_css } )"
192189
193190 x_off = _offset (panel .x )
194191 y_off = _offset (panel .y )
195192 z_off = _offset (panel .z )
196193
197194 return (
198- f"translate3d({ x_off :.2f } px , { y_off :.2f } px , { z_off :.2f } px ) "
195+ f"translate3d({ x_off } , { y_off } , { z_off } ) "
199196 f"rotateY({ panel .yaw :.2f} deg) rotateX(90deg)"
200197 )
201198
@@ -214,7 +211,7 @@ def _render_cube_html(
214211 coord : "CoordCube" | None ,
215212 legend_html : str ,
216213 title_html : str ,
217- size_px : int ,
214+ size_px : int | None ,
218215 axis_meta : Dict [str , Dict [str , str ]] | None ,
219216 axis_rig_spec : AxisRigSpec | None ,
220217 axis_rig_meta : Dict [str , Any ] | None ,
@@ -227,9 +224,10 @@ def _render_cube_html(
227224 # file export. Keeping the template self contained ensures that v.plot()
228225 # renders the exact same viewer in both contexts.
229226 interior_html_parts = []
227+ size_css = "var(--cd-cube-size)"
230228 if interior_planes :
231229 for axis , idx , b64 , meta in interior_planes :
232- transform = _interior_plane_transform (axis , idx , meta or interior_meta , size_px )
230+ transform = _interior_plane_transform (axis , idx , meta or interior_meta , size_css )
233231 interior_html_parts .append (
234232 "<div class=\" interior-plane\" "
235233 f"style=\" transform: { transform } ; background-image: url('data:image/png;base64,{ b64 } ');\" ></div>"
@@ -239,12 +237,12 @@ def _render_cube_html(
239237 vase_html_parts = []
240238 if vase_panels :
241239 for panel in vase_panels :
242- width_px = max (2.0 , float (panel .width ) * size_px )
243- height_px = max (2.0 , float (panel .height ) * size_px )
244- transform = _vase_panel_transform (panel , size_px )
240+ width_px = f" max(2px, calc( { float (panel .width ):.6f } * { size_css } ))"
241+ height_px = f" max(2px, calc( { float (panel .height ):.6f } * { size_css } ))"
242+ transform = _vase_panel_transform (panel , size_css )
245243 vase_html_parts .append (
246244 "<div class=\" cd-vase-panel\" "
247- f"style=\" width: { width_px :.2f } px ; height: { height_px :.2f } px ; transform: { transform } ;\" ></div>"
245+ f"style=\" width: { width_px } ; height: { height_px } ; transform: { transform } ;\" ></div>"
248246 )
249247 vase_html = "" .join (vase_html_parts )
250248
@@ -283,15 +281,18 @@ def _render_cube_html(
283281
284282 axis_rig_data_attr = " data-axis-rig=\" true\" " if axis_rig_spec else ""
285283
284+ cube_size_css = (
285+ f"{ size_px } px" if size_px is not None else "clamp(320px, min(70vh, 70vw), 760px)"
286+ )
286287 html = f"""
287288<!DOCTYPE html>
288289<html lang=\" en\" >
289290<head>
290291 <meta charset=\" UTF-8\" />
291292 <style>
292293 :root {{
293- --cube-size: { size_px } px ;
294- --cd- cube-size: var(--cube-size);
294+ --cd- cube-size: { cube_size_css } ;
295+ --cube-size: var(--cd -cube-size);
295296 { css_vars }
296297 }}
297298 * {{ box-sizing: border-box; }}
@@ -807,7 +808,7 @@ def cube_from_dataarray(
807808 da : xr .DataArray ,
808809 out_html : str = "cube_da.html" ,
809810 cmap : str = "viridis" ,
810- size_px : int = 260 ,
811+ size_px : int | None = None ,
811812 thin_time_factor : int = 4 ,
812813 title : str | None = None ,
813814 time_label : str | None = None ,
@@ -1065,7 +1066,7 @@ def _face_to_png(arr: np.ndarray, mask_key: str | None) -> str:
10651066 "--cube-panel-color" : getattr (theme , "panel_color" , "#000" ),
10661067 "--cube-shadow-strength" : str (getattr (theme , "shadow_strength" , 0.2 )),
10671068 "--cube-title-color" : getattr (theme , "title_color" , "#f7f7f7" ),
1068- "--cube-axis-color" : getattr (theme , "axis_color" , "#f7f7f7 " ),
1069+ "--cube-axis-color" : getattr (theme , "axis_color" , "rgba(25, 25, 25, 0.9) " ),
10691070 "--cube-legend-color" : getattr (theme , "legend_color" , "#f7f7f7" ),
10701071 "--cube-title-font-size" : f"{ getattr (theme , 'title_font_size' , 18 )} px" ,
10711072 "--cube-axis-font-size" : f"{ getattr (theme , 'title_font_size' , 18 ) * getattr (theme , 'axis_scale' , 0.6 )} px" ,
@@ -1113,11 +1114,12 @@ def _face_to_png(arr: np.ndarray, mask_key: str | None) -> str:
11131114 f .write (full_html )
11141115 if return_html :
11151116 return full_html
1117+ frame_base = size_px if size_px is not None else 760
11161118 prefix = Path (out_html ).stem or "cube_viewer"
11171119 return show_cube_viewer (
11181120 full_html ,
1119- width = max (850 , size_px + 300 ),
1120- height = max (850 , size_px + 300 ),
1121+ width = max (850 , frame_base + 300 ),
1122+ height = max (850 , frame_base + 300 ),
11211123 prefix = prefix ,
11221124 )
11231125
@@ -1195,11 +1197,12 @@ def _face_to_png(arr: np.ndarray, mask_key: str | None) -> str:
11951197
11961198 if return_html :
11971199 return full_html
1200+ frame_base = size_px if size_px is not None else 760
11981201 prefix = Path (out_html ).stem or "cube_viewer"
11991202 return show_cube_viewer (
12001203 full_html ,
1201- width = max (850 , size_px + 300 ),
1202- height = max (850 , size_px + 300 ),
1204+ width = max (850 , frame_base + 300 ),
1205+ height = max (850 , frame_base + 300 ),
12031206 prefix = prefix ,
12041207 )
12051208
0 commit comments