skip to Main Content

I’m using react-vega (a React wrapper for Vega-Lite) to render visualizations from a JSON schema. It works well, except when I want to display a vertically concatenated view (using vconcat) that fits the container size and provides an interactive brush feature to select data on the visualization.

I have tested multiple approaches including:

  • Setting the width and height of the container as schema
  • Rescaling all visualizations manually (by modifying their width/height properties in the schema)

However, nothing works as expected. Even if the visualization fits the screen, the interactive brush is offset. To be fair, all solutions I’ve come up with feel "hacky," as the problem of fitting the visualization to the container size should be solved internally by the library itself.

Link to a minimal reproduction Sandbox with all approaches explained (React)

Could you point out any invalid logic in my approaches or suggest an alternative? This issue has been haunting me for a while now.

Expected

Visualization fits the container. The interactive brush works as expected. No content clipped.

Expected

Actual

Content clipped.

Actual

Generalization

Generalization

Minimal reproduction code with all my approaches to solve this problem:

import React from "react";
import { spec, data } from "./schema.js";
import { VegaLite } from "react-vega";
import useMeasure from "react-use-measure";
import { replaceAllFieldsInJson } from "./utils.ts";

import "./style.css";

export default function App() {
  return (
    <div className="App">
      <VisualizationContainer
        style={{ overflow: "hidden" }}
        title="VegaLite + useMeasure"
        description="Interactive brush works as expected, but visualization is clipped"
        invalid
      >
        <VegaLiteAndUseMeasure spec={spec} data={data} />
      </VisualizationContainer>

      <VisualizationContainer
        style={{ overflow: "scroll" }}
        title="VegaLite + overflow-scroll"
        description="Interactive brush works as expected, content can be accessed, but scrollable container is not an ideal solution"
      >
        <VegaLiteAndOverflowScroll spec={spec} data={data} />
      </VisualizationContainer>

      <VisualizationContainer
        style={{ overflow: "hidden" }}
        title="VegaLite + useMeasure + manual re-scaling"
        description="Interactive brush works as expected, visualization fits the container (width), height is clipped"
        invalid
      >
        <VegaLiteAndManualRescaling spec={spec} data={data} />
      </VisualizationContainer>
    </div>
  );
}

/* -------------------------------------------------------------------------------------------------
 * VegaLite + useMeasure
 * -----------------------------------------------------------------------------------------------*/

function VegaLiteAndUseMeasure(props) {
  const [measureRef, geometry] = useMeasure();

  const [spec, setSpec] = React.useState(props.spec);
  const view = React.useRef(undefined);

  React.useEffect(() => {
    if (geometry) {
      setSpec((spec) => ({
        ...spec,
        width: geometry.width,
        height: geometry.height,
      }));
      view.current?.resize?.();
    }
  }, [geometry]);

  return (
    <div style={{ width: "100%", height: "100%" }} ref={measureRef}>
      <VegaRenderer spec={spec} {...props} />
    </div>
  );
}

/* -------------------------------------------------------------------------------------------------
 * VegaLite + overflow-scroll
 * -----------------------------------------------------------------------------------------------*/

function VegaLiteAndOverflowScroll(props) {
  return (
    <div style={{ width: "100%", height: "100%" }}>
      <VegaRenderer spec={spec} {...props} />
    </div>
  );
}

/* -------------------------------------------------------------------------------------------------
 * VegaLite + manual re-scaling
 * -----------------------------------------------------------------------------------------------*/

function rescaleSchema(schema, widthScaleFactor, heightScaleFactor) {
  const INTERNAL_INITIAL_WIDTH_KEY = "_initial-width";
  const INTERNAL_INITIAL_HEIGHT_KEY = "_initial-height";

  const persistInternalVariable = (json, key, value) => {
    if (typeof json !== "object" || Array.isArray(json)) {
      return undefined;
    }
    if (!(key in json)) {
      json[key] = value;
    }
    return json[key];
  };

  return replaceAllFieldsInJson(schema, [
    {
      key: "width",
      strategy(key, json) {
        const currentWidth = Number(json[key]);
        const initialWidth = persistInternalVariable(
          json,
          INTERNAL_INITIAL_WIDTH_KEY,
          currentWidth
        );

        if (initialWidth && !Number.isNaN(initialWidth)) {
          json[key] = Math.floor(initialWidth * widthScaleFactor);
        }
      },
    },
    {
      key: "height",
      strategy(key, json) {
        const currentHeight = Number(json[key]);
        const initialHeight = persistInternalVariable(
          json,
          INTERNAL_INITIAL_HEIGHT_KEY,
          currentHeight
        );

        if (initialHeight && !Number.isNaN(initialHeight)) {
          json[key] = Math.floor(initialHeight * heightScaleFactor);
        }
      },
    },
  ]);
}

/* -----------------------------------------------------------------------------------------------*/

function VegaLiteAndManualRescaling(props) {
  const [measureRef, geometry] = useMeasure();

  const [spec, setSpec] = React.useState(props.spec);

  const [initialWidth, setInitialWidth] = React.useState(null);
  const [initialHeight, setInitialHeight] = React.useState(null);

  const expectedWidth = geometry?.width;
  const expectedHeight = geometry?.height;

  const widthScaleFactor = React.useMemo(
    () => (expectedWidth && initialWidth ? expectedWidth / initialWidth : 1),
    [expectedWidth, initialWidth]
  );
  const heightScaleFactor = React.useMemo(
    () =>
      expectedHeight && initialHeight ? expectedHeight / initialHeight : 1,
    [expectedHeight, initialHeight]
  );

  React.useEffect(() => {
    if (geometry) {
      setSpec((spec) => ({
        ...rescaleSchema({ ...spec }, widthScaleFactor, heightScaleFactor),
        width: geometry.width,
        height: geometry.height,
      }));
    }
  }, [geometry, widthScaleFactor, heightScaleFactor]);

  return (
    <div style={{ width: "100%", height: "100%" }} ref={measureRef}>
      <VegaRenderer
        {...props}
        key={`vega-renderer-manual-rescaling:${widthScaleFactor}:${heightScaleFactor}`}
        spec={spec}
        onNewView={(view) => {
          if (!initialWidth) {
            setInitialWidth(view._viewWidth ?? null);
          }
          if (!initialHeight) {
            setInitialHeight(view._viewHeight ?? null);
          }
          view?.resize?.();
        }}
      />
    </div>
  );
}

/* -------------------------------------------------------------------------------------------------
 * VisualizationContainer
 * -----------------------------------------------------------------------------------------------*/

function VisualizationContainer(props) {
  return (
    <figure className="vis-container">
      <header>
        <h1>{props.title}</h1>

        {props.description ? (
          <p className="vis-container__description">
            <span>{props.invalid ? "❌" : "✅"}</span>
            {props.description}
          </p>
        ) : null}
      </header>

      <div className="vis-container__wrapper" style={{ ...props.style }}>
        {props.children}
      </div>
    </figure>
  );
}

/* -------------------------------------------------------------------------------------------------
 * VegaRenderer
 * -----------------------------------------------------------------------------------------------*/

function VegaRenderer(props) {
  return <VegaLite actions={true} padding={24} {...props} />;
}

Schema:

export const spec = {
  $schema: "https://vega.github.io/schema/vega-lite/v5.json",
  data: { name: "table" },
  vconcat: [
    {
      encoding: {
        color: {
          type: "quantitative",
          field: "calculated pI",
          title: "Calculated Isoelectric Point",
        },
        tooltip: [
          {
            type: "quantitative",
            field: "deltaSol_F",
          },
          {
            type: "quantitative",
            field: "deltaSol_D",
          },
          {
            type: "quantitative",
            field: "calculated pI",
          },
        ],
        x: {
          type: "quantitative",
          field: "deltaSol_F",
          title: "Change in solubility due to Ficoll 70 (deltaSol_F)",
        },
        y: {
          type: "quantitative",
          field: "deltaSol_D",
          title: "Change in solubility due to dextran 70 (deltaSol_D)",
        },
      },
      height: 300,
      mark: "point",
      selection: {
        brush: {
          type: "interval",
        },
      },
      title: "Effects of Ficoll 70 and Dextran 70 on Protein Solubility",
      width: 1200,
    },
    {
      hconcat: [
        {
          encoding: {
            color: {
              type: "quantitative",
              field: "Total aa",
              title: "Total number of amino acids",
            },
            tooltip: [
              {
                type: "quantitative",
                field: "Sol_noMCR",
              },
              {
                type: "quantitative",
                field: "MW (kDa)",
              },
              {
                type: "quantitative",
                field: "Total aa",
              },
            ],
            x: {
              type: "quantitative",
              field: "Sol_noMCR",
              title: "Solubility in the absence of MCRs (Sol_noMCR)",
            },
            y: {
              type: "quantitative",
              field: "MW (kDa)",
              title: "Molecular weight (MW (kDa))",
            },
          },
          height: 300,
          mark: "point",
          selection: {
            brush: {
              type: "interval",
            },
          },
          title: "Protein Solubility vs. Molecular Weight in Absence of MCRs",
          width: 600,
        },
        {
          encoding: {
            color: {
              type: "quantitative",
              field: "MW (kDa)",
              title: "Molecular weight (MW (kDa))",
            },
            tooltip: [
              {
                type: "quantitative",
                field: "deltaSol_D",
              },
              {
                type: "quantitative",
                field: "calculated pI",
              },
              {
                type: "quantitative",
                field: "MW (kDa)",
              },
            ],
            x: {
              type: "quantitative",
              field: "deltaSol_D",
              title: "Change in solubility due to dextran 70 (deltaSol_D)",
            },
            y: {
              type: "quantitative",
              field: "calculated pI",
              title: "Calculated Isoelectric Point (calculated pI)",
            },
          },
          height: 300,
          mark: "point",
          selection: {
            brush: {
              type: "interval",
            },
          },
          title: "Solubility Changes by Dextran 70 vs. Isoelectric Point",
          width: 600,
        },
      ],
    },
    {
      hconcat: [
        {
          encoding: {
            color: {
              type: "quantitative",
              field: "MW (kDa)",
              title: "Molecular weight (MW (kDa))",
            },
            tooltip: [
              {
                type: "quantitative",
                field: "deltaY_F (uM)",
              },
              {
                type: "quantitative",
                field: "deltaY_D (uM)",
              },
              {
                type: "quantitative",
                field: "MW (kDa)",
              },
            ],
            x: {
              type: "quantitative",
              field: "deltaY_F (uM)",
              title:
                "Change in synthetic yield due to Ficoll 70 (deltaY_F (uM))",
            },
            y: {
              type: "quantitative",
              field: "deltaY_D (uM)",
              title:
                "Change in synthetic yield due to dextran 70 (deltaY_D (uM))",
            },
          },
          height: 300,
          mark: "point",
          selection: {
            brush: {
              type: "interval",
            },
          },
          title: "Synthetic Yield Changes by Ficoll 70 and Dextran 70",
          width: 600,
        },
        {
          encoding: {
            color: {
              type: "quantitative",
              field: "calculated pI",
              title: "Calculated Isoelectric Point (calculated pI)",
            },
            tooltip: [
              {
                type: "quantitative",
                field: "Total aa",
              },
              {
                type: "quantitative",
                field: "deltaSol_F",
              },
              {
                type: "quantitative",
                field: "calculated pI",
              },
            ],
            x: {
              type: "quantitative",
              field: "Total aa",
              title: "Total number of amino acids (Total aa)",
            },
            y: {
              type: "quantitative",
              field: "deltaSol_F",
              title: "Change in solubility due to Ficoll 70 (deltaSol_F)",
            },
          },
          height: 300,
          mark: "point",
          selection: {
            brush: {
              type: "interval",
            },
          },
          title: "Total Amino Acids vs. Solubility Change by Ficoll 70",
          width: 600,
        },
      ],
    },
  ],
};

Link to the Dataset

Compiled schema in the Vega Editor

All solutions are welcome!


EDIT:


Here’s the adjusted solution from APB Reports. Unfortunately, it doesn’t fit the criteria. I can make it work by manually adjusting the width and height to fit the container, but that’s not ideal. I’m looking for a solution that dynamically handles all cases.

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <meta http-equiv="refresh" content="3600" />
    <script src="https://cdn.jsdelivr.net/npm/vega@5"></script>
    <script src="https://cdn.jsdelivr.net/npm/vega-lite@5"></script>
    <script src="https://cdn.jsdelivr.net/npm/vega-embed@6"></script>

    <style>
      body {
        background-color: #f0f5fa;
        padding-top: 30px;
        margin: 0px;
        width: 100%;
        height: 100%;
        margin-left: auto;
        margin-right: auto;
        scolling: auto;
      }
      .test {
        width: 800px;
        height: 800px;
        border: 1px dashed red;
        border-radius: 13px;
        overflow: hidden;
      }
    </style>
  </head>
  <body>
    <div class="test" id="test">
      <div class="vega-container" id="vis1"></div>
    </div>

    <script id="jsCode" type="text/javascript">
      const vegaWrapper = document.querySelector("#test");
      var pageWidthBody = vegaWrapper.clientWidth;
      var pageWidthBodyMinusx = pageWidthBody - 200;
      var PageWidth = pageWidthBodyMinusx;
      console.log(PageWidth);

      var pageHeightBody = vegaWrapper.clientHeight;
      var pageHeightBodyMinusx = (pageHeightBody - 50) / 2;
      var PageHeight = pageHeightBodyMinusx;
      console.log(PageHeight);

      var V1Spec = {
        $schema: "https://vega.github.io/schema/vega-lite/v5.json",
        description: "A dashboard with cross-highlighting.",
        data: {
          url: "https://gist.githubusercontent.com/letelete/4b88fcdb37f0ade26e92687c1de8c1ae/raw/1402aa849e584e008868256e4c7b085fbac6294f/raw_data.json",
        },
        vconcat: [
          {
            encoding: {
              color: {
                type: "quantitative",
                field: "calculated pI",
                title: "Calculated Isoelectric Point",
              },
              tooltip: [
                {
                  type: "quantitative",
                  field: "deltaSol_F",
                },
                {
                  type: "quantitative",
                  field: "deltaSol_D",
                },
                {
                  type: "quantitative",
                  field: "calculated pI",
                },
              ],
              x: {
                type: "quantitative",
                field: "deltaSol_F",
                title: "Change in solubility due to Ficoll 70 (deltaSol_F)",
              },
              y: {
                type: "quantitative",
                field: "deltaSol_D",
                title: "Change in solubility due to dextran 70 (deltaSol_D)",
              },
            },
            height: PageHeight,
            width: PageWidth,
            mark: "point",
            selection: {
              brush: {
                type: "interval",
              },
            },
            title: "Effects of Ficoll 70 and Dextran 70 on Protein Solubility",
          },
          {
            hconcat: [
              {
                encoding: {
                  color: {
                    type: "quantitative",
                    field: "Total aa",
                    title: "Total number of amino acids",
                  },
                  tooltip: [
                    {
                      type: "quantitative",
                      field: "Sol_noMCR",
                    },
                    {
                      type: "quantitative",
                      field: "MW (kDa)",
                    },
                    {
                      type: "quantitative",
                      field: "Total aa",
                    },
                  ],
                  x: {
                    type: "quantitative",
                    field: "Sol_noMCR",
                    title: "Solubility in the absence of MCRs (Sol_noMCR)",
                  },
                  y: {
                    type: "quantitative",
                    field: "MW (kDa)",
                    title: "Molecular weight (MW (kDa))",
                  },
                },
                mark: "point",
                selection: {
                  brush: {
                    type: "interval",
                  },
                },
                title:
                  "Protein Solubility vs. Molecular Weight in Absence of MCRs",
              },
              {
                encoding: {
                  color: {
                    type: "quantitative",
                    field: "MW (kDa)",
                    title: "Molecular weight (MW (kDa))",
                  },
                  tooltip: [
                    {
                      type: "quantitative",
                      field: "deltaSol_D",
                    },
                    {
                      type: "quantitative",
                      field: "calculated pI",
                    },
                    {
                      type: "quantitative",
                      field: "MW (kDa)",
                    },
                  ],
                  x: {
                    type: "quantitative",
                    field: "deltaSol_D",
                    title:
                      "Change in solubility due to dextran 70 (deltaSol_D)",
                  },
                  y: {
                    type: "quantitative",
                    field: "calculated pI",
                    title: "Calculated Isoelectric Point (calculated pI)",
                  },
                },
                mark: "point",
                selection: {
                  brush: {
                    type: "interval",
                  },
                },
                title: "Solubility Changes by Dextran 70 vs. Isoelectric Point",
              },
            ],
          },
          {
            hconcat: [
              {
                encoding: {
                  color: {
                    type: "quantitative",
                    field: "MW (kDa)",
                    title: "Molecular weight (MW (kDa))",
                  },
                  tooltip: [
                    {
                      type: "quantitative",
                      field: "deltaY_F (uM)",
                    },
                    {
                      type: "quantitative",
                      field: "deltaY_D (uM)",
                    },
                    {
                      type: "quantitative",
                      field: "MW (kDa)",
                    },
                  ],
                  x: {
                    type: "quantitative",
                    field: "deltaY_F (uM)",
                    title:
                      "Change in synthetic yield due to Ficoll 70 (deltaY_F (uM))",
                  },
                  y: {
                    type: "quantitative",
                    field: "deltaY_D (uM)",
                    title:
                      "Change in synthetic yield due to dextran 70 (deltaY_D (uM))",
                  },
                },
                mark: "point",
                selection: {
                  brush: {
                    type: "interval",
                  },
                },
                title: "Synthetic Yield Changes by Ficoll 70 and Dextran 70",
              },
              {
                encoding: {
                  color: {
                    type: "quantitative",
                    field: "calculated pI",
                    title: "Calculated Isoelectric Point (calculated pI)",
                  },
                  tooltip: [
                    {
                      type: "quantitative",
                      field: "Total aa",
                    },
                    {
                      type: "quantitative",
                      field: "deltaSol_F",
                    },
                    {
                      type: "quantitative",
                      field: "calculated pI",
                    },
                  ],
                  x: {
                    type: "quantitative",
                    field: "Total aa",
                    title: "Total number of amino acids (Total aa)",
                  },
                  y: {
                    type: "quantitative",
                    field: "deltaSol_F",
                    title: "Change in solubility due to Ficoll 70 (deltaSol_F)",
                  },
                },
                mark: "point",
                selection: {
                  brush: {
                    type: "interval",
                  },
                },
                title: "Total Amino Acids vs. Solubility Change by Ficoll 70",
              },
            ],
          },
        ],
      };
      vegaEmbed("#vis1", V1Spec, { actions: false, renderer: "svg" });
    </script>
  </body>
</html>

2

Answers


  1. Chosen as BEST ANSWER

    Another solution that comes to mind is to apply transform: scale(<scaleOffset>) to the vega-lite container. The scaleOffset would be calculated based on the initial size of the vega-lite visualization, and the vega-lite container's size. As long as this works as expected, the interactive brush no longer works correctly. It has an offset that makes a visualization difficult to interact with.

    Interactive brush offset when scaled using transform

    <!DOCTYPE html>
    <html>
      <head>
        <meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
        <meta http-equiv="refresh" content="3600" />
        <script src="https://cdn.jsdelivr.net/npm/vega@5"></script>
        <script src="https://cdn.jsdelivr.net/npm/vega-lite@5"></script>
        <script src="https://cdn.jsdelivr.net/npm/vega-embed@6"></script>
    
        <style>
          body {
            background-color: #f0f5fa;
            padding-top: 30px;
            margin: 0px;
            width: 100%;
            height: 100%;
            margin-left: auto;
            margin-right: auto;
            overflow: auto;
          }
          .test {
            width: 100%;
            height: 100%;
            max-width: 800px;
            max-height: 800px;
            border: 1px dashed red;
            border-radius: 13px;
            overflow: hidden;
            margin: auto;
          }
          .vega-container {
            /* scale down to fit the container */
            /* todo: calculate the scale factor based on the container size */
            transform: scale(0.5) translateX(-50%) translateY(-50%);
          }
        </style>
      </head>
      <body>
        <div class="test" id="test">
          <div class="vega-container" id="vis1"></div>
        </div>
    
        <script id="jsCode" type="text/javascript">
          const vegaWrapper = document.querySelector("#test");
          const visContainer = document.querySelector("#vis1");
    
          function resizeChart() {
            const pageWidth = vegaWrapper.clientWidth;
            const pageHeight = vegaWrapper.clientHeight;
    
            const spec = {
              $schema: "https://vega.github.io/schema/vega-lite/v5.json",
              description: "A dashboard with cross-highlighting.",
              data: {
                url: "https://gist.githubusercontent.com/letelete/4b88fcdb37f0ade26e92687c1de8c1ae/raw/1402aa849e584e008868256e4c7b085fbac6294f/raw_data.json",
              },
              vconcat: [
                {
                  height: pageHeight,
                  width: pageWidth,
                  encoding: {
                    color: {
                      type: "quantitative",
                      field: "calculated pI",
                      title: "Calculated Isoelectric Point",
                    },
                    tooltip: [
                      { type: "quantitative", field: "deltaSol_F" },
                      { type: "quantitative", field: "deltaSol_D" },
                      { type: "quantitative", field: "calculated pI" },
                    ],
                    x: {
                      type: "quantitative",
                      field: "deltaSol_F",
                      title: "Change in solubility due to Ficoll 70 (deltaSol_F)",
                    },
                    y: {
                      type: "quantitative",
                      field: "deltaSol_D",
                      title: "Change in solubility due to dextran 70 (deltaSol_D)",
                    },
                  },
                  mark: "point",
                  selection: {
                    brush: {
                      type: "interval",
                    },
                  },
                  title:
                    "Effects of Ficoll 70 and Dextran 70 on Protein Solubility",
                },
                {
                  hconcat: [
                    {
                      encoding: {
                        color: {
                          type: "quantitative",
                          field: "Total aa",
                          title: "Total number of amino acids",
                        },
                        tooltip: [
                          { type: "quantitative", field: "Sol_noMCR" },
                          { type: "quantitative", field: "MW (kDa)" },
                          { type: "quantitative", field: "Total aa" },
                        ],
                        x: {
                          type: "quantitative",
                          field: "Sol_noMCR",
                          title: "Solubility in the absence of MCRs (Sol_noMCR)",
                        },
                        y: {
                          type: "quantitative",
                          field: "MW (kDa)",
                          title: "Molecular weight (MW (kDa))",
                        },
                      },
                      mark: "point",
                      selection: {
                        brush: {
                          type: "interval",
                        },
                      },
                      title:
                        "Protein Solubility vs. Molecular Weight in Absence of MCRs",
                    },
                    {
                      encoding: {
                        color: {
                          type: "quantitative",
                          field: "MW (kDa)",
                          title: "Molecular weight (MW (kDa))",
                        },
                        tooltip: [
                          { type: "quantitative", field: "deltaSol_D" },
                          { type: "quantitative", field: "calculated pI" },
                          { type: "quantitative", field: "MW (kDa)" },
                        ],
                        x: {
                          type: "quantitative",
                          field: "deltaSol_D",
                          title:
                            "Change in solubility due to dextran 70 (deltaSol_D)",
                        },
                        y: {
                          type: "quantitative",
                          field: "calculated pI",
                          title: "Calculated Isoelectric Point (calculated pI)",
                        },
                      },
                      mark: "point",
                      selection: {
                        brush: {
                          type: "interval",
                        },
                      },
                      title:
                        "Solubility Changes by Dextran 70 vs. Isoelectric Point",
                    },
                  ],
                },
                {
                  hconcat: [
                    {
                      encoding: {
                        color: {
                          type: "quantitative",
                          field: "MW (kDa)",
                          title: "Molecular weight (MW (kDa))",
                        },
                        tooltip: [
                          { type: "quantitative", field: "deltaY_F (uM)" },
                          { type: "quantitative", field: "deltaY_D (uM)" },
                          { type: "quantitative", field: "MW (kDa)" },
                        ],
                        x: {
                          type: "quantitative",
                          field: "deltaY_F (uM)",
                          title:
                            "Change in synthetic yield due to Ficoll 70 (deltaY_F (uM))",
                        },
                        y: {
                          type: "quantitative",
                          field: "deltaY_D (uM)",
                          title:
                            "Change in synthetic yield due to dextran 70 (deltaY_D (uM))",
                        },
                      },
                      mark: "point",
                      selection: {
                        brush: {
                          type: "interval",
                        },
                      },
                      title: "Synthetic Yield Changes by Ficoll 70 and Dextran 70",
                    },
                    {
                      encoding: {
                        color: {
                          type: "quantitative",
                          field: "calculated pI",
                          title: "Calculated Isoelectric Point (calculated pI)",
                        },
                        tooltip: [
                          { type: "quantitative", field: "Total aa" },
                          { type: "quantitative", field: "deltaSol_F" },
                          { type: "quantitative", field: "calculated pI" },
                        ],
                        x: {
                          type: "quantitative",
                          field: "Total aa",
                          title: "Total number of amino acids (Total aa)",
                        },
                        y: {
                          type: "quantitative",
                          field: "deltaSol_F",
                          title:
                            "Change in solubility due to Ficoll 70 (deltaSol_F)",
                        },
                      },
                      mark: "point",
                      selection: {
                        brush: {
                          type: "interval",
                        },
                      },
                      title: "Total Amino Acids vs. Solubility Change by Ficoll 70",
                    },
                  ],
                },
              ],
            };
    
            vegaEmbed("#vis1", spec, { actions: false, renderer: "svg" });
          }
    
          window.addEventListener("resize", resizeChart);
          document.addEventListener("DOMContentLoaded", resizeChart);
        </script>
      </body>
    </html>


  2. Is it a possibility to calculate the div or page width and then insert this value into the spec like this? I do that quite often with success. You could update this automatically after a page resize.

    <!doctype html> 
    <html> 
    <head>
    <meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1"> 
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">  
    <meta http-equiv="refresh" content="3600">
    <script src="../../../js/js_vega/20240503/[email protected]"></script>
    <script src="../../../js/js_vega/20240503/[email protected]"></script>
    <script src="../../../js/js_vega/20240503/[email protected]"></script>
    <script src="movies.json"></script>
    <style> 
    body {
    background-color: #F0F5FA;
    padding-top: 30px;
    margin: 0px;
    width: 100%;
    height: 100%;
    margin-left: auto;
    margin-right: auto;
    scolling: auto;
    }
    .test
    {
    width: 100%;
    height: 800px;
    }
    
    </style> 
    </head>      
    <body>
    <div class=test id=test>
    <div class="vega-container" id="vis1"></div>
    </div>
    </body>
    
    <script id="jsCode" type="text/javascript"> 
    var pageWidthBody = document.body.clientWidth;
    var pageWidthBodyMinusx = pageWidthBody - 200;
    var PageWidth = pageWidthBodyMinusx;
    console.log(PageWidth);
    
    var pageHeightBody = window.innerHeight;
    var pageHeightBodyMinusx = (pageHeightBody - 250)/2;
    var PageHeight = pageHeightBodyMinusx;
    console.log(PageHeight);
    
    var V1Spec = {
    "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
    "description": "A dashboard with cross-highlighting.",
    "data": {"values": movies},
    "vconcat": [
    {
    "width": PageWidth,
    "height": PageHeight,
    "layer": [{
    "mark": "rect",
    "encoding": {
    "x": {
    "bin": {"maxbins": 10},
    "field": "IMDB Rating"
    },
    "y": {
    "bin": {"maxbins": 10},
    "field": "Rotten Tomatoes Rating"
    },
    "color": {
    "aggregate": "count",
    "legend": {
    "title": "All Movies Count",
    "direction": "horizontal",
    "gradientLength": 120
    }
    }
    }
    }, {
    "transform": [{
    "filter": {"param": "pts"}
    }],
    "mark": "point",
    "encoding": {
    "x": {
    "bin": {"maxbins": 10},
    "field": "IMDB Rating"
    },
    "y": {
    "bin": {"maxbins": 10},
    "field": "Rotten Tomatoes Rating"
    },
    "size": {
    "aggregate": "count",
    "legend": {"title": "Selected Category Count"}
    },
    "color": {
    "value": "#666"
    }
    }
    }]
    }, 
    {
    "width": PageWidth,
    "height": PageHeight,
    "mark": "bar",
    "params": [{
    "name": "pts",
    "select": {"type": "point", "encodings": ["x"]}
    }],
    "encoding": {
    "x": {"field": "Major Genre", "axis": {"labelAngle": -40}},
    "y": {"aggregate": "count"},
    "color": {
    "condition": {
    "param": "pts",
    "value": "steelblue"
    },
    "value": "grey"
    }
    }
    }
    ],
    "resolve": {
    "legend": {
    "color": "independent",
    "size": "independent"
    }
    }
    };
    vegaEmbed('#vis1', V1Spec, {"actions": false,renderer: "svg"});
    </script>
    </body>
    </html>
    
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search