基于javascript實現的貸款計算器

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>基于JavaScript實現的貸款計算器</title>
    <style>
      /*這是一個css樣式表:定義看程序輸出的樣式*/
        .output {font-weight: bold;}
        #payment {text-decoration: underline;}
        #graph{border: solid black 1px}
        th ,td {
            vertical-align: top;
        }
    </style>
</head>
<body>
<table>
    <tr>
        <th>
            輸入貸款數據:
        </th>
        <td></td>
        <th>貸款余額减拭,累計權益和利息支付</th>
    </tr>
    <tr>
        <td>貸款額($):</td>
        <!--onchange 事件會在域的內容改變時發(fā)生抖部。-->
        <td><input id="amount" onchange="calculate()"></td>
        <!--rowspan 屬性規(guī)定單元格可橫跨的行數。-->
        <td rowspan="8">
            <canvas id="graph" width="400" height="250"></canvas>
        </td>
    </tr>
    <tr>
        <td>年利(%):</td>
        <td><input id="apr" onchange="calculate()"></td>
    </tr>
    <tr>
        <td>還款期限(年):</td>
        <td><input id="years" onchange="calculate()"></td>
    </tr>
    <tr>
        <td>郵編(找到貸方):</td>
        <td><input id="zipcode" onchange="calculate()"></td>
    </tr>
    <tr>
        <th>近似付款:</th>
        <td>
            <button onclick="calculate()">計算</button>
        </td>
    </tr>
    <tr>
        <td>每月支付:</td>
        <td>$<span class="output" id="payment"></span></td>
    </tr>
    <tr>
        <td>總付款:</td>
        <td>$<samp class="output" id="total"></samp></td>
    </tr>
    <tr>
        <td>總利息:</td>
        <td>$<span class="output" id="totalinterset"></span></td>
    </tr>
    <tr>
        <td>贊助商:</td>
        <td colspan="2">
            向這些優(yōu)良貸款人申請貸款:
            <div id="lenders"></div>
        </td>
    </tr>
</table>
<script>
    "use strict";       //如果瀏覽器支持的話,則開始ECMAScript5的嚴格模式

    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 totalinterset = document.getElementById("totalinterset");

        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);//進行冪運算
        var monthly = (principal * x * interest) / (x - 1);
        // isFinite() 函數用于檢查其參數是否是無窮大膀斋。
        if (isFinite(monthly)) {
            //將數據填充至輸出字段的位置磕昼,四舍五入到小數點后兩位數字
            payment.innerHTML = monthly.toFixed(2);  //toFixed() 方法可把 Number 四舍五入為指定小數位數的數字俺驶。
            total.innerHTML = (monthly * payments).toFixed(2);
            totalinterset.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 = "";
            totalinterset.innerHTML = "";
            chart();
        }

    }

    //將用戶的輸入保存至localStorage對象的屬性中
    //這些屬性在再次訪問時還會繼續(xù)保持在原位置
    //如果你在瀏覽器中按照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;
        }
    }

    //將用戶的輸入發(fā)送至服務器端腳本將返回一個本地放貸人的連接列表,
    //但是我們這個例子沒有實現這種查找放貸人的服務
    //如果該服務存在剑令,該函數會使用它
    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();     //發(fā)起一個新的請求
        req.open("GET", url);    //通過url發(fā)起一個HTTP GET請求
        req.send(null);         //不帶任何正文發(fā)送這個請求

        //在返回數據之前棚蓄,注冊了一個事件處理函數堕扶,這個處理函數將會在服務器的響應
        //返回至客戶端的時候調用,這種異步編程模型在客戶端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></li>"
                }

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

    //在HTML<canvas>元素中用圖表展示月度貸款余額稍算,利息和資產收益
    //如果不傳入參宿的話,則清空之前的圖表數據
    function chart(principal, interest, monthly, payments) {
        var graph = document.getElementById("graph"); //得到<canvas>
        graph.width = graph.width;  //用一種巧妙的手法清楚并重置畫布

        //獲取畫布元素的"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);    //將文字回執(zhí)到圖例中

        //很多資產數據并不是線性的糊探,很難將其反應至圖表中
        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 = "green";      //使用綠色繪制圖形
        g.fill();
        g.fillText("總資產", 20, 35);
        /*文本設置為綠色*/


        //再次循環(huán),余額數據顯示為黑色粗體線條
        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("正確", x, y - 5);
            if (year % 5 == 0 && year * 12 !== payments) {
                g.fillText(String(year), x, y - 5);
            }
            g.textAlign = "right";              //文字右對齊
            g.textBaseline = "middle";          //文字垂直居中
            var ticks = [monthly * payments, payments];
            var rightEde = paymentToX(payments);
            for (var i = 0; i < ticks.length; i++) {
                var y = amountToY(ticks[i]);
                g.fillRect(rightEde - 3, y - 0.5, 3, 1);
                g.fillText(String(ticks[i].toFixed(0)), rightEde - 5, y);
            }
        }
    }


</script>
</body>
</html>
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末河闰,一起剝皮案震驚了整個濱河市科平,隨后出現的幾起案子,更是在濱河造成了極大的恐慌姜性,老刑警劉巖瞪慧,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異部念,居然都是意外死亡弃酌,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門儡炼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來妓湘,“玉大人,你說我怎么就攤上這事乌询“裉” “怎么了?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵楣责,是天一觀的道長竣灌。 經常有香客問我,道長秆麸,這世上最難降的妖魔是什么初嘹? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮沮趣,結果婚禮上屯烦,老公的妹妹穿的比我還像新娘。我一直安慰自己房铭,他們只是感情好驻龟,可當我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著缸匪,像睡著了一般翁狐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上凌蔬,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天露懒,我揣著相機與錄音闯冷,去河邊找鬼。 笑死懈词,一個胖子當著我的面吹牛蛇耀,可吹牛的內容都是我干的。 我是一名探鬼主播坎弯,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼纺涤,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了抠忘?” 一聲冷哼從身側響起撩炊,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎崎脉,沒想到半個月后衰抑,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡荧嵌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了砾淌。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片啦撮。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖汪厨,靈堂內的尸體忽然破棺而出赃春,到底是詐尸還是另有隱情,我是刑警寧澤劫乱,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布织中,位于F島的核電站,受9級特大地震影響衷戈,放射性物質發(fā)生泄漏狭吼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一殖妇、第九天 我趴在偏房一處隱蔽的房頂上張望刁笙。 院中可真熱鬧,春花似錦谦趣、人聲如沸疲吸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽摘悴。三九已至,卻和暖如春舰绘,著一層夾襖步出監(jiān)牢的瞬間蹂喻,已是汗流浹背葱椭。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留叉橱,地道東北人挫以。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像窃祝,于是被迫代替她去往敵國和親掐松。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內容