首页/ mobileweb/ 图表工具大全 · 移动端数据可视化图表库(原生 JS 无依赖)/ 代码预览

💻 代码预览 · 图表工具大全 · 移动端数据可视化图表库(原生 JS 无依赖)

mw_tool · 上传者 驰旭教育
← 返回详情
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