{"spec_id":"area-elevation-profile","library":"echarts","language":"javascript","code":"// anyplot.ai\n// area-elevation-profile: Terrain Elevation Profile Along Transect\n// Library: echarts 5.5.1 | JavaScript 22.22.3\n// Quality: 88/100 | Created: 2026-06-10\n\n//# anyplot-orientation: landscape\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data -------------------------------------------------------------------\n// Control points [distance_km, elevation_m] — deterministic Alpine traverse\nconst ctrl = [\n  [0, 780], [5, 1150], [10, 1820], [13, 2280], [17, 1450],\n  [21, 1320], [25, 1680], [30, 2050], [36, 2840], [40, 2450],\n  [44, 2190], [48, 2380], [52, 2560], [57, 1940], [62, 1480],\n  [66, 1100], [70, 900],  [74, 780],  [80, 650]\n];\n\n// 161 profile points at 0.5 km intervals: linear interp + micro-terrain texture\nconst profileData = [];\nfor (let i = 0; i <= 160; i++) {\n  const d = i * 0.5;\n  let base = ctrl[ctrl.length - 1][1];\n  for (let j = 0; j < ctrl.length - 1; j++) {\n    if (d >= ctrl[j][0] && d <= ctrl[j + 1][0]) {\n      const frac = (d - ctrl[j][0]) / (ctrl[j + 1][0] - ctrl[j][0]);\n      base = ctrl[j][1] + frac * (ctrl[j + 1][1] - ctrl[j][1]);\n      break;\n    }\n  }\n  // Superimposed sinusoids add deterministic micro-terrain texture\n  const tex = 32 * Math.sin(d * 1.8 + 0.4) + 18 * Math.sin(d * 4.7 + 1.1)\n            +  9 * Math.sin(d * 10.3 + 2.3) +  5 * Math.sin(d * 19.1);\n  profileData.push([d, Math.round(base + tex)]);\n}\n\n// Key landmarks along the traverse\nconst landmarks = [\n  { name: 'Northern Pass · 2280 m',  dist: 13 },\n  { name: 'Valley Village · 1320 m', dist: 21 },\n  { name: 'Main Summit · 2840 m',    dist: 36 },\n  { name: 'Plateau Hut · 2190 m',    dist: 44 },\n  { name: 'Eastern Pass · 2560 m',   dist: 52 },\n  { name: 'River Crossing · 900 m',  dist: 70 },\n];\n\n// --- Init -------------------------------------------------------------------\nconst chart = echarts.init(document.getElementById('container'));\n\n// Terrain silhouette fill — Imprint green fading to transparent\nconst areaFill = {\n  type: 'linear', x: 0, y: 0, x2: 0, y2: 1,\n  colorStops: [\n    { offset: 0, color: 'rgba(0,158,115,0.55)' },\n    { offset: 1, color: 'rgba(0,158,115,0.04)' }\n  ]\n};\n\n// Scale title font for long string (default 22 px, floor 13 px)\nconst titleStr = 'Alpine Mountain Traverse · area-elevation-profile · javascript · echarts · anyplot.ai';\nconst titleSize = Math.max(13, Math.round(22 * 67 / titleStr.length));\n\n// --- Option -----------------------------------------------------------------\nchart.setOption({\n  animation: false,\n  color: t.palette,\n  backgroundColor: 'transparent',\n\n  title: {\n    text: titleStr,\n    subtext: '~16× vertical exaggeration',\n    subtextStyle: { color: t.inkSoft, fontSize: 12 },\n    left: 'center',\n    top: 18,\n    textStyle: { color: t.ink, fontSize: titleSize, fontWeight: '500' }\n  },\n\n  grid: { left: 110, right: 55, top: 100, bottom: 90 },\n\n  xAxis: {\n    type: 'value',\n    min: 0,\n    max: 80,\n    name: 'Distance (km)',\n    nameLocation: 'middle',\n    nameGap: 50,\n    nameTextStyle: { color: t.inkSoft, fontSize: 14 },\n    axisLabel: { color: t.inkSoft, fontSize: 13, formatter: '{value} km' },\n    axisLine: { lineStyle: { color: t.inkSoft } },\n    axisTick: { lineStyle: { color: t.inkSoft } },\n    splitLine: { show: false }\n  },\n\n  yAxis: {\n    type: 'value',\n    min: 400,\n    name: 'Elevation (m)',\n    nameLocation: 'middle',\n    nameGap: 72,\n    nameTextStyle: { color: t.inkSoft, fontSize: 14 },\n    axisLabel: { color: t.inkSoft, fontSize: 13, formatter: '{value} m' },\n    axisLine: { show: false },\n    axisTick: { show: false },\n    splitLine: { lineStyle: { color: t.grid } }\n  },\n\n  series: [\n    // Main elevation profile: filled terrain silhouette + annotated landmarks\n    {\n      type: 'line',\n      data: profileData,\n      smooth: 0.3,\n      symbol: 'none',\n      lineStyle: { color: t.palette[0], width: 2.5 },\n      areaStyle: { color: areaFill },\n      // Vertical dashed lines at landmark positions\n      markLine: {\n        silent: true,\n        symbol: ['none', 'none'],\n        lineStyle: { color: t.inkSoft, type: 'dashed', width: 1.3, opacity: 0.6 },\n        label: { show: false },\n        data: landmarks.map(lm => [\n          { coord: [lm.dist, 420] },\n          { coord: [lm.dist, profileData[Math.min(Math.round(lm.dist / 0.5), 160)][1] - 40] }\n        ])\n      }\n    },\n    // Landmark dots with labels above the profile line\n    {\n      type: 'scatter',\n      data: landmarks.map(lm => ({\n        name: lm.name,\n        value: [lm.dist, profileData[Math.min(Math.round(lm.dist / 0.5), 160)][1] + 80]\n      })),\n      symbol: 'circle',\n      symbolSize: 5,\n      itemStyle: { color: t.inkSoft, opacity: 0.7 },\n      label: {\n        show: true,\n        position: 'top',\n        formatter: '{b}',\n        color: t.ink,\n        fontSize: 13\n      },\n      z: 10\n    },\n    // Trailhead start marker\n    {\n      type: 'scatter',\n      data: [[0, profileData[0][1]]],\n      symbol: 'circle',\n      symbolSize: 12,\n      itemStyle: { color: t.palette[0], borderColor: t.ink, borderWidth: 2 },\n      label: {\n        show: true,\n        position: 'right',\n        formatter: 'Trailhead · 780 m',\n        color: t.ink,\n        fontSize: 12\n      },\n      z: 10\n    },\n    // Mountain Town end marker\n    {\n      type: 'scatter',\n      data: [[80, profileData[160][1]]],\n      symbol: 'circle',\n      symbolSize: 12,\n      itemStyle: { color: t.palette[0], borderColor: t.ink, borderWidth: 2 },\n      label: {\n        show: true,\n        position: 'left',\n        formatter: 'Mountain Town · 650 m',\n        color: t.ink,\n        fontSize: 12\n      },\n      z: 10\n    }\n  ]\n});\n"}