Files
ncmr-songs/wip/274/274-transect.html
T

341 lines
102 KiB
HTML
Raw Normal View History

2026-09-11 01:06:57 +09:00
<title>274 Transect</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&family=Noto+Sans+JP:wght@400;500;700&display=swap">
<style>
:root{
--paper:#E7ECEE; --panel:#F3F6F7; --ink:#16242C; --ink-2:#42565F; --ink-3:#6E828C;
--rule:#C0CCD2; --rule-2:#D6DFE3;
--road:#2E4A5A; --ochre:#A9631A; --water:#2F7E9E;
--bridge:#116B62; --tunnel:#3A4650; --shed:#7A5AA6; --place:#8A6D1F; --util:#5B6B75;
--shadow:0 1px 0 rgba(22,36,44,.06);
}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){
--paper:#0D1418; --panel:#141F25; --ink:#DCE6EA; --ink-2:#A2B4BC; --ink-3:#798D96;
--rule:#2A3A43; --rule-2:#1E2C33;
--road:#7FB3CC; --ochre:#D9974A; --water:#5FB6D6;
--bridge:#3FBFAF; --tunnel:#9AAAB6; --shed:#B99BE0; --place:#CFA84A; --util:#8FA2AD;
--shadow:0 1px 0 rgba(0,0,0,.4);
}}
:root[data-theme="dark"]{
--paper:#0D1418; --panel:#141F25; --ink:#DCE6EA; --ink-2:#A2B4BC; --ink-3:#798D96;
--rule:#2A3A43; --rule-2:#1E2C33;
--road:#7FB3CC; --ochre:#D9974A; --water:#5FB6D6;
--bridge:#3FBFAF; --tunnel:#9AAAB6; --shed:#B99BE0; --place:#CFA84A; --util:#8FA2AD;
--shadow:0 1px 0 rgba(0,0,0,.4);
}
*{box-sizing:border-box}
body{background:var(--paper);color:var(--ink);
font-family:"Noto Sans JP",system-ui,-apple-system,"Hiragino Kaku Gothic ProN",sans-serif;
font-size:14px;line-height:1.55;margin:0;padding:0 20px 64px}
.wrap{max-width:1240px;margin:0 auto}
header{padding:34px 0 20px;border-bottom:1px solid var(--rule)}
h1{font-family:"IBM Plex Mono",ui-monospace,monospace;font-weight:600;font-size:26px;
letter-spacing:-.01em;margin:0 0 6px;text-wrap:balance}
.sub{color:var(--ink-2);max-width:66ch;margin:0}
.ends{display:flex;flex-wrap:wrap;gap:8px 26px;margin-top:14px;
font-family:"IBM Plex Mono",monospace;font-size:12px;color:var(--ink-3)}
.ends b{color:var(--ink);font-weight:500}
h2{font-family:"IBM Plex Mono",monospace;font-size:11px;font-weight:600;letter-spacing:.14em;
text-transform:uppercase;color:var(--ink-3);margin:34px 0 10px}
.note{color:var(--ink-3);font-size:12.5px;max-width:70ch;margin:0 0 12px}
.scroller{overflow-x:auto;border:1px solid var(--rule);border-radius:3px;background:var(--panel)}
svg{display:block}
text{font-family:"IBM Plex Mono",monospace;font-variant-numeric:tabular-nums}
.jp{font-family:"Noto Sans JP",sans-serif}
.filters{border:1px solid var(--rule);border-radius:3px;background:var(--panel);
padding:12px 14px;margin:0 0 12px}
.frow{display:flex;flex-wrap:wrap;gap:6px;align-items:baseline}
.frow+.frow{margin-top:10px;padding-top:10px;border-top:1px solid var(--rule-2)}
.flab{font-family:"IBM Plex Mono",monospace;font-size:10px;font-weight:600;letter-spacing:.13em;
text-transform:uppercase;color:var(--ink-3);flex:0 0 118px}
.fbar{display:flex;justify-content:space-between;align-items:baseline;gap:14px;
margin-bottom:10px;padding-bottom:10px;border-bottom:1px solid var(--rule-2)}
.count{font-family:"IBM Plex Mono",monospace;font-size:12px;color:var(--ink-2);
font-variant-numeric:tabular-nums}
.count b{color:var(--ink);font-weight:600}
.bulk{display:flex;gap:6px}
.chips{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 12px}
.chip{font-family:"IBM Plex Mono",monospace;font-size:11.5px;letter-spacing:.03em;
border:1px solid var(--rule);background:transparent;color:var(--ink-2);
padding:4px 10px;border-radius:2px;cursor:pointer}
.chip[aria-pressed="true"]{background:var(--ink);color:var(--paper);border-color:var(--ink)}
.chip .sw{display:inline-block;width:7px;height:7px;margin-right:6px;vertical-align:baseline;
border-radius:1px}
.chip .n{opacity:.62;margin-left:6px;font-variant-numeric:tabular-nums}
.chip:focus-visible{outline:2px solid var(--ochre);outline-offset:2px}
.legend{display:flex;flex-wrap:wrap;gap:6px 20px;margin:10px 0 0;
font-family:"IBM Plex Mono",monospace;font-size:11.5px;color:var(--ink-3)}
.legend i{display:inline-block;width:9px;height:9px;margin-right:6px;vertical-align:baseline}
table{border-collapse:collapse;width:100%;font-size:13px}
th{font-family:"IBM Plex Mono",monospace;font-size:10.5px;letter-spacing:.1em;text-transform:uppercase;
color:var(--ink-3);text-align:left;font-weight:600;padding:7px 10px;border-bottom:1px solid var(--rule)}
td{padding:6px 10px;border-bottom:1px solid var(--rule-2);vertical-align:baseline}
td.km{font-family:"IBM Plex Mono",monospace;font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap}
td.num{font-family:"IBM Plex Mono",monospace;font-variant-numeric:tabular-nums;text-align:right;color:var(--ink-2)}
td.kind{font-family:"IBM Plex Mono",monospace;font-size:11.5px;color:var(--ink-3)}
tr.hit{background:color-mix(in srgb,var(--ochre) 14%,transparent)}
.tblwrap{overflow-x:auto;max-height:520px;overflow-y:auto;border:1px solid var(--rule);border-radius:3px}
footer{margin-top:38px;padding-top:16px;border-top:1px solid var(--rule);
color:var(--ink-3);font-size:12px;max-width:74ch}
@media (prefers-reduced-motion:no-preference){
.mark{transition:r .12s ease, opacity .12s ease}
}
.frow.oaza .chip{font-size:11px}
button.copy{font:inherit;color:inherit;background:none;border:0;padding:0;margin:0;
cursor:copy;text-align:left;border-bottom:1px dotted var(--rule)}
button.copy:hover{border-bottom-color:var(--ink-3)}
button.copy:focus-visible{outline:2px solid var(--ochre);outline-offset:2px}
button.copy.copied{background:color-mix(in srgb,var(--ochre) 22%,transparent);
border-bottom-color:transparent}
button.copy.copied::after{content:' copied';font-size:10px;letter-spacing:.08em;
color:var(--ink-3);text-transform:uppercase}
.tblwrap{user-select:text}
2026-09-11 01:06:57 +09:00
.chip.quick{font-size:10px;padding:3px 8px;letter-spacing:.08em;text-transform:uppercase;
color:var(--ink-3);border-style:dashed;margin-right:2px}
.chip.quick:hover{color:var(--ink);border-style:solid}
.band{font-family:"IBM Plex Mono",monospace}
</style>
<div class="wrap">
<header>
<h1>274 Transect</h1>
<p class="sub">The working roster for the 川端橋&ndash;右左府 stretch of National Route 274,
ordered by distance along the road. Structures come from the 北海道開発局 facility registers,
watercourses from 国土数値情報 W05, addresses from the 国土地理院 reverse geocoder.</p>
<div class="ends">
<span>WEST <b>川端橋</b> 37.3 km &middot; 夕張郡由仁町川端</span>
<span>EAST <b>右左府</b> 106.2 km &middot; 沙流郡日高町日高</span>
<span id="tally"></span>
</div>
</header>
<h2>Strip &mdash; the road straightened</h2>
<p class="note">Distance runs left to right, structures above the line, everything else below.
The band across the top is the 大字 the road is passing through, sampled every 250&nbsp;m.
Distances are measured from a datum near 上野幌 and are <b>not</b> official kiloposts.</p>
<div class="filters">
<div class="fbar">
<span class="count" id="count"></span>
<span class="bulk">
<button class="chip" type="button" id="allOn">all</button>
<button class="chip" type="button" id="allOff">none</button>
</span>
</div>
<div id="chips"></div>
</div>
<div class="scroller"><svg id="strip" role="img" aria-label="Linear strip map of Route 274 features by distance"></svg></div>
<div class="legend" id="legend"></div>
<h2>Ground &mdash; true shape</h2>
<p class="note">The same roster in real coordinates. 50&nbsp;km east to west, under 8&nbsp;km
north to south, so the road reads nearly straight apart from the swing south through 穂別.</p>
<div class="scroller"><svg id="geo" role="img" aria-label="Geographic plot"></svg></div>
<h2>Roster</h2>
<div class="tblwrap"><table id="tbl">
<thead><tr><th style="text-align:right">km</th><th>Object</th><th>Kana</th>
<th>Kind</th><th style="text-align:right">Offset (m)</th><th>Address</th></tr></thead>
2026-09-11 01:06:57 +09:00
<tbody id="tbody"></tbody>
</table></div>
<footer>OpenStreetMap contributors (ODbL) &middot; 国土交通省 北海道開発局 個別施設計画, 令和8年3月
&middot; 国土数値情報 河川データセット W05 via 国立情報学研究所 &middot; 国土地理院 逆ジオコーディング
&middot; 日本郵便 郵便番号データ. Positions are derived, not surveyed &mdash; a starting point for
verification.</footer>
</div>
<script id="data" type="application/json">{"route":[[35.527,42.92783,141.88304],[35.827,42.92577,141.88541],[36.828,42.91884,141.89326],[36.877,42.91848,141.89362],[37.043,42.91721,141.89469],[37.06,42.91709,141.89479],[37.079,42.91692,141.89487],[37.092,42.91681,141.8949],[37.147,42.91632,141.89497],[37.236,42.91552,141.8951],[37.251,42.91538,141.89512],[37.266,42.9154,141.89529],[37.377,42.91551,141.89665],[37.476,42.91559,141.89787],[37.579,42.91568,141.89912],[37.673,42.91577,141.90026],[37.876,42.91595,141.90275],[38.055,42.91613,141.90493],[38.118,42.91618,141.90571],[38.194,42.91627,141.90663],[38.211,42.9163,141.90684],[38.229,42.91635,141.90704],[38.278,42.9165,141.90761],[38.297,42.91657,141.90783],[38.317,42.91665,141.90803],[38.339,42.91675,141.90827],[38.361,42.91686,141.9085],[38.41,42.91715,141.90896],[38.588,42.91822,141.91059],[38.659,42.91864,141.91124],[38.71,42.91892,141.91172],[38.726,42.91901,141.91189],[38.742,42.91908,141.91205],[38.769,42.9192,141.91235],[38.792,42.91928,141.9126],[38.818,42.91938,141.9129],[38.852,42.91948,141.9133],[38.885,42.91955,141.91368],[38.907,42.91959,141.91395],[38.935,42.91963,141.91429],[38.967,42.91965,141.91469],[38.999,42.91965,141.91507],[39.021,42.91964,141.91535],[39.053,42.9196,141.91574],[39.081,42.91954,141.91607],[39.12,42.91941,141.91651],[39.155,42.91928,141.9169],[39.192,42.91909,141.91727],[39.222,42.91891,141.91755],[39.255,42.9187,141.91784],[39.284,42.91849,141.91805],[39.313,42.91827,141.91823],[39.346,42.91801,141.91843],[39.38,42.91773,141.91861],[39.472,42.91696,141.91903],[39.559,42.91624,141.91944],[39.618,42.91576,141.91973],[39.66,42.91542,141.91997],[39.721,42.91495,141.92036],[39.761,42.91465,141.92062],[39.8,42.91436,141.9209],[39.914,42.91355,141.92175],[40.158,42.91178,141.92352],[40.43,42.90983,141.92554],[40.511,42.90925,141.92615],[40.574,42.90884,141.92668],[40.618,42.90861,141.92711],[40.666,42.9084,141.92763],[40.703,42.90828,141.92806],[40.736,42.9082,141.92845],[40.773,42.90814,141.92889],[40.807,42.90812,141.92931],[40.838,42.90812,141.92969],[40.864,42.90814,141.93001],[40.905,42.9082,141.9305],[41.016,42.90845,141.93182],[41.321,42.90912,141.93546],[41.472,42.90946,141.93725],[41.522,42.90957,141.93784],[41.572,42.90965,141.93845],[41.766,42.90991,141.9408],[41.862,42.91003,141.94197],[41.958,42.91015,141.94314],[42.047,42.91027,141.94422],[42.076,42.91031,141.94457],[42.097,42.91037,141.94482],[42.119,42.91044,141.94507],[42.143,42.91055,141.94532],[42.177,42.91073,141.94566],[42.2,42.91088,141.94585],[42.231,42.9111,141.94608],[42.266,42.91137,141.9463],[42.358,42.91211,141.94683],[42.418,42.91259,141.94713],[42.486,42.91317,141.94744],[42.599,42.91412,141.94789],[42.631,42.91439,141.94806],[42.663,42.91464,141.94824],[42.694,42.91487,141.94846],[42.728,42.9151,141.94875],[42.753,42.91525,141.94897],[42.782,42.9154,141.94924],[42.808,42.91553,141.94952],[42.841,42.91566,141.94988],[42.875,42.91577,141.95028],[42.907,42.91583,141.95066],[43.008,42.91597,141.95188],[43.035,42.91604,141.9522],[43.067,42.91614,141.95257],[43.213,42.91668,141.9542],[43.231,42.91674,141.95441],[43.251,42.91679,141.95464],[43.252,42.91679,141.95465],[43.275,42.91683,141.95494],[43.302,42.91684,141.95526],[43.326,42.91682,141.95555],[43.345,42.9168,141.95579],[43.363,42.91677,141.95601],[43.388,42.91671,141.9563],[43.499,42.91632,141.95755],[43.644,42.9158,141.95919],[43.87,42.915,141.96174],[43.943,42.91473,141.96256],[44.002,42.91449,141.96321],[44.048,42.91429,141.96371],[44.094,42.9141,141.96421],[44.149,42.91385,141.96479],[44.188,42.9137,141.96521],[44.23,42.91355,141.9657],[44.279,42.91342,141.96627],[44.414,42.91317,141.96789],[44.562,42.91291,141.96967],[44.625,42.91279,141.97043],[44.672,42.91268,141.97099],[44.702,42.9126,141.97134],[44.735,42.91248,141.97171],[44.747,42.91243,141.97184],[44.858,42.91193,141.97302],[44.988,42.91134,141.9744],[45.064,42.91099,141.9752],[45.099,42.91084,141.97557],[45.188,42.91042,141.9765],[45.211,42.91031,141.97674],[45.286,42.90994,141.97752],[45.505,42.90888,141.97978],[45.535,42.90873,141.98009],[45.6
2026-09-11 01:06:57 +09:00
<script>
(function(){
var D=JSON.parse(document.getElementById('data').textContent);
var K0=36.5,K1=108.5;
var FAM={bridge:'var(--bridge)',tunnel:'var(--tunnel)',shed:'var(--shed)',
watercourse:'var(--water)',place:'var(--place)',other:'var(--util)'};
function famOf(o){
if(o.kind==='bridge'||o.kind==='tunnel'||o.kind==='shed')return o.kind;
if(o.kind==='watercourse')return 'watercourse';
return /^place/.test(o.kind)?'place':'other';
}
var items=D.items.slice();
items.forEach(function(o){o._f=famOf(o)});
items.sort(function(a,b){return a.km-b.km});
var kinds={},oazas={};
items.forEach(function(o){kinds[o.kind]=(kinds[o.kind]||0)+1;oazas[o.oaza]=(oazas[o.oaza]||0)+1});
var onK={},onO={};
Object.keys(kinds).forEach(function(k){onK[k]=true});
Object.keys(oazas).forEach(function(k){onO[k]=true});
var sel=null;
document.getElementById('tally').textContent=items.length+' entries \u00b7 '+
Object.keys(kinds).length+' kinds \u00b7 '+Object.keys(oazas).length+' 大字';
var STRUCT=['bridge','tunnel','shed'],WATER=['watercourse'];
var REST=Object.keys(kinds).filter(function(k){return STRUCT.indexOf(k)<0&&WATER.indexOf(k)<0})
.sort(function(a,b){return kinds[b]-kinds[a]||a.localeCompare(b)});
var OAZA=Object.keys(oazas).sort(function(a,b){
var A=items.filter(function(o){return o.oaza===a})[0].km;
var B=items.filter(function(o){return o.oaza===b})[0].km;return A-B});
var chipEls={};
function mkRow(label,keys,store,cls){
var row=document.createElement('div');row.className='frow'+(cls?' '+cls:'');
var l=document.createElement('span');l.className='flab';l.textContent=label;row.appendChild(l);
var pre=(store===onK?'k:':'o:');
function rowBulk(v){keys.forEach(function(k){store[k]=v;
chipEls[pre+k].setAttribute('aria-pressed',v?'true':'false')});draw()}
['all','none'].forEach(function(w,i){
var q=document.createElement('button');q.className='chip quick';q.type='button';
q.textContent=w;q.title=w+' '+label;
q.onclick=function(){rowBulk(i===0)};row.appendChild(q);
});
keys.forEach(function(k){
var b=document.createElement('button');b.className='chip';b.type='button';
b.setAttribute('aria-pressed','true');
var sw='';
if(store===onK){var fam=(items.filter(function(o){return o.kind===k})[0]||{})._f||'other';
sw='<i class="sw" style="background:'+FAM[fam]+'"></i>';}
b.innerHTML=sw+k+'<span class="n">'+(store===onK?kinds[k]:oazas[k])+'</span>';
b.onclick=function(){store[k]=!store[k];b.setAttribute('aria-pressed',store[k]?'true':'false');draw()};
chipEls[(store===onK?'k:':'o:')+k]=b;row.appendChild(b);
});
return row;
}
var chips=document.getElementById('chips');
chips.appendChild(mkRow('Road structures',STRUCT,onK));
chips.appendChild(mkRow('Water',WATER,onK));
chips.appendChild(mkRow('Places & facilities',REST,onK));
chips.appendChild(mkRow('大字 (west to east)',OAZA,onO,'oaza'));
function bulk(v){
Object.keys(onK).forEach(function(k){onK[k]=v;chipEls['k:'+k].setAttribute('aria-pressed',v?'true':'false')});
Object.keys(onO).forEach(function(k){onO[k]=v;chipEls['o:'+k].setAttribute('aria-pressed',v?'true':'false')});
draw();}
document.getElementById('allOn').onclick=function(){bulk(true)};
document.getElementById('allOff').onclick=function(){bulk(false)};
document.getElementById('legend').innerHTML=
[['bridge','bridges'],['tunnel','tunnels'],['shed','snow shed'],['watercourse','watercourses'],
['place','place names'],['other','facilities']]
.map(function(g){return '<span><i style="background:'+FAM[g[0]]+'"></i>'+g[1]+'</span>'}).join('');
var NS='http://www.w3.org/2000/svg';
var rowOf=null, markOf=new Map();
function paintMarks(){
markOf.forEach(function(m,k){
var on=(k===sel);
if(m.c){m.c.setAttribute('r',on?6:m.r0);}
if(m.t){m.t.setAttribute('font-weight',on?'700':'400');}
if(m.g){m.g.setAttribute('r',on?6:3);m.g.setAttribute('opacity',on?1:.85);}
});
}
2026-09-11 01:06:57 +09:00
function el(n,a){var e=document.createElementNS(NS,n);for(var k in a)e.setAttribute(k,a[k]);return e}
function draw(){
var W=Math.max(2600,(K1-K0)*36),H=450,AX=272,PADL=54,PADR=54;
var s=document.getElementById('strip');
s.setAttribute('viewBox','0 0 '+W+' '+H);s.setAttribute('width',W);s.setAttribute('height',H);
while(s.firstChild)s.removeChild(s.firstChild);
var x=function(km){return PADL+(km-K0)/(K1-K0)*(W-PADL-PADR)};
D.bands.forEach(function(b,i){
var x0=x(b.frm),x1=x(Math.max(b.to,b.frm+0.25));
s.appendChild(el('rect',{x:x0,y:14,width:Math.max(x1-x0,2),height:20,
fill:(i%2?'var(--rule-2)':'var(--rule)'),opacity:.85}));
if(x1-x0>46){var t=el('text',{x:(x0+x1)/2,y:28,fill:'var(--ink-2)','font-size':10,
'text-anchor':'middle',class:'band jp'});t.textContent=b.lv.replace(/^字/,'');s.appendChild(t);}
});
for(var k=Math.ceil(K0/5)*5;k<=K1;k+=5){
s.appendChild(el('line',{x1:x(k),y1:40,x2:x(k),y2:H-30,stroke:'var(--rule-2)','stroke-width':1}));
var t=el('text',{x:x(k),y:H-14,fill:'var(--ink-3)','font-size':11,'text-anchor':'middle'});
t.textContent=k;s.appendChild(t);
}
s.appendChild(el('line',{x1:PADL,y1:AX,x2:W-PADR,y2:AX,stroke:'var(--road)','stroke-width':2.5}));
markOf=new Map();
2026-09-11 01:06:57 +09:00
var vis=items.filter(function(o){return onK[o.kind]&&onO[o.oaza]});
document.getElementById('count').innerHTML='showing <b>'+vis.length+'</b> of '+items.length+' entries';
var lu=[],ld=[];
vis.forEach(function(o){
var up=(o._f==='bridge'||o._f==='tunnel'||o._f==='shed');
var lanes=up?lu:ld,px=x(o.km),li=0;
while(lanes[li]!==undefined&&px-lanes[li]<58)li++;
lanes[li]=px;
var y=up?AX-26-li*30:AX+26+li*30, c=FAM[o._f];
s.appendChild(el('line',{x1:px,y1:AX,x2:px,y2:up?y+7:y-7,stroke:c,'stroke-width':1,opacity:.5}));
var r=el('circle',{cx:px,cy:up?y+7:y-7,r:(sel===o?6:(up?4:3)),fill:c,class:'mark'});
var tx=el('text',{x:px,y:up?y:y+4,fill:'var(--ink)','font-size':11.5,'text-anchor':'middle',class:'jp'});
tx.textContent=o.obj;
2026-09-11 01:06:57 +09:00
if(sel===o)tx.setAttribute('font-weight','700');
tx.style.cursor='pointer';r.style.cursor='pointer';
var pick=function(){select(o)};tx.onclick=pick;r.onclick=pick;
var e0=markOf.get(o)||{};e0.c=r;e0.t=tx;e0.r0=(up?4:3);markOf.set(o,e0);
2026-09-11 01:06:57 +09:00
s.appendChild(r);s.appendChild(tx);
var km=el('text',{x:px,y:up?y-13:y+16,fill:'var(--ink-3)','font-size':9.5,'text-anchor':'middle'});
km.textContent=o.km.toFixed(2)+(o.name&&o.name!==o.obj?' \u00b7 '+o.name:'');
s.appendChild(km);
if(o.kana){
var kn=el('text',{x:px,y:up?y-24:y+27,fill:'var(--ink-3)','font-size':9,
'text-anchor':'middle',class:'jp'});
kn.textContent=o.kana;s.appendChild(kn);
}
2026-09-11 01:06:57 +09:00
});
var lab=el('text',{x:PADL,y:H-32,fill:'var(--ink-3)','font-size':11});
lab.textContent='OBJECT NAME ON THE MARK \u00b7 km, EXTRACTED NAME AND KANA BELOW IT \u00b7 大字 BAND ACROSS THE TOP';
2026-09-11 01:06:57 +09:00
s.appendChild(lab);
var g=document.getElementById('geo'),GW=1200;
var lats=D.route.map(function(r){return r[1]}),lons=D.route.map(function(r){return r[2]});
var la0=Math.min.apply(null,lats),la1=Math.max.apply(null,lats);
var lo0=Math.min.apply(null,lons),lo1=Math.max.apply(null,lons);
var kx=Math.cos((la0+la1)/2*Math.PI/180),sx=(lo1-lo0)*kx,sy=(la1-la0);
var P=34,iw=GW-2*P,ih=iw*sy/sx,GH=ih+2*P;
g.setAttribute('viewBox','0 0 '+GW+' '+GH);g.setAttribute('width',GW);g.setAttribute('height',GH);
while(g.firstChild)g.removeChild(g.firstChild);
var gx=function(lo){return P+(lo-lo0)*kx/sx*iw},gy=function(la){return P+ih-(la-la0)/sy*ih};
g.appendChild(el('path',{d:D.route.map(function(r,i){return (i?'L':'M')+gx(r[2]).toFixed(1)+' '+gy(r[1]).toFixed(1)}).join(''),
fill:'none',stroke:'var(--road)','stroke-width':2.2,'stroke-linejoin':'round'}));
vis.forEach(function(o){
var cir=el('circle',{cx:gx(o.lon),cy:gy(o.lat),r:(sel===o?6:3),fill:FAM[o._f],
opacity:(sel===o?1:.85),class:'mark'});
cir.style.cursor='pointer';cir.onclick=function(){select(o)};
var e1=markOf.get(o)||{};e1.g=cir;markOf.set(o,e1);
2026-09-11 01:06:57 +09:00
var t=el('title');t.textContent=o.obj+' \u00b7 '+o.km.toFixed(2)+' km \u00b7 '+o.oaza;cir.appendChild(t);
g.appendChild(cir);
});
var tb=document.getElementById('tbody');tb.innerHTML='';rowOf=new Map();
2026-09-11 01:06:57 +09:00
vis.forEach(function(o){
var tr=document.createElement('tr');
if(sel===o)tr.className='hit';
tr.innerHTML='<td class="km">'+o.km.toFixed(2)+'</td>'+
'<td class="jp"><button type="button" class="copy" title="Copy name">'+o.obj+'</button></td>'+
'<td class="jp" style="color:var(--ink-3)">'+(o.kana||'')+'</td>'+
'<td class="kind">'+o.kind+'</td>'+
'<td class="num">'+Math.round(o.off)+'</td>'+
'<td class="jp" style="color:var(--ink-2)">'+(o.addr||'')+'</td>';
tr.querySelector('.copy').onclick=function(e){e.stopPropagation();copyName(o,this)};
tr.onclick=function(){select(o)};
rowOf.set(o,tr);tb.appendChild(tr);
2026-09-11 01:06:57 +09:00
});
}
function select(o){
sel=o;
if(rowOf)rowOf.forEach(function(tr,k){tr.className=(k===o?'hit':'')});
paintMarks();
}
function copyName(o,btn){
var t=o.obj, done=function(){
btn.classList.add('copied');
setTimeout(function(){btn.classList.remove('copied')},900);
};
if(navigator.clipboard&&navigator.clipboard.writeText){
navigator.clipboard.writeText(t).then(done,function(){fallback(t,done)});
} else fallback(t,done);
}
function fallback(t,done){
var ta=document.createElement('textarea');
ta.value=t;ta.setAttribute('readonly','');
ta.style.position='fixed';ta.style.left='-9999px';
document.body.appendChild(ta);ta.select();
try{document.execCommand('copy');done()}catch(e){}
document.body.removeChild(ta);
}
2026-09-11 01:06:57 +09:00
draw();
})();
</script>