Mountain Panorama Profile with Labeled Peaks — Apache ECharts

A panoramic mountain silhouette chart that renders the horizon as seen from a fixed vantage point, like a photograph of a ridgeline against the sky. A filled area under the skyline curve traces the ridgeline across a horizontal viewing range (in degrees of bearing or horizontal distance), and major summits are annotated with their name and elevation. The skyline is jagged and angular — sharp triangular peaks with steep, often asymmetric flanks meeting at pointed apexes, connected by rugged ridges with cols, sub-peaks and rocky notches — not a sequence of smooth bell-shaped bumps. Unlike an elevation-profile-along-a-trail, this plot is the angular view of the surrounding peaks from a single observer, making it ideal for summit-identification infographics, alpine panoramas, and travel guides.

Mountain Panorama Profile with Labeled Peaks rendered with Apache ECharts

Renders

JavaScript source (Apache ECharts)

// anyplot.ai
// area-mountain-panorama: Mountain Panorama Profile with Labeled Peaks
// Library: echarts 5.5.1 | JavaScript 22.23.0
// Quality: 91/100 | Created: 2026-06-30

const t = window.ANYPLOT_TOKENS;
const THEME = window.ANYPLOT_THEME || 'light';

// Wallis (Valais) panorama from Zermatt — Weisshorn to Rimpfischhorn
// peaks: [bearing_deg, elevation_m, name]
const peaks = [
  [6,   4506, "Weisshorn"],
  [16,  4221, "Zinalrothorn"],
  [24,  4063, "Ober Gabelhorn"],
  [31,  4358, "Dent Blanche"],
  [43,  4478, "Matterhorn"],
  [56,  4164, "Breithorn"],
  [63,  4092, "Pollux"],
  [68,  4223, "Castor"],
  [76,  4527, "Liskamm"],
  [86,  4634, "Dufourspitze"],
  [93,  4190, "Strahlhorn"],
  [98,  4199, "Rimpfischhorn"],
];
const MATTERHORN_IDX = 4;

// Piecewise-linear ridgeline — sharp triangular peaks with inter-summit jaggedness
const ridgePoints = [
  [0, 3050], [1, 3150], [2, 3250], [2.5, 3420], [3.5, 3600], [4, 3800], [5, 4100],
  [6, 4506],
  [7, 4150], [7.5, 4000], [8, 3800], [8.8, 3650], [9.5, 3420], [10, 3480], [11, 3520],
  [11.8, 3620], [12.5, 3700], [13, 3750], [13.8, 3900], [14.5, 4000], [15, 4080], [15.5, 4150],
  [16, 4221],
  [16.8, 4050], [17, 3900], [17.8, 3700], [18.5, 3420], [19, 3350], [19.5, 3280],
  [20, 3320], [20.8, 3420], [21, 3550], [21.5, 3650], [22.5, 3820], [23, 3940],
  [24, 4063],
  [24.8, 3900], [25, 3720], [25.8, 3580], [26, 3300], [26.8, 3180], [27, 3080],
  [27.5, 3200], [28, 3320], [28.5, 3450], [29, 3700], [29.5, 3900], [30, 4000], [30.5, 4150],
  [31, 4358],
  [31.5, 4200], [32, 4050], [32.8, 3800], [33.5, 3450], [34, 3280], [35, 2980],
  [35.8, 2900], [36.5, 2850], [37, 2870], [37.8, 2920], [38.5, 3000], [39, 3220], [39.5, 3380],
  [40, 3500], [40.8, 3650], [41.5, 3950], [42, 4150], [42.5, 4350],
  [43, 4478],
  [43.5, 4200], [44, 3900], [44.8, 3600], [45, 3700], [45.8, 3500], [46.5, 3150],
  [47, 3080], [47.8, 2980], [48, 2950],
  [48.8, 2980], [49.5, 3000], [50, 3000], [50.8, 3120], [51.5, 3200], [52, 3300],
  [52.8, 3500], [53.5, 3650], [54, 3800], [54.8, 3920], [55.5, 4050],
  [56, 4164],
  [56.8, 4050], [57.5, 3900], [58, 3800], [58.8, 3700], [59, 3500],
  [59.8, 3480], [60.5, 3480], [61, 3550], [61.8, 3650], [62, 3780],
  [63, 4092],
  [63.5, 3960], [64, 3850], [64.8, 3780], [65, 3750],
  [65.8, 3800], [66.5, 3900], [67, 3980], [67.5, 4050],
  [68, 4223],
  [68.5, 4010], [69, 3850], [69.8, 3750], [70, 3650], [70.8, 3700], [71.5, 3750],
  [72, 3800], [72.8, 3920], [73.5, 4050], [74, 4180], [74.8, 4300], [75, 4350],
  [76, 4527],
  [76.8, 4380], [77, 4280], [77.8, 4150], [78.5, 3900], [79, 3780], [79.8, 3700],
  [80, 3650], [80.8, 3800], [81.5, 3950], [82, 4000], [82.8, 4150], [83.5, 4200], [84.5, 4300],
  [85, 4420], [85.5, 4500],
  [86, 4634],
  [86.8, 4480], [87, 4380], [87.8, 4250], [88.5, 4100], [89, 3980], [89.8, 3880],
  [90, 3750], [90.8, 3800], [91.5, 3850], [92, 3920], [92.5, 4000],
  [93, 4190],
  [93.8, 4050], [94, 3950], [94.8, 3850], [95.5, 3720], [96, 3760], [96.5, 3800],
  [97, 3900], [97.5, 4030],
  [98, 4199],
  [98.8, 4000], [99, 3880],
  [99.8, 3750], [100.5, 3600], [101, 3450], [101.8, 3300], [102.5, 3200], [103, 3100],
  [103.8, 3020], [104.5, 2960], [105, 2900],
];

// Sky gradient — Imprint blue (#4467A3, palette[2]) layered as background series
const skyTopColor = THEME === 'dark' ? 'rgba(68,103,163,0.75)' : 'rgba(68,103,163,0.32)';
const skyMidColor = THEME === 'dark' ? 'rgba(68,103,163,0.30)' : 'rgba(68,103,163,0.08)';

// Mountain silhouette — theme-adaptive ink tokens (no custom hex values)
const fillColor = t.ink;
const ridgeColor = t.inkSoft;

// Imprint palette position 1 — highlight the focal Matterhorn peak
const BRAND = t.palette[0]; // #009E73

const titleText = "Alpine Panorama · area-mountain-panorama · javascript · echarts · anyplot.ai";
const titleFontSize = Math.max(14, Math.round(22 * Math.min(1.0, 67 / titleText.length)));

const chart = echarts.init(document.getElementById("container"));

chart.setOption({
  animation: false,
  color: t.palette,
  backgroundColor: t.pageBg,
  title: {
    text: titleText,
    left: 'center',
    top: 18,
    textStyle: { color: t.ink, fontSize: titleFontSize, fontWeight: 'normal' },
  },
  grid: {
    left: 95,
    right: 50,
    top: 230,
    bottom: 65,
  },
  xAxis: {
    type: 'value',
    min: 0,
    max: 105,
    show: false,
  },
  yAxis: {
    type: 'value',
    min: 2600,
    max: 4900,
    name: 'Elevation (m)',
    nameLocation: 'middle',
    nameGap: 60,
    nameTextStyle: { color: t.inkSoft, fontSize: 14 },
    axisLabel: {
      color: t.inkSoft,
      fontSize: 13,
      formatter: (v) => `${v} m`,
    },
    axisLine: { show: false },
    axisTick: { show: false },
    splitLine: { lineStyle: { color: t.grid, width: 1 } },
  },
  series: [
    {
      // Sky gradient — Imprint blue layered as background series behind mountain
      type: 'line',
      data: [[0, 4900], [105, 4900]],
      smooth: false,
      symbol: 'none',
      lineStyle: { width: 0, opacity: 0 },
      areaStyle: {
        color: {
          type: 'linear', x: 0, y: 0, x2: 0, y2: 1,
          colorStops: [
            { offset: 0,    color: skyTopColor },
            { offset: 0.55, color: skyMidColor },
            { offset: 1,    color: 'rgba(68,103,163,0)' },
          ],
        },
        opacity: 1,
      },
      z: -1,
    },
    {
      // Mountain silhouette
      type: 'line',
      data: ridgePoints,
      smooth: false,
      symbol: 'none',
      lineStyle: { color: ridgeColor, width: 1.5 },
      areaStyle: {
        color: fillColor,
        opacity: 0.95,
      },
      z: 0,
    },
  ],
});

// Peak annotations: staggered leader lines + two-line labels (name + elevation)
// Wider xShifts for dense clusters (Pollux/Castor, Strahlhorn/Rimpfischhorn)
const yOffsets = [110,  75, 115,  80, 145,  75,  95,  60, 105, 130,  65,  92];
const xShifts  = [  0,   0,   0,   0,   0,   0, -18, +18,   0,   0, -18, +18];

const graphics = [];
peaks.forEach(([angle, elev, name], i) => {
  const result = chart.convertToPixel('grid', [angle, elev]);
  if (!result) return;
  const [px, py] = result;

  const ly = py - yOffsets[i];
  const lx = px + xShifts[i];
  const isMH = (i === MATTERHORN_IDX);

  const dotColor     = isMH ? BRAND : t.inkSoft;
  const lineStroke   = isMH ? BRAND : t.inkSoft;
  const dotR         = isMH ? 5 : 3;
  const nameFill     = isMH ? BRAND : t.ink;
  const nameFontSize = isMH ? 15 : 13;
  const lineWidth    = isMH ? 1.5 : 1;

  // Leader line: from just above summit dot to just below elevation label
  graphics.push({
    type: 'line',
    z: 20,
    shape: { x1: px, y1: py - dotR - 1, x2: lx, y2: ly + 16 },
    style: { stroke: lineStroke, lineWidth, opacity: 0.7 },
  });

  // Summit dot
  graphics.push({
    type: 'circle',
    z: 20,
    shape: { cx: px, cy: py - dotR, r: dotR },
    style: { fill: dotColor, stroke: 'none' },
  });

  // Peak name (bold, baseline at ly)
  graphics.push({
    type: 'text',
    z: 20,
    x: lx,
    y: ly,
    style: {
      text: name,
      textAlign: 'center',
      textBaseline: 'bottom',
      fill: nameFill,
      fontSize: nameFontSize,
      fontWeight: 'bold',
    },
  });

  // Elevation — 14px gap below name baseline for breathing room
  graphics.push({
    type: 'text',
    z: 20,
    x: lx,
    y: ly + 14,
    style: {
      text: `${elev} m`,
      textAlign: 'center',
      textBaseline: 'top',
      fill: t.inkSoft,
      fontSize: 11,
    },
  });
});

chart.setOption({ graphic: graphics });

Part of Mountain Panorama Profile with Labeled Peaks on anyplot.ai.

Other implementations