純JS實現房貸利率報表對比

最近朋友買房,想計算下本身的房貸的還款狀況,本身正好週末沒事,從網上找來點代碼修改,也算是對本身技術的鞏固吧。php

目前這個還只是個初級版本,暫時能夠在PC上正常訪問,未來會一步一步的把相繼功能都加上的,將要完成的功能:css

  1. 能夠在Android手機上訪問的界面對齊、美化等。
  2. 圖表的優化。
  3. 等額本金法和等額本息法的實現。

以上功能暫列這麼多,之後有想到的在慢慢往上加;也但願你們多多的提出你的意見。html

之後會把每次都更新版本都添加到文章的後面,方便歷史版本的追溯。樣圖:web


 

版本一:編程

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>JS計算器,貸款利率計算器</title>
<!--參考出處:http://www.codefans.net/jscss/code/3613.shtml-->

<style> /* 這是一個CSS樣式表:定義了程序輸出的樣式 */
body{ font-size:12px;}
#payment { text-decoration: underline; } /* 定義 id="payment" 的元素樣式 */
#graph { border: solid black 1px; } /* 圖表有一個1像素的邊框 */
th, td {vertical-align: top; } /* 表格單元格對齊方式爲頂端對齊 */
table{
    border-collapse: collapse;
    border: none;
}
td, th{
    border: solid #000 1px;
}
.output { font-weight: bold; } /* 計算結果定義爲粗體 */
.btn{
    font-weight: 700;
    line-height: 30px;
    width: 100px;
    height: 35px;
}
.help
{
    float:right;
    cursor:pointer;
    line-height: 10px;
    margin-top: -4px;
    margin-right: -4px;
}
.nr {
    color: #666;
    font-size: 12px;
    padding: 10px 0 5px
}
.tsk {
    background: #f8f8f8;
    border: 1px solid #CCC;
    box-shadow: 0 1px 5px #DDD;
    line-height: 20px;
    padding: 10px;
    position: absolute;
    display: none;
    z-index: 10000
}

.circle {
    width: 15px;
    height: 15px;
    font-weight: 700;
    text-indent:4px;

        cursor:pointer;
    float:left;
    line-height:16px;
    background: #5A8BDC;
    -moz-border-radius: 50px;
    -webkit-border-radius: 50px;
    border-radius: 50px;
}
</style>

<script>
    function $(id){ return document.getElementById(id); }
    function helpClick(obj)
    {
        $(obj.id+"_help").style.display = "block";
    }
    
    function hidHelp()
    {
        $("debxhk_help").style.display = "none";
        $("debjhk_help").style.display = "none";
    }
    
</script>

</head>
<body>

  <table> 
   <tbody>
    <tr>
     <th colspan=2>輸入數據:</th>      
    </tr> 
    <tr>
     <td width=100px>
      <!--Amount of the loan-->貸款總額:</td> 
     <td><input id="amount"  value="500000" /><span style="margin-left:-18px">元</span></td> 
    </tr> 
    <tr>
     <td>
      <!--Annual interest-->年利息:</td> 
     <td><input id="apr"  value="5.65" /><span style="margin-left:-14px">%</span></td>
    </tr> 
     <td>
      利率折扣:</td> 
     <td>
         <select id=llzk style="width:156px;">
              <option value="0.7" >最新基準利率7折</option> 
               <option value="0.8" >最新基準利率8折</option> 
               <option value="0.83">最新基準利率8.3折</option> 
               <option value="0.85">最新基準利率8.5折</option> 
               <option value="0.88">最新基準利率8.8折</option> 
               <option value="0.9" >最新基準利率9折</option> 
               <option value="0.95">最新基準利率9.5折</option> 
               <option value="1.0" selected=true>最新基準利率</option> 
               <option value="1.05">最新基準利率1.05倍</option> 
               <option value="1.1" >最新基準利率1.1倍</option> 
               <option value="1.2" >最新基準利率1.2倍</option> 
               <option value="1.3" >最新基準利率1.3倍</option>
            </select> 
     </td>
    </tr> 
    <tr>
     <td>
      <!--Repayment period (years)-->償還期限:</td> 
     <td><input id="years"  value="30" /><span style="margin-left:-18px">年</span></td>
    </tr>
    <tr style="display:none"> 
     <td>
      <!--Zipcode (to find lenders)-->郵政編碼(查找放貸人):</td> 
     <td><input id="zipcode"  /></td> 
    </tr>
    <tr> 
     <th colspan=2>
      <input class="btn" type=button onclick="calculate();" value="計 算" />&nbsp;&nbsp;&nbsp;
      <input class="btn" type=reset value="重 置" />
     </th>
    </tr> 
    <tr>
         <th colspan=2>
      <!--Approximate Payments-->輸出結果:</th> 
    </tr>
    <tr>
     <td>
      <!--Monthly payment-->每個月付款:</td> 
     <td><span class="output" id="payment">0</span></td>
    </tr> 
    <tr>
     <td>
      <!--Total payment-->付款總額:</td> 
     <td><span class="output" id="total">0</span></td>
    </tr> 
    <tr>
     <td>
      <!--Total interest-->利息總額:</td> 
     <td><span class="output" id="totalinterest">0</span></td>
    </tr> 
    <tr>
     <td colspan=2>圖表:貸款金額,累計金額,利息支付</td>
    </tr> 
    <tr>
        <td colspan="2">
            <canvas id="graph" width="500" height="250"></canvas>
        </td>
    </tr> 
    <tr>
        <td colspan="2">
            <table id="result" style="width:100%"> 
       <tbody>
        <tr> 
         <td style="position:relative;width:50%;"> 
          <div>
           <span style="float:left">每個月等額還款</span>
           <div class="circle" onclick=helpClick(this) id="debxhk">?</div>
          </div>
          <div class="tsk" id="debxhk_help" style="width:214px;left:1px;top:16px"> 
              <div onclick="hidHelp()" class="help">&nbsp;x</div>
           <div class="nr">
             每個月等額還款即等額本息還款法,指借款人每個月按相等的金額償還貸款本息,其中每個月貸款利息按月初剩餘貸款本金計算並逐月結清。 
           </div> 
          </div>
          <table style="clear:both" cellpadding="0" cellspacing="0" class="tbl" > 
           <tbody>
            <tr> 
             <td class="td1" width=100px>貸款總額</td> 
             <td class="td2"><var id="_debx_dkje">0</var> 元</td> 
            </tr> 
            <tr> 
             <td class="td1">還款月數</td> 
             <td class="td2"><var id="_debx_dkqx">0</var> 月</td> 
            </tr> 
            <tr> 
             <td class="td1">首月還款</td> 
             <td class="td2"><em id="_debx_myhk">0</em> 元</td> 
            </tr> 
            <tr>
                <td class="td1">每個月遞減</td>
                <td class="td1"><em id="_debj_mydj">0</em> 元</td>
            </tr>
            <tr> 
             <td class="td1">總支付利息</td> 
             <td class="td2"><em id="_debx_zflx">0</em> 元</td> 
            </tr> 
            <tr> 
             <td class="td1">本息合計</td> 
             <td class="td2"><em id="_debx_hkze">1,039,024.42</em> 元</td> 
            </tr> 
           </tbody>
          </table> 
          </td> 
         <td style="position:relative"> 
          <div>
           <span style="float:left">逐月遞減還款</span>
           <div  onclick=helpClick(this) class="circle" id="debjhk">?</div>
          </div> 
          <div class="tsk" id="debjhk_help" style="width:214px;left:1px;top:16px"> 
              <div onclick="hidHelp()" class="help">&nbsp;X</div>
           <div class="nr">
             逐月遞減還款即等額本金還款法,指本金保持相同,利息逐月遞減,月還款數遞減;因爲每個月的還款本金額固定,而利息愈來愈少,貸款人起初還款壓力較大,可是隨時間的推移每個月還款數也愈來愈少。 
           </div> 
          </div> 
          <table  style="clear:both" cellpadding="0" cellspacing="0" class="tbl"> 
           <tbody>
            <tr> 
             <td class="td1" width=100px>貸款總額</td> 
             <td class="td2"><var id="_debj_dkje">0</var> 元</td> 
            </tr> 
            <tr> 
             <td class="td1">還款月數</td> 
             <td class="td2"><var id="_debj_dkqx">0</var> 月</td> 
            </tr> 
            <tr> 
             <td class="td1">首月還款</td> 
             <td class="td2"><em id="_debj_syhk">0</em> 元
             </td> 
            </tr> 
            <tr>
                <td class="td1">每個月遞減</td>
                <td class="td1"><em id="_debj_mydj">0</em> 元</td>
            </tr>
            <tr> 
             <td class="td1">總支付利息</td> 
             <td class="td2"><em id="_debj_zflx">0</em> 元</td> 
            </tr> 
            <tr> 
             <td class="td1">本息合計</td> 
             <td class="td2"><em id="_debj_hkze">1,039,024.42</em> 元</td> 
            </tr> 
           </tbody>
          </table> </td> 
        </tr> 
        <tr> 
         <td height="25" colspan="2"> 
             <span class="result-info">此結果僅供參考,實際應繳費以當地爲準</span>
          </td> 
        </tr> 
       </tbody>
      </table> 
        </td>
    </tr>
    
   </tbody>
  </table>


<script>
function calculate() {
    // 查找文檔中用於輸入輸出的元素
    var amount = document.getElementById("amount");
    var apr = document.getElementById("apr");
    var years = document.getElementById("years");
    var zipcode = document.getElementById("zipcode");
    var payment = document.getElementById("payment");
    var total = document.getElementById("total");
    var totalinterest = document.getElementById("totalinterest");

    // 假設全部的輸入都是合法的,將從input元素中獲取輸入數據
    // 將百分比格式轉換爲小數格式,並從年利率轉換爲月利率
    // 將年度賠付轉換爲月度賠付
    var principal = parseFloat(amount.value);
    var interest = parseFloat(apr.value) / 100 / 12;
    var payments = parseFloat(years.value) * 12;

    // 如今計算月度賠付的數據
    var x = Math.pow(1 + interest, payments); // Math.pow()進行冪次運算
    var monthly = (principal*x*interest)/(x-1);

    // 若是結果沒有超過JavaScript能表示的數字範圍,且用戶的輸入也正確
    // 這裏所展現的結果就是合法的
    if (isFinite(monthly)) {
        // 將數據填充至輸出字段的位置,四捨五入到小數點後兩位數字
        payment.innerHTML = monthly.toFixed(2);
        total.innerHTML = (monthly * payments).toFixed(2);
        totalinterest.innerHTML = ((monthly*payments)-principal).toFixed(2);

        // 將用戶的輸入數據保存下來,這樣在下次訪問時也能取到數據
        save(amount.value, apr.value, years.value, zipcode.value);
        
        // 找到並展現本地放貸人,但忽略網絡錯誤
        try { // 捕獲這段代碼拋出的全部異常
            getLenders(amount.value, apr.value, years.value, zipcode.value);
        }
        catch(e) { /* 忽略這些異常 */ }
        
        // 最後,用圖表展現貸款餘額、利息和資產收益
        chart(principal, interest, monthly, payments);
    }
    else {
        // 計算結果不是數字或者是無窮大,意味着輸入數據是非法或不完整的
        // 清空以前的輸出數據
        payment.innerHTML = "";              // 清空元素的文本內容
        total.innerHTML = ""
        totalinterest.innerHTML = "";
        chart();                             // 不傳參數的話就是清除圖表
    }
}

// 將用戶的輸入保存至localStorage對象的屬性中
// 這些屬性在再次訪問時還會繼續保持在原位置
// 若是你在瀏覽器中按照file:// URL的方式直接打開本地文件,
// 則沒法在某些瀏覽器中使用存儲功能(好比FireFox)
// 而經過HTTP打開文件是可行的
function save(amount, apr, years, zipcode) {
    if (window.localStorage) { // 只有在瀏覽器支持的時候才運行這裏的代碼
        localStorage.loan_amount = amount;
        localStorage.loan_apr = apr;
        localStorage.loan_years = years;
        localStorage.loan_zipcode = zipcode;
    }
}

// 在文檔首次加載時,將會嘗試還原輸入字段
window.onload = function() {
    // 若是瀏覽器支持本地存儲而且上次保存的值是存在的
    if (window.localStorage && localStorage.loan_amount) {
        document.getElementById("amount").value = localStorage.loan_amount;
        document.getElementById("apr").value = localStorage.loan_apr;
        document.getElementById("years").value = localStorage.loan_years;
        document.getElementById("zipcode").value = localStorage.loan_zipcode;
    }
};

// 將用戶的輸入發送至服務器端腳本(理論上)將
// 返回一個本地放貸人的連接列表,在這個例子中並無實現這種查找放貸人的服務
// 但若是該服務存在,該函數會使用它
function getLenders(amount, apr, years, zipcode) {
    // 若是瀏覽器不支持XMLHttpRequest對象,則退出
    if (!window.XMLHttpRequest) return;

    // 找到要顯示放貸人列表的元素
    var ad = document.getElementById("lenders");
    if (!ad) return;                              // 若是返回爲空,則退出

    // 將用戶的輸入數據進行URL編碼,並做爲查詢參數附加在URL裏
    var url = "getLenders.php" +                  // 處理數據的URL地址
    "?amt=" + encodeURIComponent(amount) +        // 使用查詢串中的數據
        "&apr=" + encodeURIComponent(apr) +
        "&yrs=" + encodeURIComponent(years) +
        "&zip=" + encodeURIComponent(zipcode);

    // 經過XMLHttpRequest對象來提取返回數據
    var req = new XMLHttpRequest();               // 發起一個新的請求
    req.open("GET", url);                         // 經過URL發起一個HTTP GET請求
    req.send(null);                               // 不帶任何正文發送這個請求

    // 在返回數據以前,註冊了一個事件處理函數,這個處理函數
    // 將會在服務器的響應返回至客戶端的時候調用
    // 這種異步編程模式在客戶端JavaScript中是很是常見的
    req.onreadystatechange = function() {
        if (req.readyState == 4 && req.status == 200) {
            // 若是代碼運行到這裏,說明咱們獲得了一個合法且完整的HTTP響應
            var response = req.responseText;      // HTTP響應是以字符串的形式呈現的
            var lenders = JSON.parse(response);   // 將其解析爲JS數組

            // 將數組中的放貸人對象轉換爲HTML字符串形式
            var list = "";
            for(var i = 0; i < lenders.length; i++) {
                list += "<li><a href='" + lenders[i].url + "'>" +
                    lenders[i].name + "</a>";
            }

            // 將數據在HTML元素中呈現出來
            ad.innerHTML = "<ul>" + list + "</ul>";
        }
    }
}

// 在HTML<canvas>元素中用圖表展現月度貸款餘額、利息和資產收益
// 若是不傳入參數的話,則清空以前的圖表數據
function chart(principal, interest, monthly, payments) {
    var graph = document.getElementById("graph");   // 獲得<canvas>標籤
    graph.width = graph.width;                      // 用一種巧妙的手法清除並重置畫布
    
    // 若是不傳入參數,或者瀏覽器不支持畫布,則直接返回
    if (arguments.length == 0 || !graph.getContext) return;

    // 得到畫布元素的"context"對象,這個對象定義了一組繪畫API
    var g = graph.getContext("2d");                 // 全部的繪畫操做都將基於這個對象
    var width = graph.width, height = graph.height; // 得到畫布大小

    // 這裏的函數做用是將付款數字和美圓數據轉換爲像素
    function paymentToX(n) { return n * width/payments; }
    function amountToY(a) { return height-(a * height/(monthly*payments*1.05));}

    // 付款數據是一條從(0,0)到(payments, monthly*payments)的直線
    g.moveTo(paymentToX(0), amountToY(0));          // 從左下方開始
    g.lineTo(paymentToX(payments),                  // 繪至右上方
    amountToY(monthly*payments));
    g.lineTo(paymentToX(payments), amountToY(0));   // 再至右下方
    g.closePath();                                  // 將結尾鏈接至開頭
    g.fillStyle = "#f88";                           // 亮紅色
    g.fill();                                       // 填充矩形
    g.font = "bold 12px sans-serif";                // 定義一種字體
    g.fillText("總支出", 20,20);   // 將文字繪製到圖例中

    // 不少資產數據並非線性的,很難將其反映至圖表中
    var equity = 0;
    g.beginPath();                                  // 開始繪製新圖形
    g.moveTo(paymentToX(0), amountToY(0));          // 從左下方開始
    for(var p = 1; p <= payments; p++) {
        // 計算出每一筆賠付的利息
        var thisMonthsInterest = (principal-equity)*interest;
        equity += (monthly - thisMonthsInterest);   // 獲得資產額
        g.lineTo(paymentToX(p),amountToY(equity));  // 將數據繪製到畫布上
    }
    g.lineTo(paymentToX(payments), amountToY(0));   // 將數據線繪製至X軸
    g.closePath();                                  // 將線條結尾鏈接至線條開頭
    g.fillStyle = "chartreuse";                          // 使用綠色繪製圖形
    g.fill();                                       // 曲線之下的部分均填充
    g.fillText("貸款數額", 20,35);              // 文本顏色設置爲綠色

    // 再次循環,餘額數據顯示爲黑色粗線條
    var bal = principal;
    g.beginPath();
    g.moveTo(paymentToX(0),amountToY(bal));
    for(var p = 1; p <= payments; p++) {
        var thisMonthsInterest = bal*interest;
        bal -= (monthly - thisMonthsInterest);     // 獲得資產額
        g.lineTo(paymentToX(p),amountToY(bal));    // 將直線鏈接至某點
    }
    g.lineWidth = 3;                               // 將直線寬度加粗
    g.stroke();                                    // 繪製餘額的曲線
    g.fillStyle = "black";                         // 使用黑色字體
    g.fillText("貸款餘額", 20,50);             // 圖例文字

    // 將年度數據在X軸作標記
    g.textAlign="center";                             // 文字居中對齊
    var y = amountToY(0);                             // Y座標設爲0
    for(var year=1; year*12 <= payments; year++) {    // 遍歷每一年
        var x = paymentToX(year*12);                  // 計算標記位置
        g.fillRect(x-0.5,y-3,1,3);                    // 開始繪製標記
        if (year == 1) g.fillText("Year", x, y-5);    // 在座標軸作標記
        if (year % 5 == 0 && year*12 !== payments)    // 每5年的數據
        g.fillText(String(year), x, y-5);
    }

    // 將賠付數額標記在右邊界
    g.textAlign = "right";                        // 文字右對齊
    g.textBaseline = "middle";                    // 文字垂直居中
    var ticks = [monthly*payments, principal];    // 咱們將要用到的兩個點
    var rightEdge = paymentToX(payments);         // 設置X座標
    for(var i = 0; i < ticks.length; i++) {       // 對每兩個點作循環
        var y = amountToY(ticks[i]);              // 計算每一個標記的Y座標
        g.fillRect(rightEdge-3, y-0.5, 3,1);      // 繪製標記
        g.fillText(String(ticks[i].toFixed(0)),   // 繪製文本
        rightEdge-5, y);
    }
}
</script>
</body>
</html>
View Code

版本二:  canvas

<!DOCTYPE html>
<html>
<head>
<meta http-equiv=Content-Type content="text/html; charset=gb2312">
<meta charset="utf-8"/>
<title>JS計算器,貸款利率計算器</title>
<!--參考出處:http://www.codefans.net/jscss/code/3613.shtml-->

<style> /* 這是一個CSS樣式表:定義了程序輸出的樣式 */
body{ font-size:12px;}
#payment { } /* 定義 id="payment" 的元素樣式 */
#graph { border: solid black 1px; } /* 圖表有一個1像素的邊框 */
th, td {vertical-align: top; } /* 表格單元格對齊方式爲頂端對齊 */
table{
    border-collapse: collapse;
    border: none;
}
td, th{
    border: solid #000 1px;
}
.output { font-weight: bold; } /* 計算結果定義爲粗體 */
.btn{
    font-weight: 700;
    line-height: 30px;
    width: 100px;
    height: 35px;
}
.tbl{
    width:95%;
}
.td1{
    width:70px
}
.td2{
    width:140px
}
.help
{
    float:right;
    cursor:pointer;
    line-height: 10px;
    margin-top: -6px;
    margin-right: -6px;
}
.nr {
    color: #666;
    font-size: 12px;
    
    padding-top:0px;
    margin: 8px -2px -2px;
}
.tsk {
    background: #f8f8f8;
    border: 1px solid #CCC;
    box-shadow: 0 1px 5px #DDD;
    line-height: 20px;
    padding: 10px;
    position: absolute;
    display: none;
    z-index: 10000;
    width:215px;
    left:1px;
    top:16px
}

.circle {
    width: 15px;
    height: 15px;
    font-weight: 700;
    text-indent:4px;

        cursor:pointer;
    float:left;
    line-height:16px;
    background: #5A8BDC;
    -moz-border-radius: 50px;
    -webkit-border-radius: 50px;
    border-radius: 50px;
}
.resultInfo{
    font-weight:normal;
    font-size:10px;
    color:red;
}

</style>

<script>
    function $(id){ return document.getElementById(id); }
    function helpClick(obj)
    {
        $(obj.id+"_help").style.display = "block";
    }
    
    function hidHelp(obj)
    {
        obj.parentElement.style.display = "none";
    }
    
</script>

</head>
<body>

  <table width=500px>
   <tbody>
    <tr>
     <th colspan=2 style="text-align:left;font-size:24px;background-color:#3f3">輸入數據:</th>      
    </tr> 
    <tr>
     <td width=100px>
      <!--Amount of the loan-->貸款總金額:</td> 
     <td><input id="amount"  value="500000" /><span style="margin-left:-18px">元</span></td> 
    </tr> 
    <tr>
     <td>
      <!--Annual interest-->基準年利率:</td> 
     <td><input id="apr"  value="3.5" /><span style="margin-left:-14px">%</span></td>
    </tr> 
     <td>
      利率折扣:</td> 
     <td>
         <select id=llzk style="width:173px;">
               <option value="2.0" >基準利率2倍</option>
               <option value="1.5" >基準利率1.5倍</option>
               <option value="1.4" >基準利率1.4倍</option>
               <option value="1.3" >基準利率1.3倍</option>
               <option value="1.2" >基準利率1.2倍</option>
               <option value="1.1" >基準利率1.1倍</option>
               <option value="1.05">基準利率1.05倍</option>
               <option value="1.0" selected=true>基準利率</option>
               <option value="0.95">基準利率9.5折</option>
               <option value="0.9" >基準利率9折</option>
               <option value="0.88">基準利率8.8折</option>
               <option value="0.85">基準利率8.5折</option>
               <option value="0.83">基準利率8.3折</option>
               <option value="0.8" >基準利率8折</option>
               <option value="0.75" >基準利率7.5折</option>
              <option value="0.7" >基準利率7折</option>
            </select>
     </td>
    </tr> 
    <tr>
     <td>
      <!--Repayment period (years)-->貸款期限:</td> 
     <td><input id="years"  value="30" /><span style="margin-left:-18px">年</span></td>
    </tr>
    <tr style="display:none"> 
     <td>
      <!--Zipcode (to find lenders)-->郵政編碼(查找放貸人):</td> 
     <td><input id="zipcode"  /></td> 
    </tr>
    <tr> 
     <th colspan=2>
      <input class="btn" type=button onclick="calculate();" value="計 算" />&nbsp;&nbsp;
      <input class="btn" type=button onclick="RevCalculate();" value="反 推" />&nbsp;&nbsp;
      <input class="btn" type=reset value="重 置" />
     </th>
    </tr> 
    <tr>
      <th colspan=2 style="text-align:left;font-size:24px;background-color:#3f3">
      <!--Approximate Payments-->輸出結果:<span class="resultInfo">此結果僅供參考,實際應繳費以當地爲準</span>
      </th> 
    </tr>
    <tr>
     <td>
      <!--Monthly payment-->每個月付款:</td> 
     <td>
        <input id="payment"  value="30" />
     </td>
    </tr> 
    <tr>
     <td>
      <!--Total payment-->付款總額:</td> 
     <td><span class="output" id="total">0</span></td>
    </tr> 
    <tr>
     <td>
      <!--Total interest-->利息總額:</td> 
     <td><span class="output" id="totalinterest">0</span></td>
    </tr> 
    <tr>
        <td colspan="2">
      <table id="result" style="width:100%"> 
       <tbody>
        <tr> 
         <td style="position:relative;width:50%;"> 
          <div>
           <span style="float:left">每個月等額還款</span>
           <div class="circle" onclick="helpClick(this)" id="debxhk">?</div>
          </div>
          <div class="tsk" id="debxhk_help"> 
              <div onclick="hidHelp(this)" class="help">&nbsp;X</div>
           <div class="nr">
             每個月等額還款即等額本息還款法,指借款人每個月按相等的金額償還貸款本息,其中每個月貸款利息按月初剩餘貸款本金計算並逐月結清。 
           </div> 
          </div>
          <table style="clear:both" cellpadding="0" cellspacing="0" class="tbl"> 
           <tbody>
            <tr> 
             <td class="td1">貸款總額</td> 
             <td class="td2"><var id="_debx_dkze">0</var> 元</td> 
            </tr> 
            <tr> 
             <td class="td1">還款月數</td> 
             <td class="td2"><var id="_debx_hkys">0</var> 月</td> 
            </tr> 
            <tr> 
             <td class="td1">首月還款</td> 
             <td class="td2"><em id="_debx_syhk">0</em> 元</td> 
            </tr> 
            <tr>
                <td class="td1">每個月遞減</td>
                <td class="td1"><em id="_debj_mydj">0</em> 元</td>
            </tr>
            <tr> 
             <td class="td1">總付利息</td> 
             <td class="td2"><em id="_debx_zflx">0</em> 元</td> 
            </tr> 
            <tr> 
             <td class="td1">本息合計</td> 
             <td class="td2"><em id="_debx_bxhj">1,039,024.42</em> 元</td> 
            </tr> 
           </tbody>
          </table> 
          </td> 
         <td style="position:relative"> 
          <div>
           <span style="float:left">逐月遞減還款</span>
           <div onclick="helpClick(this)" class="circle" id="debjhk">?</div>
          </div> 
          <div class="tsk" id="debjhk_help"> 
              <div onclick="hidHelp(this)" class="help">&nbsp;X</div>
           <div class="nr">
             逐月遞減還款即等額本金還款法,指本金保持相同,利息逐月遞減,月還款數遞減;因爲每個月的還款本金額固定,而利息愈來愈少,貸款人起初還款壓力較大,可是隨時間的推移每個月還款數也愈來愈少。 
           </div> 
          </div> 
          <table style="clear:both" cellpadding="0" cellspacing="0" class="tbl"> 
           <tbody>
            <tr> 
             <td class="td1">貸款總額</td> 
             <td class="td2"><var id="_debj_dkze">0</var> 元</td> 
            </tr> 
            <tr> 
             <td class="td1">還款月數</td> 
             <td class="td2"><var id="_debj_hkys">0</var> 月</td> 
            </tr> 
            <tr> 
             <td class="td1">首月還款</td> 
             <td class="td2"><em id="_debj_syhk">0</em> 元
             </td> 
            </tr> 
            <tr>
                <td class="td1">每個月遞減</td>
                <td class="td1"><em id="_debj_mydj">0</em> 元</td>
            </tr>
            <tr> 
             <td class="td1">總付利息</td> 
             <td class="td2"><em id="_debj_zflx">0</em> 元</td> 
            </tr> 
            <tr> 
             <td class="td1">本息合計</td> 
             <td class="td2"><em id="_debj_bxhj">1,039,024.42</em> 元</td> 
            </tr> 
           </tbody>
          </table> </td> 
        </tr> 
        <tr style="display:none"> 
         <td colspan="2"> 
             <span class="resultInfo">此結果僅供參考,實際應繳費以當地爲準</span>
          </td> 
        </tr> 
       </tbody>
      </table> 
        </td>
    </tr>
    
    
    
    
    <tr>
     <td colspan=2><span style="font-weight:bold;">圖表:貸款金額,累計金額,利息支付</span></td>
    </tr> 
    <tr>
        <td colspan="2">
            <canvas id="graph" width="500" height="250"><span style="font-weight:bold;color:red;">請在支持HTML5的瀏覽器中打開</span></canvas>
        </td>
    </tr> 
   </tbody>
  </table>


<script>
function calculate() {
    // 查找文檔中用於輸入輸出的元素
    var amount = document.getElementById("amount");//貸款總額
    var apr = document.getElementById("apr");//年利息
    var years = document.getElementById("years");//償還期限
    var zipcode = document.getElementById("zipcode");//郵政編碼(查找放貸人)
    var payment = document.getElementById("payment");//月還貸款額
    var total = document.getElementById("total");//還貸款總額
    var totalinterest = document.getElementById("totalinterest");//貸款總利息

    // 假設全部的輸入都是合法的,將從input元素中獲取輸入數據
    // 將百分比格式轉換爲小數格式,並從年利率轉換爲月利率
    // 將年度賠付轉換爲月度賠付
    var principal = parseFloat(amount.value);
    var interest = parseFloat(apr.value) / 100 / 12;
    var payments = parseFloat(years.value) * 12;

    // 如今計算月度賠付的數據
    var x = Math.pow(1 + interest, payments); // Math.pow()進行冪次運算
    var monthly = (principal*x*interest)/(x-1);

    // 若是結果沒有超過JavaScript能表示的數字範圍,且用戶的輸入也正確
    // 這裏所展現的結果就是合法的
    if (isFinite(monthly)) {
        // 將數據填充至輸出字段的位置,四捨五入到小數點後兩位數字
        //payment.innerHTML = monthly.toFixed(2);
        payment.value=monthly.toFixed(2);
        total.innerHTML = (monthly * payments).toFixed(2);
        totalinterest.innerHTML = ((monthly*payments)-principal).toFixed(2);

        // 將用戶的輸入數據保存下來,這樣在下次訪問時也能取到數據
        save(amount.value, apr.value, years.value, zipcode.value);
        
        // 找到並展現本地放貸人,但忽略網絡錯誤
        try { // 捕獲這段代碼拋出的全部異常
            getLenders(amount.value, apr.value, years.value, zipcode.value);
        }
        catch(e) { /* 忽略這些異常 */ }
        
        // 最後,用圖表展現貸款餘額、利息和資產收益
        chart(principal, interest, monthly, payments);
    }
    else {
        // 計算結果不是數字或者是無窮大,意味着輸入數據是非法或不完整的
        // 清空以前的輸出數據
        payment.innerHTML = "";              // 清空元素的文本內容
        total.innerHTML = ""
        totalinterest.innerHTML = "";
        chart();                             // 不傳參數的話就是清除圖表
    }
}

// 將用戶的輸入保存至localStorage對象的屬性中
// 這些屬性在再次訪問時還會繼續保持在原位置
// 若是你在瀏覽器中按照file:// URL的方式直接打開本地文件,
// 則沒法在某些瀏覽器中使用存儲功能(好比FireFox)
// 而經過HTTP打開文件是可行的
function save(amount, apr, years, zipcode) {
    if (window.localStorage) { // 只有在瀏覽器支持的時候才運行這裏的代碼
        localStorage.loan_amount = amount;
        localStorage.loan_apr = apr;
        localStorage.loan_years = years;
        localStorage.loan_zipcode = zipcode;
    }
}

// 在文檔首次加載時,將會嘗試還原輸入字段
window.onload = function() {
    // 若是瀏覽器支持本地存儲而且上次保存的值是存在的
    if (window.localStorage && localStorage.loan_amount) {
        document.getElementById("amount").value = localStorage.loan_amount;
        document.getElementById("apr").value = localStorage.loan_apr;
        document.getElementById("years").value = localStorage.loan_years;
        document.getElementById("zipcode").value = localStorage.loan_zipcode;
    }
};

// 將用戶的輸入發送至服務器端腳本(理論上)將
// 返回一個本地放貸人的連接列表,在這個例子中並無實現這種查找放貸人的服務
// 但若是該服務存在,該函數會使用它
function getLenders(amount, apr, years, zipcode) {
    // 若是瀏覽器不支持XMLHttpRequest對象,則退出
    if (!window.XMLHttpRequest) return;

    // 找到要顯示放貸人列表的元素
    var ad = document.getElementById("lenders");
    if (!ad) return;                              // 若是返回爲空,則退出

    // 將用戶的輸入數據進行URL編碼,並做爲查詢參數附加在URL裏
    var url = "getLenders.php" +                  // 處理數據的URL地址
    "?amt=" + encodeURIComponent(amount) +        // 使用查詢串中的數據
        "&apr=" + encodeURIComponent(apr) +
        "&yrs=" + encodeURIComponent(years) +
        "&zip=" + encodeURIComponent(zipcode);

    // 經過XMLHttpRequest對象來提取返回數據
    var req = new XMLHttpRequest();               // 發起一個新的請求
    req.open("GET", url);                         // 經過URL發起一個HTTP GET請求
    req.send(null);                               // 不帶任何正文發送這個請求

    // 在返回數據以前,註冊了一個事件處理函數,這個處理函數
    // 將會在服務器的響應返回至客戶端的時候調用
    // 這種異步編程模式在客戶端JavaScript中是很是常見的
    req.onreadystatechange = function() {
        if (req.readyState == 4 && req.status == 200) {
            // 若是代碼運行到這裏,說明咱們獲得了一個合法且完整的HTTP響應
            var response = req.responseText;      // HTTP響應是以字符串的形式呈現的
            var lenders = JSON.parse(response);   // 將其解析爲JS數組

            // 將數組中的放貸人對象轉換爲HTML字符串形式
            var list = "";
            for(var i = 0; i < lenders.length; i++) {
                list += "<li><a href='" + lenders[i].url + "'>" +
                    lenders[i].name + "</a>";
            }

            // 將數據在HTML元素中呈現出來
            ad.innerHTML = "<ul>" + list + "</ul>";
        }
    }
}

// 在HTML<canvas>元素中用圖表展現月度貸款餘額、利息和資產收益
// 若是不傳入參數的話,則清空以前的圖表數據
// principal:貸款金額
// interest:利息
// monthly:每個月還款額
// payments:還款期限
function chart(principal, interest, monthly, payments) {
    var graph = document.getElementById("graph");   // 獲得<canvas>標籤
    graph.width = graph.width;                      // 用一種巧妙的手法清除並重置畫布
    
    // 若是不傳入參數,或者瀏覽器不支持畫布,則直接返回
    if (arguments.length == 0 || !graph.getContext) return;

    // 得到畫布元素的"context"對象,這個對象定義了一組繪畫API
    var g = graph.getContext("2d");                 // 全部的繪畫操做都將基於這個對象
    var width = graph.width, height = graph.height; // 得到畫布大小

    // 這裏的函數做用是將付款數字的數據轉換爲像素
    function paymentToX(n) { return n * width/payments; }
    function amountToY(a) { return height-(a * height/(monthly*payments*1.05));}

    // 總付款數據是一條從(0,0)到(payments, monthly*payments)的直線
    g.moveTo(paymentToX(0), amountToY(0));          // 從左下方開始
    g.lineTo(paymentToX(payments),amountToY(monthly*payments));// 繪至右上方
    g.lineTo(paymentToX(payments), amountToY(0));   // 再至右下方
    g.closePath();                                  // 將結尾鏈接至開頭
    g.fillStyle = "#f88";                           // 亮紅色
    g.fill();                                       // 填充矩形
    g.font = "bold 12px sans-serif";                // 定義一種字體
    g.fillText("總支出", 90,15);   // 將文字繪製到圖例中

    // 總貸款額的還款進度,不少資產數據並非線性的,很難將其反映至圖表中
    var equity = 0;
    g.beginPath();                                  // 開始繪製新圖形
    g.moveTo(paymentToX(0), amountToY(0));          // 從左下方開始
    for(var p = 1; p <= payments; p++) {            // 計算出每一筆賠付的利息
        var thisMonthsInterest = (principal-equity)*interest;
        equity += (monthly - thisMonthsInterest);   // 獲得資產額
        g.lineTo(paymentToX(p),amountToY(equity));  // 將數據繪製到畫布上
    }
    g.lineTo(paymentToX(payments), amountToY(0));   // 將數據線繪製至X軸
    g.closePath();                                  // 將線條結尾鏈接至線條開頭
    g.fillStyle = "#78E682";                        // 使用綠色繪製圖形
    g.fill();                                       // 曲線之下的部分均填充
    g.fillText("貸款數額", 90,30);                  // 文本顏色設置爲綠色

    // 餘額,再次循環,餘額數據顯示爲黑色粗線條
    var bal = principal;
    g.beginPath();
    g.moveTo(paymentToX(0),amountToY(bal));
    for(var p = 1; p <= payments; p++) {
        var thisMonthsInterest = bal*interest;
        bal -= (monthly - thisMonthsInterest);     // 獲得資產額
        g.lineTo(paymentToX(p),amountToY(bal));    // 將直線鏈接至某點
    }
    g.lineWidth = 2;                               // 將直線寬度加粗
    g.strokeStyle = "#E422CB";                       // 繪製線條的顏色
    g.stroke();                                    // 繪製餘額的曲線
    g.fillStyle = "#E422CB";                         // 使用黑色字體
    g.fillText("貸款餘額", 90,45);                 // 圖例文字

    // 將年度數據在X軸作標記
    g.fillStyle = "black";                              // 使用黑色字體
    g.textAlign="center";                             // 文字居中對齊
    var y = amountToY(0);                             // Y座標設爲0
    for(var year=1; year*12 <= payments; year++) {    // 遍歷每一年
        var x = paymentToX(year*12);                  // 計算標記位置
        g.fillRect(x-0.5,y-3,1,3);                    // 開始繪製標記
        if (year == 1) g.fillText("1年", x, y-5);    // 在座標軸作標記
        if (year % 5 == 0 && year*12 !== payments)    // 每5年的數據
        g.fillText(String(year)+"年", x, y-5);
    }

    // 將賠付數額標記在右邊界
    g.textAlign = "right";                                    // 文字右對齊
    g.textBaseline = "middle";                                // 文字垂直居中
    var ticks = [monthly*payments, principal];              // 咱們將要用到的兩個點
    var rightEdge = paymentToX(payments);                   // 設置X座標
    for(var i = 0; i < ticks.length; i++) {                 // 對每兩個點作循環
        var y = amountToY(ticks[i]);                           // 計算每一個標記的Y座標
        g.fillRect(rightEdge-3, y-0.5, 5,1);                 // 繪製標記
        g.fillText(String(ticks[i].toFixed(0)),rightEdge-5, y);    // 繪製文本
    }
    g.textAlign = "left";
    g.fillRect(0, y-0.5, 6,1);                      // 繪製標記
    g.fillText(String(principal),15, y);        // 繪製文本
}
</script>
</body>
</html>
View Code

 版本三:數組

<!DOCTYPE html>
<html>
<head>
<meta http-equiv=Content-Type content="text/html; charset=gb2312">
<meta charset="utf-8"/>
<title>JS計算器,貸款利率計算器</title>
<!--參考出處:http://www.codefans.net/jscss/code/3613.shtml-->

<style> /* 這是一個CSS樣式表:定義了程序輸出的樣式 */
body{ font-size:12px;}
#payment { } /* 定義 id="payment" 的元素樣式 */
#graph { border: solid black 1px; } /* 圖表有一個1像素的邊框 */
th, td {vertical-align: top; } /* 表格單元格對齊方式爲頂端對齊 */
table{
    border-collapse: collapse;
    border: none;
}
td, th{
    border: solid #000 1px;
}
.output { font-weight: bold; } /* 計算結果定義爲粗體 */
.btn{
    font-weight: 700;
    line-height: 30px;
    width: 100px;
    height: 35px;
}
.tbl{
    width:95%;
}
.td1{
    width:70px
}
.td2{
    width:140px
}
.help
{
    float:right;
    cursor:pointer;
    line-height: 10px;
    margin-top: -6px;
    margin-right: -6px;
}
.nr {
    color: #666;
    font-size: 12px;
    
    padding-top:0px;
    margin: 8px -2px -2px;
}
.tsk {
    background: #f8f8f8;
    border: 1px solid #CCC;
    box-shadow: 0 1px 5px #DDD;
    line-height: 20px;
    padding: 10px;
    position: absolute;
    display: none;
    z-index: 10000;
    width:215px;
    left:1px;
    top:16px
}

.circle {
    width: 15px;
    height: 15px;
    font-weight: 700;
    text-indent:4px;

        cursor:pointer;
    float:left;
    line-height:16px;
    background: #5A8BDC;
    -moz-border-radius: 50px;
    -webkit-border-radius: 50px;
    border-radius: 50px;
}
.resultInfo{
    font-weight:normal;
    font-size:10px;
    color:red;
}

</style>


<script language="JavaScript"> 
//格式化參數說明:
//y:年,M:月,d:日,k周,h:時,m分,s:秒,S毫秒
Date.prototype.Format = function(formatIn){
  var formatOut=formatIn;
  var o = {
  "M+" : this.getMonth()+1, //month
  "d+" : this.getDate(),    //day
  "h+" : this.getHours(),   //hour
  "m+" : this.getMinutes(), //minute
  "s+" : this.getSeconds(), //second
  "q+" : Math.floor((this.getMonth()+3)/3),  //quarter
  "k+" : Math.ceil((Math.ceil((this.valueOf()-new Date(this.getFullYear(),0,1).valueOf())/86400000)+((new Date(this.getFullYear(),0,1).getDay()+1)-1))/7)        //weeks
  }
  if(/(y+)/ig.test(formatIn))
  for(var i=0;i<(formatIn.match(/(y+)/ig)).length;i++){formatOut=formatOut.replace((formatIn.match(/(y+)/ig))[i],(this.getFullYear()+"").substr(4 - (formatIn.match(/(y+)/ig))[i].length));}
  for(var k in o){
      var reg=new RegExp("("+ k +")","g");
    if(reg.test(formatIn))var t=formatIn.match(reg);
    for(var i in t)formatOut=formatOut.replace(t[i],(o[k]+"").length==1?("0"+ o[k]).substr(t[i].length>2?-t[i].length:2-t[i].length):o[k]);
  }
  if(/(S+)/g.test(formatIn))
  formatOut=formatOut.replace(formatIn.match(/(S+)/g)[0],(this.getMilliseconds()+"").length<2?("00"+this.getMilliseconds()).substr(0,formatIn.match(/(S+)/g)[0].length):((this.getMilliseconds()+"").length==2?("0"+this.getMilliseconds()).substr(0,formatIn.match(/(S+)/g)[0].length):(this.getMilliseconds()+"").substr(0,formatIn.match(/(S+)/g)[0].length)));
  return formatOut;
}
//測試代碼    
var dt=new Date;
var f1="yyyy-MM-dd 第k周 hh:mm:ss.SS";
var f2="MM-dd kkk yy-M-d k h:m:s.S";
var f3="hh:mm:ss.SSSS";
//alert(dt.Format(f1));
//alert(dt.Format(f2));

;          
       

    function $(id){ return document.getElementById(id); }
    function helpClick(obj)
    {
        $(obj.id+"_help").style.display = "block";
    }
    
    function hidHelp(obj)
    {
        obj.parentElement.style.display = "none";
    }
    
    

function Test()
    {    
        var t1=document.createElement("table");
        t1.width="100%";
        t1.insertRow();
        t1.rows[0].innerHTML="<th width='10%'>期次</th><th>年月</th><th width='20%'>本金</th><th width='20%'>利息</th><th width='20%'>月供</th><th>剩餘貸款</th>";
        
        /*
        t1.insertRow();
        t1.rows[t1.rows.length-1].insertCell();
        t1.rows[t1.rows.length-1].insertCell();
        t1.rows[t1.rows.length-1].insertCell();
        t1.rows[t1.rows.length-1].cells[0].innerHTML = 1;
        t1.rows[t1.rows.length-1].cells[1].innerHTML = 2;
        t1.rows[t1.rows.length-1].cells[2].innerHTML = 3;
        */
        
        //t1.rows[t1.rows.length-1].insertCell()
        //tab.appendChild("<tr><td>1</td><td>2</td></tr>");
        //tab.appendChild(t1);
        
        //alert(newRow.cells.length);
        //div.appendChild(table); 
        //cell.innerHTML = '';
        //StringBuilder html = new StringBuilder("<table width='100%'>");   
        //document.getElementById('zhutiTable').appendChild(t); 

        
        
    // 查找文檔中用於輸入輸出的元素
    var amount = document.getElementById("amount");//貸款總額
    var apr = document.getElementById("apr");//年利息
    var years = document.getElementById("yearsToM");//償還期限
    var startYM = document.getElementById("startYM");//郵政編碼(查找放貸人)
    var payment = document.getElementById("payment");//月還貸款額
    var total = document.getElementById("total");//還貸款總額
    var totalinterest = document.getElementById("totalinterest");//貸款總利息

    // 假設全部的輸入都是合法的,將從input元素中獲取輸入數據
    // 將百分比格式轉換爲小數格式,並從年利率轉換爲月利率
    // 將年度賠付轉換爲月度賠付
    var principal = parseFloat(amount.value);
    var interest = parseFloat(apr.value) / 100 / 12;
    var payments = parseFloat(years.value) * 12;
    payments = years.value;

    // 如今計算月度賠付的數據
    var x = Math.pow(1 + interest, payments); // Math.pow()進行冪次運算
    var monthly = (principal*x*interest)/(x-1);
    
    
    
    //月還款額=貸款金額*年利率/12*(1+年利率/12)^(年期*12)/((1+年利率/12)^(年期*12)-1)
    var yue = principal*(interest)*x/(Math.pow(1+interest,payments)-1);
    var shy = principal;
    var dtt = new Date(startYM.value.split("-")[0],startYM.value.split("-")[1]-1,1)
    
    
    for(i=0;i<payments;i++){
        //第N月本金: 月還款額=(1+年利率/12)^(N-1-年期*12)
        var y_bj=Math.pow(interest+1,i-payments)
        //第N月利息: 月還款額=(1-(1+年利率/12)^(N-1-年期*12))
        var y_lx=1-Math.pow(1+interest,i-payments);
        t1.insertRow(t1.rows.length);
        t1.rows[t1.rows.length-1].insertCell();
        t1.rows[t1.rows.length-1].insertCell();
        t1.rows[t1.rows.length-1].insertCell();
        t1.rows[t1.rows.length-1].insertCell();
        t1.rows[t1.rows.length-1].insertCell();
        t1.rows[t1.rows.length-1].insertCell();
        t1.rows[t1.rows.length-1].cells[0].innerHTML = i+1;
        t1.rows[t1.rows.length-1].cells[1].innerHTML = dtt.Format("yyyy-MM");
        t1.rows[t1.rows.length-1].cells[2].innerHTML = (monthly*y_bj).toFixed(2);
        t1.rows[t1.rows.length-1].cells[3].innerHTML = (monthly*y_lx).toFixed(2);
        t1.rows[t1.rows.length-1].cells[4].innerHTML = monthly.toFixed(2);
        t1.rows[t1.rows.length-1].cells[5].innerHTML = (principal-=(monthly*y_bj)).toFixed(2);
        
        dtt = dtt.setMonth(dtt.getMonth()+1);
        dtt = new Date(dtt);
    }
    
    
    var tr=$("tr_tab");
    tr.cells[0].innerHTML=t1.outerHTML;    
        

    }
    
</script>

</head>
<body>

  <table id="t_main" width=500px>
   <tbody>
    <tr>
     <th colspan=2 style="text-align:left;font-size:24px;background-color:#3f3">輸入數據:</th>      
    </tr> 
    <tr>
     <td width=100px>
      <!--Amount of the loan-->貸款總金額:</td> 
     <td><input id="amount"  value="500000" /><span style="margin-left:-18px"></span></td> 
    </tr> 
    <tr>
     <td>
      <!--Annual interest-->基準年利率:</td> 
     <td><input id="apr"  value="3.5" /><span style="margin-left:-14px">%</span></td>
    </tr> 
     <td>
      利率折扣:</td> 
     <td>
         <select id=llzk style="width:173px;">
               <option value="2.0" >基準利率2倍</option>
               <option value="1.5" >基準利率1.5倍</option>
               <option value="1.4" >基準利率1.4倍</option>
               <option value="1.3" >基準利率1.3倍</option>
               <option value="1.2" >基準利率1.2倍</option>
               <option value="1.1" >基準利率1.1倍</option>
               <option value="1.05">基準利率1.05倍</option>
               <option value="1.0" selected=true>基準利率</option>
               <option value="0.95">基準利率9.5折</option>
               <option value="0.9" >基準利率9折</option>
               <option value="0.88">基準利率8.8折</option>
               <option value="0.85">基準利率8.5折</option>
               <option value="0.83">基準利率8.3折</option>
               <option value="0.8" >基準利率8折</option>
               <option value="0.75" >基準利率7.5折</option>
              <option value="0.7" >基準利率7折</option>
            </select>
     </td>
    </tr> 
    <tr>
     <td>
      <!--Repayment period (years)-->貸款期限:</td> 
     <td><input id="yearsToM"  value="180" /><span style="margin-left:-18px"></span></td>
    </tr>
    <tr> 
     <td>
      <!--Zipcode (to find lenders)-->首次還貸年月:</td> 
     <td><input id="startYM" value='2016-01' />
        <span id="lenders"></span>
     </td> 
    </tr>
    <tr> 
     <th colspan=2>
      <input class="btn" type=button onclick="calculate();" value="計 算" />&nbsp;&nbsp;
      <input class="btn" type=button onclick="Test();" value="測 試" />&nbsp;&nbsp;
      <input class="btn" type=reset value="重 置" />
     </th>
    </tr> 
    <tr>
      <th colspan=2 style="text-align:left;font-size:24px;background-color:#3f3">
      <!--Approximate Payments-->輸出結果:<span class="resultInfo">此結果僅供參考,實際應繳費以當地爲準</span>
      </th> 
    </tr>
    <tr>
     <td>
      <!--Monthly payment-->每個月付款:</td> 
     <td>
        <input id="payment"  value="30" />
     </td>
    </tr> 
    <tr>
     <td>
      <!--Total payment-->付款總額:</td> 
     <td><span class="output" id="total">0</span></td>
    </tr> 
    <tr>
     <td>
      <!--Total interest-->利息總額:</td> 
     <td><span class="output" id="totalinterest">0</span></td>
    </tr> 
    <tr>
        <td colspan="2">
      <table id="result" style="width:100%"> 
       <tbody>
        <tr> 
         <td style="position:relative;width:50%;"> 
          <div>
           <span style="float:left">每個月等額還款</span>
           <div class="circle" onclick="helpClick(this)" id="debxhk">?</div>
          </div>
          <div class="tsk" id="debxhk_help"> 
              <div onclick="hidHelp(this)" class="help">&nbsp;X</div>
           <div class="nr">
             每個月等額還款即等額本息還款法,指借款人每個月按相等的金額償還貸款本息,其中每個月貸款利息按月初剩餘貸款本金計算並逐月結清。 
           </div> 
          </div>
          <table style="clear:both" cellpadding="0" cellspacing="0" class="tbl"> 
           <tbody>
            <tr> 
             <td class="td1">貸款總額</td> 
             <td class="td2"><var id="_debx_dkze">0</var></td> 
            </tr> 
            <tr> 
             <td class="td1">還款月數</td> 
             <td class="td2"><var id="_debx_hkys">0</var></td> 
            </tr> 
            <tr> 
             <td class="td1">首月還款</td> 
             <td class="td2"><em id="_debx_syhk">0</em></td> 
            </tr> 
            <tr>
                <td class="td1">每個月遞減</td>
                <td class="td1"><em id="_debj_mydj">0</em></td>
            </tr>
            <tr> 
             <td class="td1">總付利息</td> 
             <td class="td2"><em id="_debx_zflx">0</em></td> 
            </tr> 
            <tr> 
             <td class="td1">本息合計</td> 
             <td class="td2"><em id="_debx_bxhj">1,039,024.42</em></td> 
            </tr> 
           </tbody>
          </table> 
          </td> 
         <td style="position:relative"> 
          <div>
           <span style="float:left">逐月遞減還款</span>
           <div onclick="helpClick(this)" class="circle" id="debjhk">?</div>
          </div> 
          <div class="tsk" id="debjhk_help"> 
              <div onclick="hidHelp(this)" class="help">&nbsp;X</div>
           <div class="nr">
             逐月遞減還款即等額本金還款法,指本金保持相同,利息逐月遞減,月還款數遞減;因爲每個月的還款本金額固定,而利息愈來愈少,貸款人起初還款壓力較大,可是隨時間的推移每個月還款數也愈來愈少。 
           </div> 
          </div> 
          <table style="clear:both" cellpadding="0" cellspacing="0" class="tbl"> 
           <tbody>
            <tr> 
             <td class="td1">貸款總額</td> 
             <td class="td2"><var id="_debj_dkze">0</var></td> 
            </tr> 
            <tr> 
             <td class="td1">還款月數</td> 
             <td class="td2"><var id="_debj_hkys">0</var></td> 
            </tr> 
            <tr> 
             <td class="td1">首月還款</td> 
             <td class="td2"><em id="_debj_syhk">0</em></td> 
            </tr> 
            <tr>
                <td class="td1">每個月遞減</td>
                <td class="td1"><em id="_debj_mydj">0</em></td>
            </tr>
            <tr> 
             <td class="td1">總付利息</td> 
             <td class="td2"><em id="_debj_zflx">0</em></td> 
            </tr> 
            <tr> 
             <td class="td1">本息合計</td> 
             <td class="td2"><em id="_debj_bxhj">1,039,024.42</em></td> 
            </tr> 
           </tbody>
          </table> </td> 
        </tr> 
        <tr style="display:none"> 
         <td colspan="2"> 
             <span class="resultInfo">此結果僅供參考,實際應繳費以當地爲準</span>
          </td> 
        </tr> 
       </tbody>
      </table> 
        </td>
    </tr>
    
    
    
    
    <tr>
     <td colspan=2><span style="font-weight:bold;">圖表:貸款金額,累計金額,利息支付</span></td>
    </tr> 
    <tr>
        <td colspan="2">
            <canvas id="graph" width="500" height="250"></canvas>
        </td>
    </tr> 
    <tr id="tr_tab">
        <td colspan="2">
        </td>
    </tr> 
   </tbody>
  </table>
<div id="list"></div>

<script>
function calculate() {

//生成每個月還款額表格
Test();

    // 查找文檔中用於輸入輸出的元素
    var amount = document.getElementById("amount");//貸款總額
    var apr = document.getElementById("apr");//年利息
    var years = document.getElementById("yearsToM");//償還期限
    var startYM = document.getElementById("startYM");//郵政編碼(查找放貸人)
    var payment = document.getElementById("payment");//月還貸款額
    var total = document.getElementById("total");//還貸款總額
    var totalinterest = document.getElementById("totalinterest");//貸款總利息

    // 假設全部的輸入都是合法的,將從input元素中獲取輸入數據
    // 將百分比格式轉換爲小數格式,並從年利率轉換爲月利率
    // 將年度賠付轉換爲月度賠付
    var principal = parseFloat(amount.value);
    var interest = parseFloat(apr.value) / 100 / 12;
    var payments = parseFloat(years.value) * 12;
    payments = years.value;

    // 如今計算月度賠付的數據
    var x = Math.pow(1 + interest, payments); // Math.pow()進行冪次運算
    var monthly = (principal*x*interest)/(x-1);
    
    
    
    //月還款額=貸款金額*年利率/12*(1+年利率/12)^(年期*12)/((1+年利率/12)^(年期*12)-1)
    var yue = principal*(interest)*x/(Math.pow(1+interest,payments)-1)
    //第N月本金: 月還款額=(1+年利率/12)^(N-1-年期*12)
    var y_bj=Math.pow(interest+1,-payments)
    //第N月利息: 月還款額=(1-(1+年利率/12)^(N-1-年期*12))
    var y_lx=1-Math.pow(1+interest,-payments)

    // 若是結果沒有超過JavaScript能表示的數字範圍,且用戶的輸入也正確
    // 這裏所展現的結果就是合法的
    if (isFinite(monthly)) {
        // 將數據填充至輸出字段的位置,四捨五入到小數點後兩位數字
        //payment.innerHTML = monthly.toFixed(2);
        payment.value=monthly.toFixed(2);
        total.innerHTML = (monthly * payments).toFixed(2);
        totalinterest.innerHTML = ((monthly*payments)-principal).toFixed(2);

        // 將用戶的輸入數據保存下來,這樣在下次訪問時也能取到數據
        save(amount.value, apr.value, years.value, startYM.value);
        
        // 找到並展現本地放貸人,但忽略網絡錯誤
        try { // 捕獲這段代碼拋出的全部異常
            //getLenders(amount.value, apr.value, years.value, startYM.value);
        }
        catch(e) { /* 忽略這些異常 */ }
        
        // 最後,用圖表展現貸款餘額、利息和資產收益
        chart(principal, interest, monthly, payments);
    }
    else {
        // 計算結果不是數字或者是無窮大,意味着輸入數據是非法或不完整的
        // 清空以前的輸出數據
        payment.innerHTML = "";              // 清空元素的文本內容
        total.innerHTML = ""
        totalinterest.innerHTML = "";
        chart();                             // 不傳參數的話就是清除圖表
    }
}

// 將用戶的輸入保存至localStorage對象的屬性中
// 這些屬性在再次訪問時還會繼續保持在原位置
// 若是你在瀏覽器中按照file:// URL的方式直接打開本地文件,
// 則沒法在某些瀏覽器中使用存儲功能(好比FireFox)
// 而經過HTTP打開文件是可行的
function save(amount, apr, years, zipcode) {
    if (window.localStorage) { // 只有在瀏覽器支持的時候才運行這裏的代碼
        localStorage.loan_amount = amount;
        localStorage.loan_apr = apr;
        localStorage.loan_years = years;
        localStorage.loan_zipcode = zipcode;
    }
}

// 在文檔首次加載時,將會嘗試還原輸入字段
window.onload = function() {
    // 若是瀏覽器支持本地存儲而且上次保存的值是存在的
    if (window.localStorage && localStorage.loan_amount) {
        document.getElementById("amount").value = localStorage.loan_amount;
        document.getElementById("apr").value = localStorage.loan_apr;
        document.getElementById("yearsToM").value = localStorage.loan_years;
        document.getElementById("startYM").value = localStorage.loan_zipcode;
    }
};

// 將用戶的輸入發送至服務器端腳本(理論上)將
// 返回一個本地放貸人的連接列表,在這個例子中並無實現這種查找放貸人的服務
// 但若是該服務存在,該函數會使用它
function getLenders(amount, apr, years, zipcode) {
    // 若是瀏覽器不支持XMLHttpRequest對象,則退出
    if (!window.XMLHttpRequest) return;

    // 找到要顯示放貸人列表的元素
    var ad = document.getElementById("lenders");
    if (!ad) return;                              // 若是返回爲空,則退出

    // 將用戶的輸入數據進行URL編碼,並做爲查詢參數附加在URL裏
    var url = "getLenders.php" +                  // 處理數據的URL地址
    "?amt=" + encodeURIComponent(amount) +        // 使用查詢串中的數據
        "&apr=" + encodeURIComponent(apr) +
        "&yrs=" + encodeURIComponent(years) +
        "&zip=" + encodeURIComponent(zipcode);

    // 經過XMLHttpRequest對象來提取返回數據
    var req = new XMLHttpRequest();               // 發起一個新的請求
    req.open("GET", url);                         // 經過URL發起一個HTTP GET請求
    req.send(null);                               // 不帶任何正文發送這個請求

    // 在返回數據以前,註冊了一個事件處理函數,這個處理函數
    // 將會在服務器的響應返回至客戶端的時候調用
    // 這種異步編程模式在客戶端JavaScript中是很是常見的
    req.onreadystatechange = function() {
        if (req.readyState == 4 && req.status == 200) {
            // 若是代碼運行到這裏,說明咱們獲得了一個合法且完整的HTTP響應
            var response = req.responseText;      // HTTP響應是以字符串的形式呈現的
            var lenders = JSON.parse(response);   // 將其解析爲JS數組

            // 將數組中的放貸人對象轉換爲HTML字符串形式
            var list = "";
            for(var i = 0; i < lenders.length; i++) {
                list += "<li><a href='" + lenders[i].url + "'>" +
                    lenders[i].name + "</a>";
            }

            // 將數據在HTML元素中呈現出來
            ad.innerHTML = "<ul>" + list + "</ul>";
        }
    }
}

// 在HTML<canvas>元素中用圖表展現月度貸款餘額、利息和資產收益
// 若是不傳入參數的話,則清空以前的圖表數據
// principal:貸款金額
// interest:利息
// monthly:每個月還款額
// payments:還款期限
function chart(principal, interest, monthly, payments) {
    var graph = document.getElementById("graph");   // 獲得<canvas>標籤
    graph.width = graph.width;                      // 用一種巧妙的手法清除並重置畫布
    
    // 若是不傳入參數,或者瀏覽器不支持畫布,則直接返回
    if (arguments.length == 0 || !graph.getContext) return;

    // 得到畫布元素的"context"對象,這個對象定義了一組繪畫API
    var g = graph.getContext("2d");                 // 全部的繪畫操做都將基於這個對象
    var width = graph.width, height = graph.height; // 得到畫布大小

    // 這裏的函數做用是將付款數字的數據轉換爲像素
    function paymentToX(n) { return n * width/payments; }
    function amountToY(a) { return height-(a * height/(monthly*payments*1.05));}

    // 總付款數據是一條從(0,0)到(payments, monthly*payments)的直線
    g.moveTo(paymentToX(0), amountToY(0));          // 從左下方開始
    g.lineTo(paymentToX(payments),amountToY(monthly*payments));// 繪至右上方
    g.lineTo(paymentToX(payments), amountToY(0));   // 再至右下方
    g.closePath();                                  // 將結尾鏈接至開頭
    g.fillStyle = "#f88";                           // 亮紅色
    g.fill();                                       // 填充矩形
    g.font = "bold 12px sans-serif";                // 定義一種字體
    g.fillText("總支出", 15,20);   // 將文字繪製到圖例中

    // 總貸款額的還款進度,不少資產數據並非線性的,很難將其反映至圖表中
    var equity = 0;
    g.beginPath();                                  // 開始繪製新圖形
    g.moveTo(paymentToX(0), amountToY(0));          // 從左下方開始
    for(var p = 1; p <= payments; p++) {            // 計算出每一筆賠付的利息
        var thisMonthsInterest = (principal-equity)*interest;
        equity += (monthly - thisMonthsInterest);   // 獲得資產額
        g.lineTo(paymentToX(p),amountToY(equity));  // 將數據繪製到畫布上
    }
    g.lineTo(paymentToX(payments), amountToY(0));   // 將數據線繪製至X軸
    g.closePath();                                  // 將線條結尾鏈接至線條開頭
    g.fillStyle = "#78E682";                     // 使用綠色繪製圖形
    g.fill();                                       // 曲線之下的部分均填充
    g.fillText("貸款數額", 60,20);                  // 文本顏色設置爲綠色

    // 餘額,再次循環,餘額數據顯示爲黑色粗線條
    var bal = principal;
    g.beginPath();
    g.moveTo(paymentToX(0),amountToY(bal));
    for(var p = 1; p <= payments; p++) {
        var thisMonthsInterest = bal*interest;
        bal -= (monthly - thisMonthsInterest);     // 獲得資產額
        g.lineTo(paymentToX(p),amountToY(bal));    // 將直線鏈接至某點
    }
    g.lineWidth = 2;                               // 將直線寬度加粗
    g.strokeStyle = "#e2e";                           // 繪製線條的顏色
    g.stroke();                                    // 繪製餘額的曲線
    g.fillStyle = "#e2e";                         // 使用黑色字體
    g.fillText("貸款餘額", 120,20);                 // 圖例文字

    // 將年度數據在X軸作標記
    g.fillStyle = "black";                         // 使用黑色字體
    g.textAlign="center";                             // 文字居中對齊
    var y = amountToY(0);                             // Y座標設爲0
    for(var year=1; year*12 <= payments; year++) {    // 遍歷每一年
        var x = paymentToX(year*12);                  // 計算標記位置
        g.fillRect(x-0.5,y-3,1,3);                    // 開始繪製標記
        if (year == 1) g.fillText("1年", x, y-5);    // 在座標軸作標記
        if (year % 5 == 0 && year*12 !== payments)    // 每5年的數據
        g.fillText(String(year)+"", x, y-5);
    }

    // 將賠付數額標記在右邊界
    g.textAlign = "right";                                    // 文字右對齊
    g.textBaseline = "middle";                                // 文字垂直居中
    var ticks = [monthly*payments, principal];   // 咱們將要用到的兩個點
    var rightEdge = paymentToX(payments);                   // 設置X座標
    for(var i = 0; i < ticks.length; i++) {                 // 對每兩個點作循環
        var y = amountToY(ticks[i]);                           // 計算每一個標記的Y座標
        g.fillRect(rightEdge-3, y-0.5, 5,1);                 // 繪製標記
        g.fillText(String(ticks[i].toFixed(0)),rightEdge-5, y);    // 繪製文本
    }
    g.textAlign = "left";
    g.fillRect(0, y-0.5, 6,1);                      // 繪製標記
    g.fillText(String(principal),15, y);        // 繪製文本
}

</script>

</body>
</html>
View Code

 

 

 

 

出處參考:瀏覽器

http://www.codefans.net/jscss/code/3613.shtml服務器

http://www.rong360.com/calculator/fangdai.html網絡

相關文章
相關標籤/搜索