diff --git a/functions/README.md b/functions/README.md
index f5402687d66..bf039c79701 100644
--- a/functions/README.md
+++ b/functions/README.md
@@ -232,13 +232,14 @@ All of the below options can be given as query parameters, e.g. `?imType=og&noca
imType |
twitter or og (short for
- Open Graph)
+ Open Graph) or social-media-square
|
If present, will use fitting defaults for the generated image size:
twitter : 800x418
og : 1200x628
+ social-media-square : 2160x2160, customizable using imSquareSize=[number]
All below options will be ignored if imType is set to one of these values.
|
diff --git a/functions/_common/grapherRenderer.ts b/functions/_common/grapherRenderer.ts
index 784c32607e5..7dd979a085a 100644
--- a/functions/_common/grapherRenderer.ts
+++ b/functions/_common/grapherRenderer.ts
@@ -82,7 +82,8 @@ async function fetchAndRenderGrapherToSvg(
const svg = grapher.generateStaticSvg()
grapherLogger.log("generateStaticSvg")
- return svg
+
+ return { svg, backgroundColor: grapher.backgroundColor }
}
export const fetchAndRenderGrapher = async (
@@ -94,12 +95,17 @@ export const fetchAndRenderGrapher = async (
const options = extractOptions(searchParams)
console.log("Rendering", id.id, outType, options)
- const svg = await fetchAndRenderGrapherToSvg(id, options, searchParams, env)
+ const { svg, backgroundColor } = await fetchAndRenderGrapherToSvg(
+ id,
+ options,
+ searchParams,
+ env
+ )
console.log("fetched svg")
switch (outType) {
case "png":
- return png(await renderSvgToPng(svg, options))
+ return png(await renderSvgToPng(svg, options, backgroundColor))
case "svg":
return new Response(svg, {
headers: {
@@ -111,7 +117,11 @@ export const fetchAndRenderGrapher = async (
let initialized = false
-export async function renderSvgToPng(svg: string, options: ImageOptions) {
+export async function renderSvgToPng(
+ svg: string,
+ options: ImageOptions,
+ backgroundColor: string
+) {
if (!initialized) {
await initializeSvg2Png(svg2png_wasm)
initialized = true
@@ -123,7 +133,7 @@ export async function renderSvgToPng(svg: string, options: ImageOptions) {
// if we include details, pngHeight is only the height of the chart, but we also have an "appendix" at the bottom that we want to include
height: options.details ? undefined : options.pngHeight,
- backgroundColor: "#fff",
+ backgroundColor,
fonts: [LatoRegular, LatoMedium, LatoBold, PlayfairSemiBold].map(
(f) => new Uint8Array(f)
),
diff --git a/functions/_common/grapherTools.ts b/functions/_common/grapherTools.ts
index 990391ce476..51bedac65db 100644
--- a/functions/_common/grapherTools.ts
+++ b/functions/_common/grapherTools.ts
@@ -144,7 +144,9 @@ export async function initGrapher(
bounds,
staticBounds: bounds,
baseFontSize: options.fontSize,
+ ...options.grapherProps,
})
+ grapher.isExportingToSvgOrPng = true
grapher.shouldIncludeDetailsInStaticExport = options.details
return grapher
diff --git a/functions/_common/imageOptions.ts b/functions/_common/imageOptions.ts
index 4fab7759338..0ccf0b3be43 100644
--- a/functions/_common/imageOptions.ts
+++ b/functions/_common/imageOptions.ts
@@ -1,3 +1,7 @@
+import {
+ GrapherProgrammaticInterface,
+ GRAPHER_SQUARE_SIZE,
+} from "@ourworldindata/grapher"
import {
DEFAULT_ASPECT_RATIO,
MIN_ASPECT_RATIO,
@@ -7,6 +11,7 @@ import {
DEFAULT_WIDTH,
DEFAULT_HEIGHT,
} from "./grapherRenderer.js"
+import { GrapherStaticFormat } from "@ourworldindata/types"
export interface ImageOptions {
pngWidth: number
@@ -14,7 +19,8 @@ export interface ImageOptions {
svgWidth: number
svgHeight: number
details: boolean
- fontSize: number
+ fontSize: number | undefined
+ grapherProps?: Partial
}
export const TWITTER_OPTIONS: ImageOptions = {
// Twitter cards are 1.91:1 in aspect ratio, and 800x418 is the recommended size
@@ -34,12 +40,34 @@ const OPEN_GRAPH_OPTIONS: ImageOptions = {
details: false,
fontSize: 21,
}
-export const extractOptions = (params: URLSearchParams): ImageOptions => {
- const options: Partial = {}
+const SOCIAL_MEDIA_SQUARE_OPTIONS: ImageOptions = {
+ pngWidth: 4 * GRAPHER_SQUARE_SIZE,
+ pngHeight: 4 * GRAPHER_SQUARE_SIZE,
+ svgWidth: GRAPHER_SQUARE_SIZE,
+ svgHeight: GRAPHER_SQUARE_SIZE,
+ details: false,
+ fontSize: undefined,
+ grapherProps: {
+ isSocialMediaExport: true,
+ staticFormat: GrapherStaticFormat.square,
+ },
+}
+export const extractOptions = (params: URLSearchParams): ImageOptions => {
// We have two special images types specified via the `imType` query param:
if (params.get("imType") === "twitter") return TWITTER_OPTIONS
else if (params.get("imType") === "og") return OPEN_GRAPH_OPTIONS
+ else if (params.get("imType") === "social-media-square") {
+ const squareOptions = SOCIAL_MEDIA_SQUARE_OPTIONS
+ if (params.has("imSquareSize")) {
+ const size = parseInt(params.get("imSquareSize")!)
+ squareOptions.pngWidth = size
+ squareOptions.pngHeight = size
+ }
+ return squareOptions
+ }
+
+ const options: Partial = {}
// Otherwise, query params can specify the size to be rendered at; and in addition we're doing a
// bunch of normalization to make sure the image is rendered at a reasonable size and aspect ratio.
diff --git a/packages/@ourworldindata/grapher/src/core/Grapher.tsx b/packages/@ourworldindata/grapher/src/core/Grapher.tsx
index 0243e038ba2..99080b5f556 100644
--- a/packages/@ourworldindata/grapher/src/core/Grapher.tsx
+++ b/packages/@ourworldindata/grapher/src/core/Grapher.tsx
@@ -139,6 +139,7 @@ import {
GRAPHER_FRAME_PADDING_VERTICAL,
latestGrapherConfigSchema,
validChartTypeCombinations,
+ GRAPHER_SQUARE_SIZE,
} from "../core/GrapherConstants"
import { loadVariableDataAndMetadata } from "./loadVariable"
import Cookies from "js-cookie"
@@ -2072,7 +2073,12 @@ export class Grapher
case GrapherStaticFormat.landscape:
return this.defaultBounds
case GrapherStaticFormat.square:
- return new Bounds(0, 0, 540, 540)
+ return new Bounds(
+ 0,
+ 0,
+ GRAPHER_SQUARE_SIZE,
+ GRAPHER_SQUARE_SIZE
+ )
default:
return this.defaultBounds
}
diff --git a/packages/@ourworldindata/grapher/src/core/GrapherConstants.ts b/packages/@ourworldindata/grapher/src/core/GrapherConstants.ts
index fd8bc6d38a5..1485a2658c4 100644
--- a/packages/@ourworldindata/grapher/src/core/GrapherConstants.ts
+++ b/packages/@ourworldindata/grapher/src/core/GrapherConstants.ts
@@ -19,6 +19,8 @@ export const GRAPHER_LOADED_EVENT_NAME = "grapherLoaded"
export const DEFAULT_GRAPHER_WIDTH = 850
export const DEFAULT_GRAPHER_HEIGHT = 600
+export const GRAPHER_SQUARE_SIZE = 540
+
export const GRAPHER_FRAME_PADDING_VERTICAL = 16
export const GRAPHER_FRAME_PADDING_HORIZONTAL = 16
diff --git a/packages/@ourworldindata/grapher/src/index.ts b/packages/@ourworldindata/grapher/src/index.ts
index 81efb82e166..b2476752247 100644
--- a/packages/@ourworldindata/grapher/src/index.ts
+++ b/packages/@ourworldindata/grapher/src/index.ts
@@ -14,6 +14,7 @@ export {
GRAPHER_IS_IN_IFRAME_CLASS,
DEFAULT_GRAPHER_WIDTH,
DEFAULT_GRAPHER_HEIGHT,
+ GRAPHER_SQUARE_SIZE,
STATIC_EXPORT_DETAIL_SPACING,
DEFAULT_GRAPHER_ENTITY_TYPE,
GRAPHER_LOADED_EVENT_NAME,