r111/funnel.html · 约 7492 字符
1<!DOCTYPE html>2<html lang="zh-CN">3<head>4<meta charset="UTF-8">5<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover">6<meta name="theme-color" content="#4263eb">7<title>漏斗图与热力图 · 图表工具大全</title>8<link rel="stylesheet" href="style.css">9</head>10<body data-page="funnel" class="nopad">11<div class="navbar"><a class="bk" href="gallery.html">‹</a><div class="tt">漏斗图与热力图</div><div class="rt"><a href="#" id="viewjson">JSON</a></div></div>12<div class="wrap" style="padding-bottom:0">13 <div class="seg" id="tab">14 <button class="on" data-v="funnel">转化漏斗</button>15 <button data-v="heat">日历热力</button>16 </div>17</div>1819<div id="pane-funnel">20 <div class="card mt12">21 <div class="ch"><b id="tt">--</b><span id="src"></span></div>22 <div class="chart" id="c1"></div>23 </div>24 <div class="card">25 <div class="ch"><b>逐级转化明细</b><span>相对上一层 / 相对首层</span></div>26 <div class="tblwrap"><table class="tbl" id="tb"></table></div>27 </div>28 <div class="card">29 <div class="ch"><b>流失诊断</b><span>自动定位瓶颈环节</span></div>30 <div id="diag"></div>31 </div>32</div>3334<div id="pane-heat" style="display:none">35 <div class="card mt12">36 <div class="ch"><b id="tt2">--</b><span id="src2"></span></div>37 <div class="chart" id="c2"></div>38 <div class="row" style="justify-content:flex-end;gap:6px;padding:0 4px 2px">39 <span class="muted" style="font-size:10px">低</span>40 <span id="ramp" class="row" style="gap:2px"></span>41 <span class="muted" style="font-size:10px">高</span>42 </div>43 <div class="muted" style="font-size:11px;padding:2px 4px 0">点击任意色块可查看当日数值</div>44 </div>45 <div class="card">46 <div class="ch"><b>星期分布</b><span>各星期日均活跃</span></div>47 <div class="chart" id="c3"></div>48 </div>49 <div class="card">50 <div class="ch"><b>峰值 TOP 5</b></div>51 <div id="top5"></div>52 </div>53 <div class="card">54 <div class="ch"><b>强度分档</b><span>共 <i id="cnt">0</i> 天</span></div>55 <div id="buckets"></div>56 </div>57</div>58<div style="height:18px"></div>5960<div class="sheet" id="sjson">61 <div class="sh"><b>数据源 JSON</b><span class="x">×</span></div>62 <div class="sb"><pre class="code" id="jsonbox"></pre></div>63</div>646566<div class="mask" id="mask"></div>67<div class="toast" id="toast"></div>68<script src="data/fallback.js"></script>69<script src="chart.js"></script>70<script src="app.js"></script>71<script>7273var FD=null, HD=null, cur='funnel';7475function drawFunnel(){76 if(!FD) return;77 CH.funnel($('#c1'), {items:FD.items});78 var it=FD.items, top=it[0].value;79 var h='<tr><th>阶段</th><th class="n">人数</th><th class="n">环比</th><th class="n">总转化</th></tr>';80 for(var i=0;i<it.length;i++){81 var prev = i===0 ? it[0].value : it[i-1].value;82 var st = it[i].value/prev*100;83 var all = it[i].value/top*100;84 var cls = i===0 ? '' : (st<45 ? 'style="color:#fa5252;font-weight:700"' : (st>=80?'style="color:#12b886"':''));85 h+='<tr><td><span class="dot" style="background:'+it[i].color+'"></span>'+it[i].name+'</td>'+86 '<td class="n">'+CH.thousand(it[i].value)+'</td>'+87 '<td class="n" '+cls+'>'+(i===0?'—':st.toFixed(1)+'%')+'</td>'+88 '<td class="n">'+all.toFixed(2)+'%</td></tr>';89 }90 $('#tb').innerHTML=h;9192 var worst=-1, wr=999;93 for(var k=1;k<it.length;k++){94 var r=it[k].value/it[k-1].value*100;95 if(r<wr){ wr=r; worst=k; }96 }97 var lost = it[worst-1].value - it[worst].value;98 $('#diag').innerHTML =99 '<div class="kv"><span>整体转化率</span><b>'+(it[it.length-1].value/top*100).toFixed(2)+'%</b></div>'+100 '<div class="kv"><span>最大流失环节</span><b style="color:#fa5252">'+it[worst-1].name+' → '+it[worst].name+'</b></div>'+101 '<div class="kv"><span>该环节流失人数</span><b>'+CH.thousand(lost)+' '+(FD.unit||'')+'</b></div>'+102 '<div class="kv"><span>该环节通过率</span><b>'+wr.toFixed(1)+'%</b></div>'+103 '<div class="tk" style="margin-top:10px">建议优先优化「'+it[worst-1].name+'→'+it[worst].name+104 '」,若把通过率提升到 '+Math.min(95,(wr+10)).toFixed(0)+'%,末层可多得约 '+105 CH.thousand(Math.round(it[it.length-1].value*((wr+10)/wr-1)))+' '+(FD.unit||'')+'。</div>';106}107108function drawHeat(){109 if(!HD) return;110 CH.heat($('#c2'), {values:HD.values, weeks:HD.weeks, days:HD.days, start:HD.start,111 rgb:HD.rgb, unit:HD.unit, name:HD.name});112 var rgb=(HD.rgb||[66,99,235]).join(',');113 $('#ramp').innerHTML=[0.1,0.3,0.5,0.72,1].map(function(a){114 return '<i style="display:inline-block;width:12px;height:12px;border-radius:3px;background:rgba('+rgb+','+a+')"></i>';115 }).join('');116117 var v=HD.values, i, sum=[0,0,0,0,0,0,0], cn=[0,0,0,0,0,0,0];118 for(i=0;i<v.length;i++){ sum[i%7]+=v[i]; cn[i%7]++; }119 CH.bar($('#c3'), {120 cats:HD.days.map(function(d){return '周'+d;}),121 series:[{name:'日均活跃', color:'#fa5252', data:sum.map(function(s,i){return Math.round(s/(cn[i]||1));})}],122 h:200, unit:HD.unit123 });124125 var idx=v.map(function(x,i){return [x,i];}).sort(function(a,b){return b[0]-a[0];}).slice(0,5);126 var mx=idx.length?idx[0][0]:1;127 $('#top5').innerHTML=idx.map(function(p,rank){128 var d=new Date(HD.start); d.setDate(d.getDate()+p[1]);129 var ds=(d.getMonth()+1)+'月'+d.getDate()+'日 周'+HD.days[p[1]%7];130 return '<div class="rank"><div class="rt"><span><i class="no">'+(rank+1)+'</i>'+ds+'</span><b>'+131 CH.thousand(p[0])+'</b></div><div class="bar"><i style="width:'+(p[0]/mx*100)+'%;background:#fa5252"></i></div></div>';132 }).join('');133134 var mxa=Math.max.apply(null,v);135 var lv=[['清淡',0,.25,'#dbe4ff'],['一般',.25,.5,'#91a7ff'],['活跃',.5,.75,'#5c7cfa'],['火热',.75,1.01,'#3b5bdb']];136 $('#cnt').textContent=v.length;137 $('#buckets').innerHTML=lv.map(function(L){138 var c=v.filter(function(x){var r=x/mxa; return r>=L[1]&&r<L[2];}).length;139 return '<div class="rank"><div class="rt"><span><span class="dot" style="background:'+L[3]+'"></span>'+L[0]+140 '('+Math.round(L[1]*mxa)+'~'+Math.round(L[2]>1?mxa:L[2]*mxa)+')</span><b>'+c+' 天 · '+141 (c/v.length*100).toFixed(0)+'%</b></div><div class="bar"><i style="width:'+(c/v.length*100)+142 '%;background:'+L[3]+'"></i></div></div>';143 }).join('');144}145146function boot(){147 loading($('#c1'),'正在读取 data/funnel.json');148 DS.all(['funnel','heat']).then(function(r){149 FD=r[0]; HD=r[1];150 $('#tt').textContent=FD.name; $('#src').innerHTML=srcBadge(FD);151 $('#tt2').textContent=HD.name; $('#src2').innerHTML=srcBadge(HD);152 $('#jsonbox').innerHTML=hlJSON(cur==='heat'?HD:FD);153 drawFunnel();154 if(cur==='heat') drawHeat();155 }).catch(function(e){ failBox($('#c1'), e); });156}157158segGroup('#tab', function(v){159 cur=v;160 $('#pane-funnel').style.display = v==='funnel' ? '' : 'none';161 $('#pane-heat').style.display = v==='heat' ? '' : 'none';162 if(FD) $('#jsonbox').innerHTML=hlJSON(v==='heat'?HD:FD);163 if(v==='heat') drawHeat(); else drawFunnel();164});165$('#viewjson').addEventListener('click', function(e){ e.preventDefault(); openSheet('#sjson'); });166167if(/tab=heat/.test(location.search)){168 cur='heat';169 $$('#tab button').forEach(function(b){ b.classList.toggle('on', b.dataset.v==='heat'); });170 $('#pane-funnel').style.display='none';171 $('#pane-heat').style.display='';172}173boot();174175</script>176</body>177</html>178